diff --git a/src/MyWebLog.Data/MyWebLog.Data.fsproj b/src/MyWebLog.Data/MyWebLog.Data.fsproj index 0aa40b8..804465b 100644 --- a/src/MyWebLog.Data/MyWebLog.Data.fsproj +++ b/src/MyWebLog.Data/MyWebLog.Data.fsproj @@ -5,9 +5,9 @@ - - - + + + diff --git a/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs b/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs index d127585..60afe53 100644 --- a/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs @@ -81,15 +81,26 @@ type PostgresCategoryData(log: ILogger) = let! children = Find.byContains Table.Category {| ParentId = catId |} let hasChildren = not (List.isEmpty children) if hasChildren then - let! _ = - Configuration.dataSource () - |> Sql.fromDataSource - |> Sql.executeTransactionAsync - [ Query.Patch.byId Table.Category, - children - |> List.map (fun child -> - [ idParam child.Id; jsonParam "@data" {| ParentId = cat.ParentId |} ]) ] - () + if cat.ParentId.IsSome then + let! _ = + Configuration.dataSource () + |> Sql.fromDataSource + |> Sql.executeTransactionAsync + [ Query.Patch.byId Table.Category, + children + |> List.map (fun child -> + [ idParam child.Id; jsonParam "@data" {| ParentId = cat.ParentId |} ]) ] + () + else + let! _ = + Configuration.dataSource () + |> Sql.fromDataSource + |> Sql.executeTransactionAsync + [ Query.RemoveFields.byId Table.Category, + children + |> List.map (fun child -> + [ idParam child.Id; fieldNameParam [ nameof Category.Empty.ParentId ] ]) ] + () // Delete the category off all posts where it is assigned let! posts = Custom.list diff --git a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs index 66d325f..4cf6104 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteCategoryData.fs @@ -53,7 +53,7 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge SELECT COUNT(DISTINCT data ->> '{nameof Post.Empty.Id}') FROM {Table.Post} WHERE {Document.Query.whereByWebLog} - AND {Query.whereByField (nameof Post.Empty.Status) EQ $"'{string Published}'"} + AND {Query.whereByField (Field.EQ (nameof Post.Empty.Status) "") $"'{string Published}'"} AND {catSql}""" let! postCount = conn.customScalar query (webLogParam webLogId :: catParams) toCount return it.Id, int postCount @@ -79,17 +79,12 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge match! findById catId webLogId with | Some cat -> // Reassign any children to the category's parent category - let! children = conn.countByField Table.Category parentIdField EQ (string catId) + let! children = conn.countByField Table.Category (Field.EQ parentIdField (string catId)) if children > 0L then + let parent = Field.EQ parentIdField (string catId) match cat.ParentId with - | Some _ -> - do! conn.patchByField Table.Category parentIdField EQ (string catId) {| ParentId = cat.ParentId |} - | None -> - do! conn.customNonQuery - $"""UPDATE {Table.Category} - SET data = json_remove(data, '$.ParentId') - WHERE {Query.whereByField parentIdField EQ "@field"}""" - [ fieldParam (string catId) ] + | Some _ -> do! conn.patchByField Table.Category parent {| ParentId = cat.ParentId |} + | None -> do! conn.removeFieldsByField Table.Category parent [ parentIdField ] // Delete the category off all posts where it is assigned, and the category itself let catIdField = nameof Post.Empty.CategoryIds let! posts = diff --git a/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs b/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs index 07e23e7..bfb8952 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteHelpers.fs @@ -239,7 +239,7 @@ module Document = /// Fragment to add a web log ID condition to a WHERE clause (parameter @webLogId) let whereByWebLog = - Query.whereByField "WebLogId" EQ "@webLogId" + Query.whereByField (Field.EQ "WebLogId" "") "@webLogId" /// A SELECT query to count documents for a given web log ID let countByWebLog table = @@ -255,7 +255,7 @@ module Document = /// Count documents for the given web log ID let countByWebLog table (webLogId: WebLogId) conn = backgroundTask { - let! count = Count.byField table "WebLogId" EQ (string webLogId) conn + let! count = Count.byField table (Field.EQ "WebLogId" (string webLogId)) conn return int count } @@ -265,7 +265,7 @@ module Document = /// Find documents for the given web log let findByWebLog<'TDoc> table (webLogId: WebLogId) conn = - Find.byField<'TDoc> table "WebLogId" EQ (string webLogId) conn + Find.byField<'TDoc> table (Field.EQ "WebLogId" (string webLogId)) conn /// Functions to support revisions diff --git a/src/MyWebLog.Data/SQLite/SQLitePageData.fs b/src/MyWebLog.Data/SQLite/SQLitePageData.fs index e76448c..dde7b02 100644 --- a/src/MyWebLog.Data/SQLite/SQLitePageData.fs +++ b/src/MyWebLog.Data/SQLite/SQLitePageData.fs @@ -53,7 +53,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) = let countListed webLogId = log.LogTrace "Page.countListed" conn.customScalar - $"""{Document.Query.countByWebLog Table.Page} AND {Query.whereByField pgListName EQ "true"}""" + $"""{Document.Query.countByWebLog Table.Page} AND {Query.whereByField (Field.EQ pgListName "") "true"}""" [ webLogParam webLogId ] (toCount >> int) @@ -88,9 +88,10 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) = /// Find a page by its permalink for the given web log let findByPermalink (permalink: Permalink) webLogId = log.LogTrace "Page.findByPermalink" + let linkParam = Field.EQ linkName (string permalink) conn.customSingle - $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField linkName EQ "@link"}""" - [ webLogParam webLogId; SqliteParameter("@link", string permalink) ] + $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField linkParam "@link"}""" + (addFieldParam "@link" linkParam [ webLogParam webLogId ]) fromData /// Find the current permalink within a set of potential prior permalinks for the given web log @@ -116,7 +117,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) = let findListed webLogId = log.LogTrace "Page.findListed" conn.customList - $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField pgListName EQ "true"} + $"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField (Field.EQ pgListName "") "true"} ORDER BY LOWER({titleField})""" [ webLogParam webLogId ] (fun rdr -> { fromData rdr with Text = "" }) diff --git a/src/MyWebLog.Data/SQLite/SQLitePostData.fs b/src/MyWebLog.Data/SQLite/SQLitePostData.fs index d2d5f0d..3a67a9c 100644 --- a/src/MyWebLog.Data/SQLite/SQLitePostData.fs +++ b/src/MyWebLog.Data/SQLite/SQLitePostData.fs @@ -34,7 +34,8 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) = let postByWebLog = Document.Query.selectByWebLog Table.Post /// The SELECT statement to retrieve published posts with a web log ID parameter - let publishedPostByWebLog = $"""{postByWebLog} AND {Query.whereByField statName EQ $"'{string Published}'"}""" + let publishedPostByWebLog = + $"""{postByWebLog} AND {Query.whereByField (Field.EQ statName "") $"'{string Published}'"}""" /// Update a post's revisions let updatePostRevisions (postId: PostId) oldRevs newRevs = @@ -46,9 +47,10 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) = /// Count posts in a status for the given web log let countByStatus (status: PostStatus) webLogId = log.LogTrace "Post.countByStatus" + let statParam = Field.EQ statName (string status) conn.customScalar - $"""{Document.Query.countByWebLog Table.Post} AND {Query.whereByField statName EQ "@status"}""" - [ webLogParam webLogId; SqliteParameter("@status", string status) ] + $"""{Document.Query.countByWebLog Table.Post} AND {Query.whereByField statParam "@status"}""" + (addFieldParam "@status" statParam [ webLogParam webLogId ]) (toCount >> int) /// Find a post by its ID for the given web log (excluding revisions) @@ -59,9 +61,10 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) = /// Find a post by its permalink for the given web log (excluding revisions) let findByPermalink (permalink: Permalink) webLogId = log.LogTrace "Post.findByPermalink" + let linkParam = Field.EQ linkName (string permalink) conn.customSingle - $"""{Document.Query.selectByWebLog Table.Post} AND {Query.whereByField linkName EQ "@link"}""" - [ webLogParam webLogId; SqliteParameter("@link", string permalink) ] + $"""{Document.Query.selectByWebLog Table.Post} AND {Query.whereByField linkParam "@link"}""" + (addFieldParam "@link" linkParam [ webLogParam webLogId ]) fromData /// Find a complete post by its ID for the given web log @@ -82,7 +85,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) = do! conn.customNonQuery $"""DELETE FROM {Table.PostRevision} WHERE post_id = @id; DELETE FROM {Table.PostComment} - WHERE {Query.whereByField (nameof Comment.Empty.PostId) EQ "@id"}; + WHERE {Query.whereByField (Field.EQ (nameof Comment.Empty.PostId) "") "@id"}; {Query.Delete.byId Table.Post}""" [ idParam postId ] return true diff --git a/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs b/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs index 50a4b04..f71c61e 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteTagMapData.fs @@ -28,10 +28,10 @@ type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) = /// Find a tag mapping by its URL value for the given web log let findByUrlValue (urlValue: string) webLogId = log.LogTrace "TagMap.findByUrlValue" + let urlParam = Field.EQ (nameof TagMap.Empty.UrlValue) urlValue conn.customSingle - $"""{Document.Query.selectByWebLog Table.TagMap} - AND {Query.whereByField (nameof TagMap.Empty.UrlValue) EQ "@urlValue"}""" - [ webLogParam webLogId; SqliteParameter("@urlValue", urlValue) ] + $"""{Document.Query.selectByWebLog Table.TagMap} AND {Query.whereByField urlParam "@urlValue"}""" + (addFieldParam "@urlValue" urlParam [ webLogParam webLogId ]) fromData /// Get all tag mappings for the given web log diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs index a9d1d17..93af895 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogData.fs @@ -23,25 +23,25 @@ type SQLiteWebLogData(conn: SqliteConnection, log: ILogger) = /// Delete a web log by its ID let delete webLogId = log.LogTrace "WebLog.delete" - let subQuery table = - $"""(SELECT data ->> 'Id' FROM {table} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}""" + let webLogMatches = Query.whereByField (Field.EQ "WebLogId" "") "@webLogId" + let subQuery table = $"(SELECT data ->> 'Id' FROM {table} WHERE {webLogMatches}" Custom.nonQuery $"""DELETE FROM {Table.PostComment} WHERE data ->> 'PostId' IN {subQuery Table.Post}; DELETE FROM {Table.PostRevision} WHERE post_id IN {subQuery Table.Post}; DELETE FROM {Table.PageRevision} WHERE page_id IN {subQuery Table.Page}; - DELETE FROM {Table.Post} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}; - DELETE FROM {Table.Page} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}; - DELETE FROM {Table.Category} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}; - DELETE FROM {Table.TagMap} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}; + DELETE FROM {Table.Post} WHERE {webLogMatches}; + DELETE FROM {Table.Page} WHERE {webLogMatches}; + DELETE FROM {Table.Category} WHERE {webLogMatches}; + DELETE FROM {Table.TagMap} WHERE {webLogMatches}; DELETE FROM {Table.Upload} WHERE web_log_id = @webLogId; - DELETE FROM {Table.WebLogUser} WHERE {Query.whereByField "WebLogId" EQ "@webLogId"}; + DELETE FROM {Table.WebLogUser} WHERE {webLogMatches}; DELETE FROM {Table.WebLog} WHERE {Query.whereById "@webLogId"}""" [ webLogParam webLogId ] /// Find a web log by its host (URL base) let findByHost (url: string) = log.LogTrace "WebLog.findByHost" - conn.findFirstByField Table.WebLog (nameof WebLog.Empty.UrlBase) EQ url + conn.findFirstByField Table.WebLog (Field.EQ (nameof WebLog.Empty.UrlBase) url) /// Find a web log by its ID let findById webLogId = diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs index 216c29b..f87b6c4 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs @@ -20,8 +20,8 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) = log.LogTrace "WebLogUser.delete" match! findById userId webLogId with | Some _ -> - let! pageCount = conn.countByField Table.Page (nameof Page.Empty.AuthorId) EQ (string userId) - let! postCount = conn.countByField Table.Post (nameof Post.Empty.AuthorId) EQ (string userId) + let! pageCount = conn.countByField Table.Page (Field.EQ (nameof Page.Empty.AuthorId) (string userId)) + let! postCount = conn.countByField Table.Post (Field.EQ (nameof Post.Empty.AuthorId) (string userId)) if pageCount + postCount > 0 then return Error "User has pages or posts; cannot delete" else @@ -33,10 +33,11 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) = /// Find a user by their e-mail address for the given web log let findByEmail (email: string) webLogId = log.LogTrace "WebLogUser.findByEmail" + let emailParam = Field.EQ (nameof WebLogUser.Empty.Email) email conn.customSingle $"""{Document.Query.selectByWebLog Table.WebLogUser} - AND {Query.whereByField (nameof WebLogUser.Empty.Email) EQ "@email"}""" - [ webLogParam webLogId; sqlParam "@email" email ] + AND {Query.whereByField emailParam "@email"}""" + (addFieldParam "@email" emailParam [ webLogParam webLogId ]) fromData /// Get all users for the given web log diff --git a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj index 9460006..d86aa8a 100644 --- a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj +++ b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj @@ -7,10 +7,10 @@ - + - + diff --git a/src/MyWebLog/MyWebLog.fsproj b/src/MyWebLog/MyWebLog.fsproj index 4707fa3..076a51b 100644 --- a/src/MyWebLog/MyWebLog.fsproj +++ b/src/MyWebLog/MyWebLog.fsproj @@ -26,8 +26,8 @@ - - + +