Tweak PostgreSQL calls

This commit is contained in:
Daniel J. Summers 2024-08-19 22:45:14 -04:00
parent fbc4e891bd
commit d4c0e4e26c
8 changed files with 42 additions and 49 deletions

View File

@ -29,7 +29,7 @@ type PostgresCategoryData(log: ILogger) =
log.LogTrace "Category.findAllForView" log.LogTrace "Category.findAllForView"
let! cats = let! cats =
Custom.list Custom.list
$"{selectWithCriteria Table.Category} ORDER BY LOWER(data ->> '{nameof Category.Empty.Name}')" $"{selectWithCriteria Table.Category} ORDER BY LOWER(data->>'{nameof Category.Empty.Name}')"
[ webLogContains webLogId ] [ webLogContains webLogId ]
fromData<Category> fromData<Category>
let ordered = Utils.orderByHierarchy cats None None [] let ordered = Utils.orderByHierarchy cats None None []
@ -46,7 +46,7 @@ type PostgresCategoryData(log: ILogger) =
|> arrayContains (nameof Post.Empty.CategoryIds) id |> arrayContains (nameof Post.Empty.CategoryIds) id
let postCount = let postCount =
Custom.scalar Custom.scalar
$"""SELECT COUNT(DISTINCT data ->> '{nameof Post.Empty.Id}') AS it $"""SELECT COUNT(DISTINCT data->>'{nameof Post.Empty.Id}') AS it
FROM {Table.Post} FROM {Table.Post}
WHERE {Query.whereDataContains "@criteria"} WHERE {Query.whereDataContains "@criteria"}
AND {catIdSql}""" AND {catIdSql}"""
@ -74,7 +74,7 @@ type PostgresCategoryData(log: ILogger) =
/// Find all categories for the given web log /// Find all categories for the given web log
let findByWebLog webLogId = let findByWebLog webLogId =
log.LogTrace "Category.findByWebLog" log.LogTrace "Category.findByWebLog"
Document.findByWebLog<Category> Table.Category webLogId Find.byContains<Category> Table.Category (webLogDoc webLogId)
/// Delete a category /// Delete a category
let delete catId webLogId = backgroundTask { let delete catId webLogId = backgroundTask {
@ -103,7 +103,7 @@ type PostgresCategoryData(log: ILogger) =
// Delete the category off all posts where it is assigned // Delete the category off all posts where it is assigned
let! posts = let! posts =
Custom.list Custom.list
$"SELECT data FROM {Table.Post} WHERE data -> '{nameof Post.Empty.CategoryIds}' @> @id" $"SELECT data FROM {Table.Post} WHERE data->'{nameof Post.Empty.CategoryIds}' @> @id"
[ jsonParam "@id" [| string catId |] ] [ jsonParam "@id" [| string catId |] ]
fromData<Post> fromData<Post>
if not (List.isEmpty posts) then if not (List.isEmpty posts) then

View File

@ -165,10 +165,6 @@ module Document =
$"""{Query.find table} WHERE {Query.whereById "@id"} AND {Query.whereDataContains "@criteria"}""" $"""{Query.find table} WHERE {Query.whereById "@id"} AND {Query.whereDataContains "@criteria"}"""
[ "@id", Sql.string (string key); webLogContains webLogId ] [ "@id", Sql.string (string key); webLogContains webLogId ]
fromData<'TDoc> fromData<'TDoc>
/// Find documents for the given web log
let findByWebLog<'TDoc> table webLogId : Task<'TDoc list> =
Find.byContains table (webLogDoc webLogId)
/// Functions to support revisions /// Functions to support revisions
@ -186,7 +182,7 @@ module Revisions =
Custom.list Custom.list
$"""SELECT pr.* $"""SELECT pr.*
FROM %s{revTable} pr FROM %s{revTable} pr
INNER JOIN %s{entityTable} p ON p.data ->> '{nameof Post.Empty.Id}' = pr.{entityTable}_id INNER JOIN %s{entityTable} p ON p.data->>'{nameof Post.Empty.Id}' = pr.{entityTable}_id
WHERE p.{Query.whereDataContains "@criteria"} WHERE p.{Query.whereDataContains "@criteria"}
ORDER BY as_of DESC""" ORDER BY as_of DESC"""
[ webLogContains webLogId ] [ webLogContains webLogId ]

View File

@ -47,7 +47,7 @@ type PostgresPageData(log: ILogger) =
let all webLogId = let all webLogId =
log.LogTrace "Page.all" log.LogTrace "Page.all"
Custom.list Custom.list
$"{selectWithCriteria Table.Page} ORDER BY LOWER(data ->> '{nameof Page.Empty.Title}')" $"{selectWithCriteria Table.Page} ORDER BY LOWER(data->>'{nameof Page.Empty.Title}')"
[ webLogContains webLogId ] [ webLogContains webLogId ]
(fun row -> { fromData<Page> row with Text = ""; Metadata = []; PriorPermalinks = [] }) (fun row -> { fromData<Page> row with Text = ""; Metadata = []; PriorPermalinks = [] })
@ -86,8 +86,8 @@ type PostgresPageData(log: ILogger) =
match! pageExists pageId webLogId with match! pageExists pageId webLogId with
| true -> | true ->
do! Custom.nonQuery do! Custom.nonQuery
$"""DELETE FROM {Table.PageRevision} WHERE page_id = @id; $"""{Query.delete Table.PageRevision} WHERE page_id = @id;
DELETE FROM {Table.Page} WHERE {Query.whereById "@id"}""" {Query.delete Table.Page} WHERE {Query.whereById "@id"}"""
[ idParam pageId ] [ idParam pageId ]
return true return true
| false -> return false | false -> return false
@ -110,7 +110,7 @@ type PostgresPageData(log: ILogger) =
let linkSql, linkParam = arrayContains (nameof Page.Empty.PriorPermalinks) string permalinks let linkSql, linkParam = arrayContains (nameof Page.Empty.PriorPermalinks) string permalinks
return! return!
Custom.single Custom.single
$"""SELECT data ->> '{nameof Page.Empty.Permalink}' AS permalink $"""SELECT data->>'{nameof Page.Empty.Permalink}' AS permalink
FROM page FROM page
WHERE {Query.whereDataContains "@criteria"} WHERE {Query.whereDataContains "@criteria"}
AND {linkSql}""" AND {linkSql}"""
@ -121,7 +121,7 @@ type PostgresPageData(log: ILogger) =
/// Get all complete pages for the given web log /// Get all complete pages for the given web log
let findFullByWebLog webLogId = backgroundTask { let findFullByWebLog webLogId = backgroundTask {
log.LogTrace "Page.findFullByWebLog" log.LogTrace "Page.findFullByWebLog"
let! pages = Document.findByWebLog<Page> Table.Page webLogId let! pages = Find.byContains<Page> Table.Page (webLogDoc webLogId)
let! revisions = Revisions.findByWebLog Table.PageRevision Table.Page PageId webLogId let! revisions = Revisions.findByWebLog Table.PageRevision Table.Page PageId webLogId
return return
pages pages
@ -133,7 +133,7 @@ type PostgresPageData(log: ILogger) =
let findListed webLogId = let findListed webLogId =
log.LogTrace "Page.findListed" log.LogTrace "Page.findListed"
Custom.list Custom.list
$"{selectWithCriteria Table.Page} ORDER BY LOWER(data ->> '{nameof Page.Empty.Title}')" $"{selectWithCriteria Table.Page} ORDER BY LOWER(data->>'{nameof Page.Empty.Title}')"
[ jsonParam "@criteria" {| webLogDoc webLogId with IsInPageList = true |} ] [ jsonParam "@criteria" {| webLogDoc webLogId with IsInPageList = true |} ]
pageWithoutText pageWithoutText

View File

@ -84,9 +84,9 @@ type PostgresPostData(log: ILogger) =
match! postExists postId webLogId with match! postExists postId webLogId with
| true -> | true ->
do! Custom.nonQuery do! Custom.nonQuery
$"""DELETE FROM {Table.PostComment} WHERE {Query.whereDataContains "@criteria"}; $"""{Query.delete Table.PostComment} WHERE {Query.whereDataContains "@criteria"};
DELETE FROM {Table.PostRevision} WHERE post_id = @id; {Query.delete Table.PostRevision} WHERE post_id = @id;
DELETE FROM {Table.Post} WHERE {Query.whereById "@id"}""" {Query.delete Table.Post} WHERE {Query.whereById "@id"}"""
[ idParam postId; jsonParam "@criteria" {| PostId = postId |} ] [ idParam postId; jsonParam "@criteria" {| PostId = postId |} ]
return true return true
| false -> return false | false -> return false
@ -100,7 +100,7 @@ type PostgresPostData(log: ILogger) =
let linkSql, linkParam = arrayContains (nameof Post.Empty.PriorPermalinks) string permalinks let linkSql, linkParam = arrayContains (nameof Post.Empty.PriorPermalinks) string permalinks
return! return!
Custom.single Custom.single
$"""SELECT data ->> '{nameof Post.Empty.Permalink}' AS permalink $"""SELECT data->>'{nameof Post.Empty.Permalink}' AS permalink
FROM {Table.Post} FROM {Table.Post}
WHERE {Query.whereDataContains "@criteria"} WHERE {Query.whereDataContains "@criteria"}
AND {linkSql}""" AND {linkSql}"""
@ -111,7 +111,7 @@ type PostgresPostData(log: ILogger) =
/// Get all complete posts for the given web log /// Get all complete posts for the given web log
let findFullByWebLog webLogId = backgroundTask { let findFullByWebLog webLogId = backgroundTask {
log.LogTrace "Post.findFullByWebLog" log.LogTrace "Post.findFullByWebLog"
let! posts = Document.findByWebLog<Post> Table.Post webLogId let! posts = Find.byContains<Post> Table.Post (webLogDoc webLogId)
let! revisions = Revisions.findByWebLog Table.PostRevision Table.Post PostId webLogId let! revisions = Revisions.findByWebLog Table.PostRevision Table.Post PostId webLogId
return return
posts posts
@ -126,7 +126,7 @@ type PostgresPostData(log: ILogger) =
Custom.list Custom.list
$"{selectWithCriteria Table.Post} $"{selectWithCriteria Table.Post}
AND {catSql} AND {catSql}
ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}; catParam ] [ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}; catParam ]
postWithoutLinks postWithoutLinks
@ -136,8 +136,8 @@ type PostgresPostData(log: ILogger) =
log.LogTrace "Post.findPageOfPosts" log.LogTrace "Post.findPageOfPosts"
Custom.list Custom.list
$"{selectWithCriteria Table.Post} $"{selectWithCriteria Table.Post}
ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC NULLS FIRST, ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC NULLS FIRST,
data ->> '{nameof Post.Empty.UpdatedOn}' data->>'{nameof Post.Empty.UpdatedOn}'
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ webLogContains webLogId ] [ webLogContains webLogId ]
postWithoutText postWithoutText
@ -147,7 +147,7 @@ type PostgresPostData(log: ILogger) =
log.LogTrace "Post.findPageOfPublishedPosts" log.LogTrace "Post.findPageOfPublishedPosts"
Custom.list Custom.list
$"{selectWithCriteria Table.Post} $"{selectWithCriteria Table.Post}
ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |} ] [ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |} ]
postWithoutLinks postWithoutLinks
@ -158,7 +158,7 @@ type PostgresPostData(log: ILogger) =
Custom.list Custom.list
$"{selectWithCriteria Table.Post} $"{selectWithCriteria Table.Post}
AND data['{nameof Post.Empty.Tags}'] @> @tag AND data['{nameof Post.Empty.Tags}'] @> @tag
ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC ORDER BY data->>'{nameof Post.Empty.PublishedOn}' DESC
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
[ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}; jsonParam "@tag" [| tag |] ] [ jsonParam "@criteria" {| webLogDoc webLogId with Status = Published |}; jsonParam "@tag" [| tag |] ]
postWithoutLinks postWithoutLinks
@ -171,8 +171,8 @@ type PostgresPostData(log: ILogger) =
"@publishedOn", Sql.timestamptz (publishedOn.ToDateTimeOffset()) ] "@publishedOn", Sql.timestamptz (publishedOn.ToDateTimeOffset()) ]
let query op direction = let query op direction =
$"{selectWithCriteria Table.Post} $"{selectWithCriteria Table.Post}
AND (data ->> '{nameof Post.Empty.PublishedOn}')::timestamp with time zone %s{op} @publishedOn AND (data->>'{nameof Post.Empty.PublishedOn}')::timestamp with time zone %s{op} @publishedOn
ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' %s{direction} ORDER BY data->>'{nameof Post.Empty.PublishedOn}' %s{direction}
LIMIT 1" LIMIT 1"
let! older = Custom.list (query "<" "DESC") (queryParams ()) postWithoutLinks let! older = Custom.list (query "<" "DESC") (queryParams ()) postWithoutLinks
let! newer = Custom.list (query ">" "") (queryParams ()) postWithoutLinks let! newer = Custom.list (query ">" "") (queryParams ()) postWithoutLinks

View File

@ -33,10 +33,7 @@ type PostgresTagMapData(log: ILogger) =
/// Get all tag mappings for the given web log /// Get all tag mappings for the given web log
let findByWebLog webLogId = let findByWebLog webLogId =
log.LogTrace "TagMap.findByWebLog" log.LogTrace "TagMap.findByWebLog"
Custom.list Find.byContainsOrdered<TagMap> Table.TagMap (webLogDoc webLogId) [ Field.Named (nameof TagMap.Empty.Tag) ]
$"{selectWithCriteria Table.TagMap} ORDER BY data ->> 'tag'"
[ webLogContains webLogId ]
fromData<TagMap>
/// Find any tag mappings in a list of tags for the given web log /// Find any tag mappings in a list of tags for the given web log
let findMappingForTags tags webLogId = let findMappingForTags tags webLogId =

View File

@ -19,8 +19,8 @@ type PostgresThemeData(log: ILogger) =
log.LogTrace "Theme.all" log.LogTrace "Theme.all"
Custom.list Custom.list
$"{Query.find Table.Theme} $"{Query.find Table.Theme}
WHERE data ->> '{nameof Theme.Empty.Id}' <> 'admin' WHERE data->>'{nameof Theme.Empty.Id}' <> 'admin'
ORDER BY data ->> '{nameof Theme.Empty.Id}'" ORDER BY data->>'{nameof Theme.Empty.Id}'"
[] []
withoutTemplateText withoutTemplateText
@ -45,8 +45,8 @@ type PostgresThemeData(log: ILogger) =
match! exists themeId with match! exists themeId with
| true -> | true ->
do! Custom.nonQuery do! Custom.nonQuery
$"""DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id; $"""{Query.delete Table.ThemeAsset} WHERE theme_id = @id;
DELETE FROM {Table.Theme} WHERE {Query.whereById "@id"}""" {Query.delete Table.Theme} WHERE {Query.whereById "@id"}"""
[ idParam themeId ] [ idParam themeId ]
return true return true
| false -> return false | false -> return false
@ -77,7 +77,7 @@ type PostgresThemeAssetData(log: ILogger) =
/// Delete all assets for the given theme /// Delete all assets for the given theme
let deleteByTheme (themeId: ThemeId) = let deleteByTheme (themeId: ThemeId) =
log.LogTrace "ThemeAsset.deleteByTheme" log.LogTrace "ThemeAsset.deleteByTheme"
Custom.nonQuery $"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id" [ idParam themeId ] Custom.nonQuery $"{Query.delete Table.ThemeAsset} WHERE theme_id = @id" [ idParam themeId ]
/// Find a theme asset by its ID /// Find a theme asset by its ID
let findById assetId = let findById assetId =

View File

@ -23,22 +23,22 @@ type PostgresWebLogData(log: ILogger) =
let delete webLogId = let delete webLogId =
log.LogTrace "WebLog.delete" log.LogTrace "WebLog.delete"
Custom.nonQuery Custom.nonQuery
$"""DELETE FROM {Table.PostComment} $"""{Query.delete Table.PostComment}
WHERE data->>'{nameof Comment.Empty.PostId}' WHERE data->>'{nameof Comment.Empty.PostId}'
IN (SELECT data->>'{nameof Post.Empty.Id}' IN (SELECT data->>'{nameof Post.Empty.Id}'
FROM {Table.Post} FROM {Table.Post}
WHERE {Query.whereDataContains "@criteria"}); WHERE {Query.whereDataContains "@criteria"});
DELETE FROM {Table.PostRevision} {Query.delete Table.PostRevision}
WHERE post_id IN (SELECT data->>'Id' FROM {Table.Post} WHERE {Query.whereDataContains "@criteria"}); WHERE post_id IN (SELECT data->>'Id' FROM {Table.Post} WHERE {Query.whereDataContains "@criteria"});
DELETE FROM {Table.PageRevision} {Query.delete Table.PageRevision}
WHERE page_id IN (SELECT data->>'Id' FROM {Table.Page} WHERE {Query.whereDataContains "@criteria"}); WHERE page_id IN (SELECT data->>'Id' FROM {Table.Page} WHERE {Query.whereDataContains "@criteria"});
{Query.byContains (Query.delete Table.Post)}; {Query.byContains (Query.delete Table.Post)};
{Query.byContains (Query.delete Table.Page)}; {Query.byContains (Query.delete Table.Page)};
{Query.byContains (Query.delete Table.Category)}; {Query.byContains (Query.delete Table.Category)};
{Query.byContains (Query.delete Table.TagMap)}; {Query.byContains (Query.delete Table.TagMap)};
{Query.byContains (Query.delete Table.WebLogUser)}; {Query.byContains (Query.delete Table.WebLogUser)};
DELETE FROM {Table.Upload} WHERE web_log_id = @webLogId; {Query.delete Table.Upload} WHERE web_log_id = @webLogId;
DELETE FROM {Table.WebLog} WHERE data->>'Id' = @webLogId""" {Query.delete Table.WebLog} WHERE data->>'Id' = @webLogId"""
[ webLogIdParam webLogId; webLogContains webLogId ] [ webLogIdParam webLogId; webLogContains webLogId ]
/// Find a web log by its host (URL base) /// Find a web log by its host (URL base)

View File

@ -50,14 +50,14 @@ type PostgresWebLogUserData(log: ILogger) =
let findByWebLog webLogId = let findByWebLog webLogId =
log.LogTrace "WebLogUser.findByWebLog" log.LogTrace "WebLogUser.findByWebLog"
Custom.list Custom.list
$"{selectWithCriteria Table.WebLogUser} ORDER BY LOWER(data ->> '{nameof WebLogUser.Empty.PreferredName}')" $"{selectWithCriteria Table.WebLogUser} ORDER BY LOWER(data->>'{nameof WebLogUser.Empty.PreferredName}')"
[ webLogContains webLogId ] [ webLogContains webLogId ]
fromData<WebLogUser> fromData<WebLogUser>
/// Find the names of users by their IDs for the given web log /// Find the names of users by their IDs for the given web log
let findNames webLogId (userIds: WebLogUserId list) = backgroundTask { let findNames webLogId (userIds: WebLogUserId list) = backgroundTask {
log.LogTrace "WebLogUser.findNames" log.LogTrace "WebLogUser.findNames"
let idSql, idParams = inClause $"AND data ->> '{nameof WebLogUser.Empty.Id}'" "id" userIds let idSql, idParams = inClause $"AND data->>'{nameof WebLogUser.Empty.Id}'" "id" userIds
let! users = let! users =
Custom.list Custom.list
$"{selectWithCriteria Table.WebLogUser} {idSql}" $"{selectWithCriteria Table.WebLogUser} {idSql}"