diff --git a/src/MyWebLog.Data/MyWebLog.Data.fsproj b/src/MyWebLog.Data/MyWebLog.Data.fsproj
index cb6c042..03014eb 100644
--- a/src/MyWebLog.Data/MyWebLog.Data.fsproj
+++ b/src/MyWebLog.Data/MyWebLog.Data.fsproj
@@ -5,9 +5,9 @@
-
-
-
+
+
+
@@ -15,7 +15,7 @@
-
+
diff --git a/src/MyWebLog.Data/Postgres/PostgresHelpers.fs b/src/MyWebLog.Data/Postgres/PostgresHelpers.fs
index 1e2b483..c14610c 100644
--- a/src/MyWebLog.Data/Postgres/PostgresHelpers.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresHelpers.fs
@@ -83,7 +83,7 @@ let webLogContains webLogId =
/// A SQL string to select data from a table with the given JSON document contains criteria
let selectWithCriteria tableName =
- $"""{Query.find tableName} WHERE {Query.whereDataContains "@criteria"}"""
+ Query.byContains (Query.find tableName)
/// Create the SQL and parameters for an IN clause
let inClause<'T> colNameAndPrefix paramName (items: 'T list) =
diff --git a/src/MyWebLog.Data/Postgres/PostgresPageData.fs b/src/MyWebLog.Data/Postgres/PostgresPageData.fs
index d14da27..ba757e4 100644
--- a/src/MyWebLog.Data/Postgres/PostgresPageData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresPageData.fs
@@ -33,6 +33,10 @@ type PostgresPageData(log: ILogger) =
log.LogTrace "Page.pageExists"
Document.existsByWebLog Table.Page pageId webLogId
+ /// The query to get all pages ordered by title
+ let sortedPages =
+ selectWithCriteria Table.Page + Query.orderBy [ Field.Named $"i:{nameof Page.Empty.Title}" ] PostgreSQL
+
// IMPLEMENTATION FUNCTIONS
/// Add a page
@@ -47,7 +51,7 @@ type PostgresPageData(log: ILogger) =
let all webLogId =
log.LogTrace "Page.all"
Custom.list
- $"{selectWithCriteria Table.Page} ORDER BY LOWER(data->>'{nameof Page.Empty.Title}')"
+ sortedPages
[ webLogContains webLogId ]
(fun row -> { fromData row with Text = ""; Metadata = []; PriorPermalinks = [] })
@@ -133,17 +137,13 @@ type PostgresPageData(log: ILogger) =
let findListed webLogId =
log.LogTrace "Page.findListed"
Custom.list
- $"{selectWithCriteria Table.Page} ORDER BY LOWER(data->>'{nameof Page.Empty.Title}')"
- [ jsonParam "@criteria" {| webLogDoc webLogId with IsInPageList = true |} ]
- pageWithoutText
+ sortedPages [ jsonParam "@criteria" {| webLogDoc webLogId with IsInPageList = true |} ] pageWithoutText
/// Get a page of pages for the given web log (without revisions)
let findPageOfPages webLogId pageNbr =
log.LogTrace "Page.findPageOfPages"
Custom.list
- $"{selectWithCriteria Table.Page}
- ORDER BY LOWER(data->>'{nameof Page.Empty.Title}')
- LIMIT @pageSize OFFSET @toSkip"
+ $"{sortedPages} LIMIT @pageSize OFFSET @toSkip"
[ webLogContains webLogId; "@pageSize", Sql.int 26; "@toSkip", Sql.int ((pageNbr - 1) * 25) ]
(fun row -> { fromData row with Metadata = []; PriorPermalinks = [] })
diff --git a/src/MyWebLog.Data/Postgres/PostgresPostData.fs b/src/MyWebLog.Data/Postgres/PostgresPostData.fs
index b986280..c12f0e9 100644
--- a/src/MyWebLog.Data/Postgres/PostgresPostData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresPostData.fs
@@ -124,21 +124,24 @@ type PostgresPostData(log: ILogger) =
log.LogTrace "Post.findPageOfCategorizedPosts"
let catSql, catParam = arrayContains (nameof Post.Empty.CategoryIds) string categoryIds
Custom.list
- $"{selectWithCriteria Table.Post}
- AND {catSql}
- ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"""{selectWithCriteria Table.Post}
+ AND {catSql}
+ {Query.orderBy [ Field.Named $"{nameof Post.Empty.PublishedOn} DESC" ] PostgreSQL}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"""
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}; catParam ]
postWithoutLinks
/// Get a page of posts for the given web log (excludes text and revisions)
let findPageOfPosts webLogId pageNbr postsPerPage =
log.LogTrace "Post.findPageOfPosts"
+ let order =
+ Query.orderBy
+ [ Field.Named $"{nameof Post.Empty.PublishedOn} DESC NULLS FIRST"
+ Field.Named (nameof Post.Empty.UpdatedOn) ]
+ PostgreSQL
Custom.list
- $"{selectWithCriteria Table.Post}
- ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC NULLS FIRST,
- data->>'{nameof Post.Empty.UpdatedOn}'
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"{selectWithCriteria Table.Post}{order}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ webLogContains webLogId ]
postWithoutText
@@ -146,9 +149,9 @@ type PostgresPostData(log: ILogger) =
let findPageOfPublishedPosts webLogId pageNbr postsPerPage =
log.LogTrace "Post.findPageOfPublishedPosts"
Custom.list
- $"{selectWithCriteria Table.Post}
- ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"""{selectWithCriteria Table.Post}
+ {Query.orderBy [ Field.Named $"{nameof Post.Empty.PublishedOn} DESC" ] PostgreSQL}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"""
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |} ]
postWithoutLinks
@@ -156,10 +159,10 @@ type PostgresPostData(log: ILogger) =
let findPageOfTaggedPosts webLogId (tag: string) pageNbr postsPerPage =
log.LogTrace "Post.findPageOfTaggedPosts"
Custom.list
- $"{selectWithCriteria Table.Post}
- AND data['{nameof Post.Empty.Tags}'] @> @tag
- ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"""{selectWithCriteria Table.Post}
+ AND data['{nameof Post.Empty.Tags}'] @> @tag
+ {Query.orderBy [ Field.Named $"{nameof Post.Empty.PublishedOn} DESC" ] PostgreSQL}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"""
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}; jsonParam "@tag" [| tag |] ]
postWithoutLinks
@@ -170,10 +173,10 @@ type PostgresPostData(log: ILogger) =
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}
"@publishedOn", Sql.timestamptz (publishedOn.ToDateTimeOffset()) ]
let query op direction =
- $"{selectWithCriteria Table.Post}
- AND (data->>'{nameof Post.Empty.PublishedOn}')::timestamp with time zone %s{op} @publishedOn
- ORDER BY data->>'{nameof Post.Empty.PublishedOn}' %s{direction}
- LIMIT 1"
+ $"""{selectWithCriteria Table.Post}
+ AND (data->>'{nameof Post.Empty.PublishedOn}')::timestamp with time zone %s{op} @publishedOn
+ {Query.orderBy [ Field.Named $"{nameof Post.Empty.PublishedOn} %s{direction}" ] PostgreSQL}
+ LIMIT 1"""
let! older = Custom.list (query "<" "DESC") (queryParams ()) postWithoutLinks
let! newer = Custom.list (query ">" "") (queryParams ()) postWithoutLinks
return List.tryHead older, List.tryHead newer
diff --git a/src/MyWebLog.Data/Postgres/PostgresThemeData.fs b/src/MyWebLog.Data/Postgres/PostgresThemeData.fs
index 6942f3b..727aecd 100644
--- a/src/MyWebLog.Data/Postgres/PostgresThemeData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresThemeData.fs
@@ -17,11 +17,11 @@ type PostgresThemeData(log: ILogger) =
/// Retrieve all themes (except 'admin'; excludes template text)
let all () =
log.LogTrace "Theme.all"
+ let fields = [ Field.NE (nameof Theme.Empty.Id) "admin" ]
Custom.list
- $"{Query.find Table.Theme}
- WHERE data->>'{nameof Theme.Empty.Id}' <> 'admin'
- ORDER BY data->>'{nameof Theme.Empty.Id}'"
- []
+ (Query.byFields (Query.find Table.Theme) Any fields
+ + Query.orderBy [ Field.Named (nameof Theme.Empty.Id) ] PostgreSQL)
+ (addFieldParams fields [])
withoutTemplateText
/// Does a given theme exist?
diff --git a/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs b/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs
index caca8ba..3507d83 100644
--- a/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs
+++ b/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs
@@ -49,10 +49,8 @@ type PostgresWebLogUserData(log: ILogger) =
/// Get all users for the given web log
let findByWebLog webLogId =
log.LogTrace "WebLogUser.findByWebLog"
- Custom.list
- $"{selectWithCriteria Table.WebLogUser} ORDER BY LOWER(data->>'{nameof WebLogUser.Empty.PreferredName}')"
- [ webLogContains webLogId ]
- fromData
+ Find.byContainsOrdered
+ Table.WebLogUser (webLogDoc webLogId) [ Field.Named $"i:{nameof WebLogUser.Empty.PreferredName}" ]
/// Find the names of users by their IDs for the given web log
let findNames webLogId (userIds: WebLogUserId list) = backgroundTask {
diff --git a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
index 47f0541..8faf3ae 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs
@@ -16,16 +16,18 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
let parentIdField = nameof Category.Empty.ParentId
/// Count all categories for the given web log
- let countAll webLogId =
+ let countAll webLogId = backgroundTask {
log.LogTrace "Category.countAll"
- Document.countByWebLog Table.Category webLogId conn
+ let! count = conn.countByFields Table.Category Any [ webLogField webLogId ]
+ return int count
+ }
/// Count all top-level categories for the given web log
- let countTopLevel webLogId =
+ let countTopLevel webLogId = backgroundTask {
log.LogTrace "Category.countTopLevel"
- let fields = [ webLogField webLogId; Field.NEX parentIdField ]
- conn.customScalar
- (Query.byFields (Query.count Table.Category) All fields) (addFieldParams fields []) (toCount >> int)
+ let! count = conn.countByFields Table.Category All [ webLogField webLogId; Field.NEX parentIdField ]
+ return int count
+ }
/// Find all categories for the given web log
let findByWebLog webLogId =
diff --git a/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs b/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs
index 48b3ca7..f071b93 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs
@@ -251,12 +251,6 @@ module Document =
/// A query to select from a table by its web log ID
let selectByWebLog table =
Query.statementWhere (Query.find table) whereByWebLog
-
- /// Count documents for the given web log ID
- let countByWebLog table (webLogId: WebLogId) conn = backgroundTask {
- let! count = Count.byFields table Any [ webLogField webLogId ] conn
- return int count
- }
/// Functions to support revisions
diff --git a/src/MyWebLog.Data/SQLite/SQLitePageData.fs b/src/MyWebLog.Data/SQLite/SQLitePageData.fs
index f12d61b..de3144e 100644
--- a/src/MyWebLog.Data/SQLite/SQLitePageData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLitePageData.fs
@@ -17,8 +17,10 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
/// The JSON field name for the "is in page list" flag
let pgListName = nameof Page.Empty.IsInPageList
- /// The JSON field for the title of the page
- let titleField = $"data->>'{nameof Page.Empty.Title}'"
+ /// Query to return pages sorted by title
+ let sortedPages fields =
+ Query.byFields (Query.find Table.Page) All fields
+ + Query.orderBy [ Field.Named $"i:{nameof Page.Empty.Title}" ] SQLite
// SUPPORT FUNCTIONS
@@ -52,21 +54,23 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Page.all"
let field = [ webLogField webLogId ]
conn.customList
- $"{Query.byFields (Query.find Table.Page) Any field} ORDER BY LOWER({titleField})"
+ (sortedPages field)
(addFieldParams field [])
(fun rdr -> { fromData rdr with Text = ""; Metadata = []; PriorPermalinks = [] })
/// Count all pages for the given web log
- let countAll webLogId =
+ let countAll webLogId = backgroundTask {
log.LogTrace "Page.countAll"
- Document.countByWebLog Table.Page webLogId conn
+ let! count = conn.countByFields Table.Page Any [ webLogField webLogId ]
+ return int count
+ }
/// Count all pages shown in the page list for the given web log
- let countListed webLogId =
+ let countListed webLogId = backgroundTask {
log.LogTrace "Page.countListed"
- let fields = [ webLogField webLogId; Field.EQ pgListName true ]
- conn.customScalar
- (Query.byFields (Query.count Table.Page) All fields) (addFieldParams fields []) (toCount >> int)
+ let! count = conn.countByFields Table.Page All [ webLogField webLogId; Field.EQ pgListName true ]
+ return int count
+ }
/// Find a page by its ID (without revisions and prior permalinks)
let findById (pageId: PageId) webLogId = backgroundTask {
@@ -131,17 +135,14 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Page.findListed"
let fields = [ webLogField webLogId; Field.EQ pgListName true ]
conn.customList
- $"{Query.byFields (Query.find Table.Page) All fields} ORDER BY LOWER({titleField})"
- (addFieldParams fields [])
- (fun rdr -> { fromData rdr with Text = "" })
+ (sortedPages fields) (addFieldParams fields []) (fun rdr -> { fromData rdr with Text = "" })
/// Get a page of pages for the given web log (without revisions)
let findPageOfPages webLogId pageNbr =
log.LogTrace "Page.findPageOfPages"
let field = [ webLogField webLogId ]
conn.customList
- $"{Query.byFields (Query.find Table.Page) Any field} ORDER BY LOWER({titleField})
- LIMIT @pageSize OFFSET @toSkip"
+ $"{sortedPages field} LIMIT @pageSize OFFSET @toSkip"
(addFieldParams field [ sqlParam "@pageSize" 26; sqlParam "@toSkip" ((pageNbr - 1) * 25) ])
(fun rdr -> { pageWithoutLinks rdr with Metadata = [] })
diff --git a/src/MyWebLog.Data/SQLite/SQLitePostData.fs b/src/MyWebLog.Data/SQLite/SQLitePostData.fs
index 414048f..66659d5 100644
--- a/src/MyWebLog.Data/SQLite/SQLitePostData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLitePostData.fs
@@ -16,7 +16,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let linkName = nameof Post.Empty.Permalink
/// The JSON field for when the post was published
- let publishField = $"data->>'{nameof Post.Empty.PublishedOn}'"
+ let publishName = nameof Post.Empty.PublishedOn
/// The name of the JSON field for the post's status
let statName = nameof Post.Empty.Status
@@ -60,11 +60,11 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
}
/// Count posts in a status for the given web log
- let countByStatus (status: PostStatus) webLogId =
+ let countByStatus (status: PostStatus) webLogId = backgroundTask {
log.LogTrace "Post.countByStatus"
- let fields = [ webLogField webLogId; Field.EQ statName (string status) ]
- conn.customScalar
- (Query.byFields (Query.count Table.Post) All fields) (addFieldParams fields []) (toCount >> int)
+ let! count = conn.countByFields Table.Post All [ webLogField webLogId; Field.EQ statName (string status) ]
+ return int count
+ }
/// Find a post by its ID for the given web log (excluding revisions)
let findById (postId: PostId) webLogId = backgroundTask {
@@ -132,19 +132,20 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Post.findPageOfCategorizedPosts"
let catSql, catParams = inJsonArray Table.Post (nameof Post.Empty.CategoryIds) "catId" categoryIds
conn.customList
- $"{publishedPostByWebLog} AND {catSql}
- ORDER BY {publishField} DESC
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"""{publishedPostByWebLog} AND {catSql}
+ {Query.orderBy [ Field.Named $"{publishName} DESC" ] SQLite}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"""
(webLogParam webLogId :: catParams)
postWithoutLinks
/// Get a page of posts for the given web log (excludes text and revisions)
let findPageOfPosts webLogId pageNbr postsPerPage =
log.LogTrace "Post.findPageOfPosts"
+ let order =
+ Query.orderBy
+ [ Field.Named $"{publishName} DESC NULLS FIRST"; Field.Named (nameof Post.Empty.UpdatedOn) ] SQLite
conn.customList
- $"{postByWebLog}
- ORDER BY {publishField} DESC NULLS FIRST, data->>'{nameof Post.Empty.UpdatedOn}'
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"{postByWebLog}{order} LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ webLogParam webLogId ]
postWithoutText
@@ -152,9 +153,9 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
let findPageOfPublishedPosts webLogId pageNbr postsPerPage =
log.LogTrace "Post.findPageOfPublishedPosts"
conn.customList
- $"{publishedPostByWebLog}
- ORDER BY {publishField} DESC
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"""{publishedPostByWebLog}
+ {Query.orderBy [ Field.Named $"{publishName} DESC" ] SQLite}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"""
[ webLogParam webLogId ]
postWithoutLinks
@@ -163,26 +164,28 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
log.LogTrace "Post.findPageOfTaggedPosts"
let tagSql, tagParams = inJsonArray Table.Post (nameof Post.Empty.Tags) "tag" [ tag ]
conn.customList
- $"{publishedPostByWebLog} AND {tagSql}
- ORDER BY {publishField} DESC
- LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
+ $"""{publishedPostByWebLog} AND {tagSql}
+ {Query.orderBy [ Field.Named $"{publishName} DESC" ] SQLite}
+ LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"""
(webLogParam webLogId :: tagParams)
postWithoutLinks
/// Find the next newest and oldest post from a publish date for the given web log
let findSurroundingPosts webLogId (publishedOn : Instant) = backgroundTask {
log.LogTrace "Post.findSurroundingPosts"
- let parameters = [ webLogParam webLogId; sqlParam "@publishedOn" (instantParam publishedOn) ]
- let! older =
+ let adjacent op order =
+ let fields = [
+ webLogField webLogId
+ Field.EQ (nameof Post.Empty.Status) (string Published)
+ (if op = "<" then Field.LT else Field.GT) publishName (instantParam publishedOn)
+ ]
conn.customSingle
- $"{publishedPostByWebLog} AND {publishField} < @publishedOn ORDER BY {publishField} DESC LIMIT 1"
- parameters
- postWithoutLinks
- let! newer =
- conn.customSingle
- $"{publishedPostByWebLog} AND {publishField} > @publishedOn ORDER BY {publishField} LIMIT 1"
- parameters
+ (Query.byFields (Query.find Table.Post) All fields
+ + Query.orderBy [ Field.Named (publishName + order) ] SQLite + " LIMIT 1")
+ (addFieldParams fields [])
postWithoutLinks
+ let! older = adjacent "<" " DESC"
+ let! newer = adjacent ">" ""
return older, newer
}
diff --git a/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs b/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
index ff205f5..580fcb7 100644
--- a/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
+++ b/src/MyWebLog.Data/SQLite/SQLiteThemeData.fs
@@ -10,8 +10,8 @@ open MyWebLog.Data
/// SQLite myWebLog theme data implementation
type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
- /// The JSON field for the theme ID
- let idField = $"data->>'{nameof Theme.Empty.Id}'"
+ /// The name of the theme ID field
+ let idName = nameof Theme.Empty.Id
/// Convert a document to a theme with no template text
let withoutTemplateText (rdr: SqliteDataReader) =
@@ -25,7 +25,11 @@ type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
/// Retrieve all themes (except 'admin'; excludes template text)
let all () =
log.LogTrace "Theme.all"
- conn.customList $"{Query.find Table.Theme} WHERE {idField} <> 'admin' ORDER BY {idField}" [] withoutTemplateText
+ let fields = [ Field.NE idName "admin" ]
+ conn.customList
+ (Query.byFields (Query.find Table.Theme) Any fields + Query.orderBy [ Field.Named idName ] SQLite)
+ (addFieldParams fields [])
+ withoutTemplateText
/// Does a given theme exist?
let exists (themeId: ThemeId) =
diff --git a/src/MyWebLog.Data/SQLiteData.fs b/src/MyWebLog.Data/SQLiteData.fs
index 158ed7c..1540808 100644
--- a/src/MyWebLog.Data/SQLiteData.fs
+++ b/src/MyWebLog.Data/SQLiteData.fs
@@ -1,7 +1,6 @@
namespace MyWebLog.Data
open System
-open System.Threading.Tasks
open BitBadger.Documents
open BitBadger.Documents.Sqlite
open Microsoft.Data.Sqlite
@@ -24,108 +23,107 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria
let needsTable table =
not (List.contains table tables)
- let jsonTable table =
- $"{Query.Definition.ensureTable table}; {Query.Definition.ensureKey table SQLite}"
+ let creatingTable = "Creating {Table} table..."
- let tasks =
- seq {
- // Theme tables
- if needsTable Table.Theme then jsonTable Table.Theme
- if needsTable Table.ThemeAsset then
+ // Theme tables
+ if needsTable Table.Theme then
+ log.LogInformation(creatingTable, Table.Theme)
+ do! conn.ensureTable Table.Theme
+
+ if needsTable Table.ThemeAsset then
+ log.LogInformation(creatingTable, Table.ThemeAsset)
+ do! conn.customNonQuery
$"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 jsonTable Table.WebLog
-
- // Category table
- if needsTable Table.Category then
- $"""{jsonTable Table.Category};
- {Query.Definition.ensureIndexOn
- Table.Category "web_log" [ nameof Category.Empty.WebLogId ] SQLite}"""
-
- // Web log user table
- if needsTable Table.WebLogUser then
- $"""{jsonTable Table.WebLogUser};
- {Query.Definition.ensureIndexOn
- Table.WebLogUser
- "email"
- [ nameof WebLogUser.Empty.WebLogId; nameof WebLogUser.Empty.Email ]
- SQLite}"""
-
- // Page tables
- if needsTable Table.Page then
- $"""{jsonTable Table.Page};
- {Query.Definition.ensureIndexOn Table.Page "author" [ nameof Page.Empty.AuthorId ] SQLite};
- {Query.Definition.ensureIndexOn
- Table.Page
- "permalink"
- [ nameof Page.Empty.WebLogId; nameof Page.Empty.Permalink ]
- SQLite}"""
- if needsTable Table.PageRevision then
+ PRIMARY KEY (theme_id, path))" []
+
+ // Web log table
+ if needsTable Table.WebLog then
+ log.LogInformation(creatingTable, Table.WebLog)
+ do! conn.ensureTable Table.WebLog
+
+ // Category table
+ if needsTable Table.Category then
+ log.LogInformation(creatingTable, Table.Category)
+ do! conn.ensureTable Table.Category
+ do! conn.ensureFieldIndex Table.Category "web_log" [ nameof Category.Empty.WebLogId ]
+
+ // Web log user table
+ if needsTable Table.WebLogUser then
+ log.LogInformation(creatingTable, Table.WebLogUser)
+ do! conn.ensureTable Table.WebLogUser
+ do! conn.ensureFieldIndex
+ Table.WebLogUser "email" [ nameof WebLogUser.Empty.WebLogId; nameof WebLogUser.Empty.Email ]
+
+ // Page tables
+ if needsTable Table.Page then
+ log.LogInformation(creatingTable, Table.Page)
+ do! conn.ensureTable Table.Page
+ do! conn.ensureFieldIndex Table.Page "author" [ nameof Page.Empty.AuthorId ]
+ do! conn.ensureFieldIndex Table.Page "permalink" [ nameof Page.Empty.WebLogId; nameof Page.Empty.Permalink ]
+
+ if needsTable Table.PageRevision then
+ log.LogInformation(creatingTable, Table.PageRevision)
+ do! conn.customNonQuery
$"CREATE TABLE {Table.PageRevision} (
page_id TEXT NOT NULL,
as_of TEXT NOT NULL,
revision_text TEXT NOT NULL,
- PRIMARY KEY (page_id, as_of))"
-
- // Post tables
- if needsTable Table.Post then
- $"""{jsonTable Table.Post};
- {Query.Definition.ensureIndexOn Table.Post "author" [ nameof Post.Empty.AuthorId ] SQLite};
- {Query.Definition.ensureIndexOn
- Table.Post "permalink" [ nameof Post.Empty.WebLogId; nameof Post.Empty.Permalink ] SQLite};
- {Query.Definition.ensureIndexOn
- Table.Post
- "status"
- [ nameof Post.Empty.WebLogId; nameof Post.Empty.Status; nameof Post.Empty.UpdatedOn ]
- SQLite}"""
- // TODO: index categories by post?
- if needsTable Table.PostRevision then
+ PRIMARY KEY (page_id, as_of))" []
+
+ // Post tables
+ if needsTable Table.Post then
+ log.LogInformation(creatingTable, Table.Post)
+ do! conn.ensureTable Table.Post
+ do! conn.ensureFieldIndex Table.Post "author" [ nameof Post.Empty.AuthorId ]
+ do! conn.ensureFieldIndex Table.Post "permalink" [ nameof Post.Empty.WebLogId; nameof Post.Empty.Permalink ]
+ do! conn.ensureFieldIndex
+ Table.Post
+ "status"
+ [ nameof Post.Empty.WebLogId; nameof Post.Empty.Status; nameof Post.Empty.UpdatedOn ]
+ // TODO: index categories by post?
+
+ if needsTable Table.PostRevision then
+ log.LogInformation(creatingTable, Table.PostRevision)
+ do! conn.customNonQuery
$"CREATE TABLE {Table.PostRevision} (
post_id TEXT NOT NULL,
as_of TEXT NOT NULL,
revision_text TEXT NOT NULL,
- PRIMARY KEY (post_id, as_of))"
- if needsTable Table.PostComment then
- $"""{jsonTable Table.PostComment};
- {Query.Definition.ensureIndexOn
- Table.PostComment "post" [ nameof Comment.Empty.PostId ] SQLite}"""
-
- // Tag map table
- if needsTable Table.TagMap then
- $"""{jsonTable Table.TagMap};
- {Query.Definition.ensureIndexOn
- Table.TagMap
- "url"
- [ nameof TagMap.Empty.WebLogId; nameof TagMap.Empty.UrlValue ]
- SQLite}"""
-
- // Uploaded file table
- if needsTable Table.Upload then
+ PRIMARY KEY (post_id, as_of))" []
+
+ if needsTable Table.PostComment then
+ log.LogInformation(creatingTable, Table.PostComment)
+ do! conn.ensureTable Table.PostComment
+ do! conn.ensureFieldIndex Table.PostComment "post" [ nameof Comment.Empty.PostId ]
+
+ // Tag map table
+ if needsTable Table.TagMap then
+ log.LogInformation(creatingTable, Table.TagMap)
+ do! conn.ensureTable Table.TagMap
+ do! conn.ensureFieldIndex Table.TagMap "url" [ nameof TagMap.Empty.WebLogId; nameof TagMap.Empty.UrlValue ]
+
+ // Uploaded file table
+ if needsTable Table.Upload then
+ log.LogInformation(creatingTable, Table.Upload)
+ do! conn.customNonQuery
$"CREATE TABLE {Table.Upload} (
id TEXT PRIMARY KEY,
web_log_id TEXT NOT NULL,
path TEXT NOT NULL,
updated_on TEXT NOT NULL,
data BLOB NOT NULL);
- CREATE INDEX idx_{Table.Upload}_path ON {Table.Upload} (web_log_id, path)"
-
- // Database version table
- if needsTable Table.DbVersion then
- $"CREATE TABLE {Table.DbVersion} (id TEXT PRIMARY KEY);
- INSERT INTO {Table.DbVersion} VALUES ('{Utils.Migration.currentDbVersion}')"
- }
- |> Seq.map (fun sql ->
- log.LogInformation $"""Creating {(sql.Replace("IF NOT EXISTS ", "").Split ' ')[2]} table..."""
- conn.customNonQuery sql [])
+ CREATE INDEX idx_{Table.Upload}_path ON {Table.Upload} (web_log_id, path)" []
- let! _ = Task.WhenAll tasks
- ()
+ // Database version table
+ if needsTable Table.DbVersion then
+ log.LogInformation(creatingTable, Table.DbVersion)
+ do! conn.customNonQuery
+ $"CREATE TABLE {Table.DbVersion} (id TEXT PRIMARY KEY);
+ INSERT INTO {Table.DbVersion} VALUES ('{Utils.Migration.currentDbVersion}')" []
}
/// Set the database version to the specified version
diff --git a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj
index 1eecef4..7682c35 100644
--- a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj
+++ b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/MyWebLog.Tests/MyWebLog.Tests.fsproj b/src/MyWebLog.Tests/MyWebLog.Tests.fsproj
index 64edcd9..fd362a3 100644
--- a/src/MyWebLog.Tests/MyWebLog.Tests.fsproj
+++ b/src/MyWebLog.Tests/MyWebLog.Tests.fsproj
@@ -28,7 +28,7 @@
-
+
diff --git a/src/MyWebLog/MyWebLog.fsproj b/src/MyWebLog/MyWebLog.fsproj
index 9bb4bce..06b4bf1 100644
--- a/src/MyWebLog/MyWebLog.fsproj
+++ b/src/MyWebLog/MyWebLog.fsproj
@@ -32,12 +32,12 @@
-
-
+
+
-
+