Version 2.1 #41
@ -367,6 +367,25 @@ module Map =
|
||||
LastSeenOn = tryInstant "last_seen_on" rdr
|
||||
}
|
||||
|
||||
/// Map from a document to a domain type, specifying the field name for the document
|
||||
let fromData<'T> ser rdr fieldName : 'T =
|
||||
Utils.deserialize<'T> ser (getString fieldName rdr)
|
||||
|
||||
/// Map from a document to a domain type
|
||||
let fromDoc<'T> ser rdr : 'T =
|
||||
fromData<'T> ser rdr "data"
|
||||
|
||||
/// Queries to assist with document manipulation
|
||||
module Query =
|
||||
|
||||
/// Fragment to add an ID condition to a WHERE clause
|
||||
let whereById =
|
||||
"data ->> 'Id' = @id"
|
||||
|
||||
/// Fragment to add a web log ID condition to a WHERE clause
|
||||
let whereWebLogId =
|
||||
"data ->> 'WebLogId' = @webLogId"
|
||||
|
||||
/// Add a web log ID parameter
|
||||
let addWebLogId (cmd: SqliteCommand) (webLogId: WebLogId) =
|
||||
cmd.Parameters.AddWithValue("@webLogId", string webLogId) |> ignore
|
||||
|
@ -4,9 +4,10 @@ open System.Threading.Tasks
|
||||
open Microsoft.Data.Sqlite
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open Newtonsoft.Json
|
||||
|
||||
/// SQLite myWebLog category data implementation
|
||||
type SQLiteCategoryData(conn: SqliteConnection) =
|
||||
type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer) =
|
||||
|
||||
/// Add parameters for category INSERT or UPDATE statements
|
||||
let addCategoryParameters (cmd: SqliteCommand) (cat: Category) =
|
||||
@ -35,7 +36,7 @@ type SQLiteCategoryData(conn: SqliteConnection) =
|
||||
/// Count all categories for the given web log
|
||||
let countAll webLogId = backgroundTask {
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- "SELECT COUNT(id) FROM category WHERE web_log_id = @webLogId"
|
||||
cmd.CommandText <- $"SELECT COUNT(*) FROM {Table.Category} WHERE {whereWebLogId}"
|
||||
addWebLogId cmd webLogId
|
||||
return! count cmd
|
||||
}
|
||||
@ -44,23 +45,25 @@ type SQLiteCategoryData(conn: SqliteConnection) =
|
||||
let countTopLevel webLogId = backgroundTask {
|
||||
use cmd = conn.CreateCommand ()
|
||||
cmd.CommandText <-
|
||||
"SELECT COUNT(id) FROM category WHERE web_log_id = @webLogId AND parent_id IS NULL"
|
||||
$"SELECT COUNT(*) FROM {Table.Category}
|
||||
WHERE {whereWebLogId} AND data ->> '{nameof Category.Empty.ParentId}' IS NULL"
|
||||
addWebLogId cmd webLogId
|
||||
return! count cmd
|
||||
}
|
||||
|
||||
// TODO: need to get SQLite in clause format for JSON documents
|
||||
/// Retrieve all categories for the given web log in a DotLiquid-friendly format
|
||||
let findAllForView webLogId = backgroundTask {
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- "SELECT * FROM category WHERE web_log_id = @webLogId"
|
||||
cmd.CommandText <- $"SELECT data FROM {Table.Category} WHERE {whereWebLogId}"
|
||||
addWebLogId cmd webLogId
|
||||
use! rdr = cmd.ExecuteReaderAsync()
|
||||
let cats =
|
||||
seq {
|
||||
while rdr.Read() do
|
||||
Map.toCategory rdr
|
||||
Map.fromDoc<Category> ser rdr
|
||||
}
|
||||
|> Seq.sortBy (fun cat -> cat.Name.ToLowerInvariant ())
|
||||
|> Seq.sortBy _.Name.ToLowerInvariant()
|
||||
|> List.ofSeq
|
||||
do! rdr.CloseAsync()
|
||||
let ordered = Utils.orderByHierarchy cats None None []
|
||||
@ -71,7 +74,7 @@ type SQLiteCategoryData(conn: SqliteConnection) =
|
||||
let catSql, catParams =
|
||||
ordered
|
||||
|> Seq.filter (fun cat -> cat.ParentNames |> Array.contains it.Name)
|
||||
|> Seq.map (fun cat -> cat.Id)
|
||||
|> Seq.map _.Id
|
||||
|> Seq.append (Seq.singleton it.Id)
|
||||
|> List.ofSeq
|
||||
|> inClause "AND pc.category_id" "catId" id
|
||||
@ -103,12 +106,12 @@ type SQLiteCategoryData(conn: SqliteConnection) =
|
||||
/// Find a category by its ID for the given web log
|
||||
let findById (catId: CategoryId) webLogId = backgroundTask {
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- "SELECT * FROM category WHERE id = @id"
|
||||
cmd.CommandText <- $"SELECT * FROM {Table.Category} WHERE {Query.whereById}"
|
||||
cmd.Parameters.AddWithValue("@id", string catId) |> ignore
|
||||
use! rdr = cmd.ExecuteReaderAsync()
|
||||
return verifyWebLog<Category> webLogId (_.WebLogId) Map.toCategory rdr
|
||||
return verifyWebLog<Category> webLogId (_.WebLogId) (Map.fromDoc ser) rdr
|
||||
}
|
||||
|
||||
// TODO: stopped here
|
||||
/// Find all categories for the given web log
|
||||
let findByWebLog (webLogId: WebLogId) = backgroundTask {
|
||||
use cmd = conn.CreateCommand ()
|
||||
|
@ -18,47 +18,46 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
cmd.CommandText <- "SELECT name FROM sqlite_master WHERE type = 'table'"
|
||||
let! rdr = cmd.ExecuteReaderAsync()
|
||||
let mutable tableList = []
|
||||
while rdr.Read() do
|
||||
while! rdr.ReadAsync() do
|
||||
tableList <- Map.getString "name" rdr :: tableList
|
||||
do! rdr.CloseAsync()
|
||||
return tableList
|
||||
}
|
||||
|
||||
let needsTable table =
|
||||
not (List.contains table tables)
|
||||
|
||||
let jsonTable table =
|
||||
$"CREATE TABLE {table} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{table}_key ON {table} (data ->> 'Id')"
|
||||
|
||||
seq {
|
||||
// Theme tables
|
||||
if needsTable Table.Theme then
|
||||
$"CREATE TABLE {Table.Theme} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.Theme}_key ON {Table.Theme} (data ->> 'Id')";
|
||||
if needsTable "theme_asset" then
|
||||
"CREATE TABLE theme_asset (
|
||||
theme_id TEXT NOT NULL REFERENCES theme (id),
|
||||
if needsTable Table.Theme then jsonTable Table.Theme
|
||||
if needsTable Table.ThemeAsset then
|
||||
$"CREATE TABLE {Table.ThemeAsset} (
|
||||
theme_id TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
updated_on TEXT NOT NULL,
|
||||
data BLOB NOT NULL,
|
||||
PRIMARY KEY (theme_id, path))"
|
||||
|
||||
// Web log table
|
||||
if needsTable Table.WebLog then
|
||||
$"CREATE TABLE {Table.WebLog} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.WebLog}_key ON {Table.WebLog} (data ->> 'Id')"
|
||||
if needsTable Table.WebLog then jsonTable Table.WebLog
|
||||
|
||||
// Category table
|
||||
if needsTable Table.Category then
|
||||
$"CREATE TABLE {Table.Category} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.Category}_key ON {Table.Category} (data -> 'Id');
|
||||
$"{jsonTable Table.Category};
|
||||
CREATE INDEX idx_{Table.Category}_web_log ON {Table.Category} (data ->> 'WebLogId')"
|
||||
|
||||
// Web log user table
|
||||
if needsTable Table.WebLogUser then
|
||||
$"CREATE TABLE web_log_user (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.WebLogUser}_key ON {Table.WebLogUser} (data ->> 'Id');
|
||||
$"{jsonTable Table.WebLogUser};
|
||||
CREATE INDEX idx_{Table.WebLogUser}_email ON {Table.WebLogUser} (data ->> 'WebLogId', data ->> 'Email')"
|
||||
|
||||
// Page tables
|
||||
if needsTable Table.Page then
|
||||
$"CREATE TABLE {Table.Page} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.Page}_key ON {Table.Page} (data ->> 'Id');
|
||||
$"{jsonTable Table.Page};
|
||||
CREATE INDEX idx_{Table.Page}_author ON {Table.Page} (data ->> 'AuthorId');
|
||||
CREATE INDEX idx_{Table.Page}_permalink ON {Table.Page} (data ->> 'WebLogId', data ->> 'Permalink')"
|
||||
if needsTable Table.PageRevision then
|
||||
@ -70,8 +69,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
|
||||
// Post tables
|
||||
if needsTable Table.Post then
|
||||
$"CREATE TABLE {Table.Post} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.Post}_key ON {Table.Post} (data ->> 'Id');
|
||||
$"{jsonTable Table.Post};
|
||||
CREATE INDEX idx_{Table.Post}_author ON {Table.Post} (data ->> 'AuthorId');
|
||||
CREATE INDEX idx_{Table.Post}_status ON {Table.Post} (data ->> 'WebLogId', data ->> 'Status', data ->> 'UpdatedOn');
|
||||
CREATE INDEX idx_{Table.Post}_permalink ON {Table.Post} (data ->> 'WebLogId', data ->> 'Permalink')"
|
||||
@ -83,22 +81,12 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
revision_text TEXT NOT NULL,
|
||||
PRIMARY KEY (post_id, as_of))"
|
||||
if needsTable Table.PostComment then
|
||||
$"CREATE TABLE {Table.PostComment} (
|
||||
id TEXT PRIMARY KEY,
|
||||
post_id TEXT NOT NULL,
|
||||
in_reply_to_id TEXT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
url TEXT,
|
||||
status TEXT NOT NULL,
|
||||
posted_on TEXT NOT NULL,
|
||||
comment_text TEXT NOT NULL);
|
||||
CREATE INDEX idx_{Table.PostComment}_post ON {Table.PostComment} (post_id)"
|
||||
$"{jsonTable Table.PostComment};
|
||||
CREATE INDEX idx_{Table.PostComment}_post ON {Table.PostComment} (data ->> 'PostId')"
|
||||
|
||||
// Tag map table
|
||||
if needsTable Table.TagMap then
|
||||
$"CREATE TABLE {Table.TagMap} (data TEXT NOT NULL);
|
||||
CREATE UNIQUE INDEX idx_{Table.TagMap}_key ON {Table.TagMap} (data ->> 'Id');
|
||||
$"{jsonTable Table.TagMap};
|
||||
CREATE INDEX idx_{Table.TagMap}_tag ON {Table.TagMap} (data ->> 'WebLogId', data ->> 'UrlValue')";
|
||||
|
||||
// Uploaded file table
|
||||
@ -195,8 +183,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
FundingUrl = Map.tryString "funding_url" podcastRdr
|
||||
FundingText = Map.tryString "funding_text" podcastRdr
|
||||
Medium = Map.tryString "medium" podcastRdr
|
||||
|> Option.map PodcastMedium.Parse
|
||||
}
|
||||
|> Option.map PodcastMedium.Parse }
|
||||
} |> List.ofSeq
|
||||
podcastRdr.Close()
|
||||
podcasts
|
||||
@ -233,8 +220,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
SeasonDescription = Map.tryString "season_description" epRdr
|
||||
EpisodeNumber = Map.tryString "episode_number" epRdr
|
||||
|> Option.map System.Double.Parse
|
||||
EpisodeDescription = Map.tryString "episode_description" epRdr
|
||||
}
|
||||
EpisodeDescription = Map.tryString "episode_description" epRdr }
|
||||
} |> List.ofSeq
|
||||
epRdr.Close()
|
||||
episodes
|
||||
@ -263,8 +249,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
cmd.CommandText <- "UPDATE page SET updated_on = @updatedOn, published_on = @publishedOn WHERE id = @id"
|
||||
[ cmd.Parameters.Add("@id", SqliteType.Text)
|
||||
cmd.Parameters.Add("@updatedOn", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@publishedOn", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@publishedOn", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (pageId, updatedOn, publishedOn) ->
|
||||
cmd.Parameters["@id" ].Value <- pageId
|
||||
@ -289,8 +274,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
[ cmd.Parameters.Add("@pageId", SqliteType.Text)
|
||||
cmd.Parameters.Add("@oldAsOf", SqliteType.Text)
|
||||
cmd.Parameters.Add("@asOf", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@text", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@text", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (pageId, oldAsOf, asOf, text) ->
|
||||
cmd.Parameters["@pageId" ].Value <- pageId
|
||||
@ -314,8 +298,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
cmd.CommandText <- "UPDATE post SET updated_on = @updatedOn, published_on = @publishedOn WHERE id = @id"
|
||||
[ cmd.Parameters.Add("@id", SqliteType.Text)
|
||||
cmd.Parameters.Add("@updatedOn", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@publishedOn", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@publishedOn", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (postId, updatedOn, publishedOn) ->
|
||||
cmd.Parameters["@id" ].Value <- postId
|
||||
@ -340,8 +323,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
[ cmd.Parameters.Add("@postId", SqliteType.Text)
|
||||
cmd.Parameters.Add("@oldAsOf", SqliteType.Text)
|
||||
cmd.Parameters.Add("@asOf", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@text", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@text", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (postId, oldAsOf, asOf, text) ->
|
||||
cmd.Parameters["@postId" ].Value <- postId
|
||||
@ -364,8 +346,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
cmd.CommandText <- "UPDATE theme_asset SET updated_on = @updatedOn WHERE theme_id = @themeId AND path = @path"
|
||||
[ cmd.Parameters.Add("@updatedOn", SqliteType.Text)
|
||||
cmd.Parameters.Add("@themeId", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@path", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@path", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (themeId, path, updatedOn) ->
|
||||
cmd.Parameters["@themeId" ].Value <- themeId
|
||||
@ -385,8 +366,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
upRdr.Close ()
|
||||
cmd.CommandText <- "UPDATE upload SET updated_on = @updatedOn WHERE id = @id"
|
||||
[ cmd.Parameters.Add("@updatedOn", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@id", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@id", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (upId, updatedOn) ->
|
||||
cmd.Parameters["@id" ].Value <- upId
|
||||
@ -408,8 +388,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
cmd.CommandText <- "UPDATE web_log_user SET created_on = @createdOn, last_seen_on = @lastSeenOn WHERE id = @id"
|
||||
[ cmd.Parameters.Add("@id", SqliteType.Text)
|
||||
cmd.Parameters.Add("@createdOn", SqliteType.Text)
|
||||
cmd.Parameters.Add ("@lastSeenOn", SqliteType.Text)
|
||||
] |> ignore
|
||||
cmd.Parameters.Add("@lastSeenOn", SqliteType.Text) ] |> ignore
|
||||
toUpdate
|
||||
|> List.iter (fun (userId, createdOn, lastSeenOn) ->
|
||||
cmd.Parameters["@id" ].Value <- userId
|
||||
@ -487,7 +466,7 @@ type SQLiteData (conn : SqliteConnection, log : ILogger<SQLiteData>, ser : JsonS
|
||||
|
||||
interface IData with
|
||||
|
||||
member _.Category = SQLiteCategoryData conn
|
||||
member _.Category = SQLiteCategoryData (conn, ser)
|
||||
member _.Page = SQLitePageData (conn, ser)
|
||||
member _.Post = SQLitePostData (conn, ser)
|
||||
member _.TagMap = SQLiteTagMapData conn
|
||||
|
Loading…
Reference in New Issue
Block a user