Integrate v4 document library for SQLite
- Eliminate warnings for PostgreSQL
This commit is contained in:
parent
cd450a05e5
commit
fbc4e891bd
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Postgres
|
open BitBadger.Documents.Postgres
|
||||||
open BitBadger.Documents.Postgres.Compat
|
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
open MyWebLog.Data
|
open MyWebLog.Data
|
||||||
@ -21,7 +20,7 @@ type PostgresCategoryData(log: ILogger) =
|
|||||||
log.LogTrace "Category.countTopLevel"
|
log.LogTrace "Category.countTopLevel"
|
||||||
Custom.scalar
|
Custom.scalar
|
||||||
$"""{Query.byContains (Query.count Table.Category)}
|
$"""{Query.byContains (Query.count Table.Category)}
|
||||||
AND {Query.whereByField (Field.NEX (nameof Category.Empty.ParentId)) ""}"""
|
AND {Query.whereByFields Any [ Field.NEX (nameof Category.Empty.ParentId) ]}"""
|
||||||
[ webLogContains webLogId ]
|
[ webLogContains webLogId ]
|
||||||
toCount
|
toCount
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ type PostgresCategoryData(log: ILogger) =
|
|||||||
Query.byId (Query.removeFields Table.Category) "",
|
Query.byId (Query.removeFields Table.Category) "",
|
||||||
children
|
children
|
||||||
|> List.map (fun child ->
|
|> List.map (fun child ->
|
||||||
[ idParam child.Id; fieldNameParam [ nameof Category.Empty.ParentId ] ])
|
[ idParam child.Id; fieldNameParams [ nameof Category.Empty.ParentId ] ])
|
||||||
let! _ =
|
let! _ =
|
||||||
Configuration.dataSource ()
|
Configuration.dataSource ()
|
||||||
|> Sql.fromDataSource
|
|> Sql.fromDataSource
|
||||||
|
@ -3,7 +3,6 @@ namespace MyWebLog.Data.SQLite
|
|||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
|
||||||
open Microsoft.Data.Sqlite
|
open Microsoft.Data.Sqlite
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
@ -24,15 +23,14 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
|
|||||||
/// Count all top-level categories for the given web log
|
/// Count all top-level categories for the given web log
|
||||||
let countTopLevel webLogId =
|
let countTopLevel webLogId =
|
||||||
log.LogTrace "Category.countTopLevel"
|
log.LogTrace "Category.countTopLevel"
|
||||||
|
let fields = [ webLogField webLogId; Field.NEX parentIdField ]
|
||||||
conn.customScalar
|
conn.customScalar
|
||||||
$"{Document.Query.countByWebLog Table.Category} AND data ->> '{parentIdField}' IS NULL"
|
(Query.byFields (Query.count Table.Category) All fields) (addFieldParams fields []) (toCount >> int)
|
||||||
[ webLogParam webLogId ]
|
|
||||||
(toCount >> int)
|
|
||||||
|
|
||||||
/// 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 conn
|
conn.findByFields<Category> Table.Category Any [ webLogField webLogId ]
|
||||||
|
|
||||||
/// Retrieve all categories for the given web log in a DotLiquid-friendly format
|
/// Retrieve all categories for the given web log in a DotLiquid-friendly format
|
||||||
let findAllForView webLogId = backgroundTask {
|
let findAllForView webLogId = backgroundTask {
|
||||||
@ -51,10 +49,10 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
|
|||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|> inJsonArray Table.Post (nameof Post.Empty.CategoryIds) "catId"
|
|> inJsonArray Table.Post (nameof Post.Empty.CategoryIds) "catId"
|
||||||
let query = $"""
|
let query = $"""
|
||||||
SELECT COUNT(DISTINCT data ->> '{nameof Post.Empty.Id}')
|
SELECT COUNT(DISTINCT data->>'{nameof Post.Empty.Id}')
|
||||||
FROM {Table.Post}
|
FROM {Table.Post}
|
||||||
WHERE {Document.Query.whereByWebLog}
|
WHERE {Document.Query.whereByWebLog}
|
||||||
AND {Query.whereByField (Field.EQ (nameof Post.Empty.Status) "") $"'{string Published}'"}
|
AND data->>'{nameof Post.Empty.Status}' = '{string Published}'
|
||||||
AND {catSql}"""
|
AND {catSql}"""
|
||||||
let! postCount = conn.customScalar query (webLogParam webLogId :: catParams) toCount
|
let! postCount = conn.customScalar query (webLogParam webLogId :: catParams) toCount
|
||||||
return it.Id, int postCount
|
return it.Id, int postCount
|
||||||
@ -70,9 +68,9 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Find a category by its ID for the given web log
|
/// Find a category by its ID for the given web log
|
||||||
let findById catId webLogId =
|
let findById (catId: CategoryId) webLogId =
|
||||||
log.LogTrace "Category.findById"
|
log.LogTrace "Category.findById"
|
||||||
Document.findByIdAndWebLog<CategoryId, Category> Table.Category catId webLogId conn
|
conn.findFirstByFields<Category> Table.Category All [ idField catId; webLogField webLogId ]
|
||||||
|
|
||||||
/// Delete a category
|
/// Delete a category
|
||||||
let delete catId webLogId = backgroundTask {
|
let delete catId webLogId = backgroundTask {
|
||||||
@ -80,22 +78,22 @@ type SQLiteCategoryData(conn: SqliteConnection, ser: JsonSerializer, log: ILogge
|
|||||||
match! findById catId webLogId with
|
match! findById catId webLogId with
|
||||||
| Some cat ->
|
| Some cat ->
|
||||||
// Reassign any children to the category's parent category
|
// Reassign any children to the category's parent category
|
||||||
let! children = conn.countByField Table.Category (Field.EQ parentIdField (string catId))
|
let! children = conn.countByFields Table.Category Any [ Field.EQ parentIdField (string catId) ]
|
||||||
if children > 0L then
|
if children > 0L then
|
||||||
let parent = Field.EQ parentIdField (string catId)
|
let parent = [ Field.EQ parentIdField (string catId) ]
|
||||||
match cat.ParentId with
|
match cat.ParentId with
|
||||||
| Some _ -> do! conn.patchByField Table.Category parent {| ParentId = cat.ParentId |}
|
| Some _ -> do! conn.patchByFields Table.Category Any parent {| ParentId = cat.ParentId |}
|
||||||
| None -> do! conn.removeFieldsByField Table.Category parent [ parentIdField ]
|
| None -> do! conn.removeFieldsByFields Table.Category Any parent [ parentIdField ]
|
||||||
// Delete the category off all posts where it is assigned, and the category itself
|
// Delete the category off all posts where it is assigned, and the category itself
|
||||||
let catIdField = nameof Post.Empty.CategoryIds
|
let catIdField = nameof Post.Empty.CategoryIds
|
||||||
let! posts =
|
let! posts =
|
||||||
conn.customList
|
conn.customList
|
||||||
$"SELECT data ->> '{nameof Post.Empty.Id}', data -> '{catIdField}'
|
$"SELECT data->>'{nameof Post.Empty.Id}', data->'{catIdField}'
|
||||||
FROM {Table.Post}
|
FROM {Table.Post}
|
||||||
WHERE {Document.Query.whereByWebLog}
|
WHERE {Document.Query.whereByWebLog}
|
||||||
AND EXISTS
|
AND EXISTS
|
||||||
(SELECT 1
|
(SELECT 1
|
||||||
FROM json_each({Table.Post}.data -> '{catIdField}')
|
FROM json_each({Table.Post}.data->'{catIdField}')
|
||||||
WHERE json_each.value = @id)"
|
WHERE json_each.value = @id)"
|
||||||
[ idParam catId; webLogParam webLogId ]
|
[ idParam catId; webLogParam webLogId ]
|
||||||
(fun rdr -> rdr.GetString 0, Utils.deserialize<string list> ser (rdr.GetString 1))
|
(fun rdr -> rdr.GetString 0, Utils.deserialize<string list> ser (rdr.GetString 1))
|
||||||
|
@ -218,6 +218,10 @@ module Map =
|
|||||||
Data = data }
|
Data = data }
|
||||||
|
|
||||||
|
|
||||||
|
open BitBadger.Documents
|
||||||
|
open BitBadger.Documents.Sqlite
|
||||||
|
open BitBadger.Documents.Sqlite.WithConn
|
||||||
|
|
||||||
/// Create a named parameter
|
/// Create a named parameter
|
||||||
let sqlParam name (value: obj) =
|
let sqlParam name (value: obj) =
|
||||||
SqliteParameter(name, value)
|
SqliteParameter(name, value)
|
||||||
@ -226,11 +230,13 @@ let sqlParam name (value: obj) =
|
|||||||
let webLogParam (webLogId: WebLogId) =
|
let webLogParam (webLogId: WebLogId) =
|
||||||
sqlParam "@webLogId" (string webLogId)
|
sqlParam "@webLogId" (string webLogId)
|
||||||
|
|
||||||
|
/// Create a field for an ID value
|
||||||
|
let idField<'T> (idValue: 'T) =
|
||||||
|
{ Field.EQ "Id" (string idValue) with ParameterName = Some "@id" }
|
||||||
|
|
||||||
open BitBadger.Documents
|
/// Create a web log field
|
||||||
open BitBadger.Documents.Sqlite
|
let webLogField (webLogId: WebLogId) =
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
{ Field.EQ "WebLogId" (string webLogId) with ParameterName = Some "@webLogId" }
|
||||||
open BitBadger.Documents.Sqlite.WithConn
|
|
||||||
|
|
||||||
/// Functions for manipulating documents
|
/// Functions for manipulating documents
|
||||||
module Document =
|
module Document =
|
||||||
@ -240,33 +246,17 @@ module Document =
|
|||||||
|
|
||||||
/// Fragment to add a web log ID condition to a WHERE clause (parameter @webLogId)
|
/// Fragment to add a web log ID condition to a WHERE clause (parameter @webLogId)
|
||||||
let whereByWebLog =
|
let whereByWebLog =
|
||||||
Query.whereByField (Field.EQ "WebLogId" "") "@webLogId"
|
Query.whereByFields Any [ { Field.EQ "WebLogId" "" with ParameterName = Some "@webLogId" } ]
|
||||||
|
|
||||||
/// A SELECT query to count documents for a given web log ID
|
|
||||||
let countByWebLog table =
|
|
||||||
Query.statementWhere (Query.count table) whereByWebLog
|
|
||||||
|
|
||||||
/// A query to select from a table by the document's ID and its web log ID
|
|
||||||
let selectByIdAndWebLog table =
|
|
||||||
Query.statementWhere (Query.find table) $"""{Query.whereById "@id"} AND {whereByWebLog}"""
|
|
||||||
|
|
||||||
/// A query to select from a table by its web log ID
|
/// A query to select from a table by its web log ID
|
||||||
let selectByWebLog table =
|
let selectByWebLog table =
|
||||||
$"{Query.selectFromTable table} WHERE {whereByWebLog}"
|
Query.statementWhere (Query.find table) whereByWebLog
|
||||||
|
|
||||||
/// Count documents for the given web log ID
|
/// Count documents for the given web log ID
|
||||||
let countByWebLog table (webLogId: WebLogId) conn = backgroundTask {
|
let countByWebLog table (webLogId: WebLogId) conn = backgroundTask {
|
||||||
let! count = Count.byFields table Any [ Field.EQ "WebLogId" (string webLogId) ] conn
|
let! count = Count.byFields table Any [ webLogField webLogId ] conn
|
||||||
return int count
|
return int count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a document by its ID and web log ID
|
|
||||||
let findByIdAndWebLog<'TKey, 'TDoc> table (key: 'TKey) webLogId conn =
|
|
||||||
Custom.single (Query.selectByIdAndWebLog table) [ idParam key; webLogParam webLogId ] fromData<'TDoc> conn
|
|
||||||
|
|
||||||
/// Find documents for the given web log
|
|
||||||
let findByWebLog<'TDoc> table (webLogId: WebLogId) conn =
|
|
||||||
Find.byFields<'TDoc> table Any [ Field.EQ "WebLogId" (string webLogId) ] conn
|
|
||||||
|
|
||||||
|
|
||||||
/// Functions to support revisions
|
/// Functions to support revisions
|
||||||
@ -285,7 +275,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 ->> 'Id' = pr.{entityTable}_id
|
INNER JOIN %s{entityTable} p ON p.data->>'Id' = pr.{entityTable}_id
|
||||||
WHERE p.{Document.Query.whereByWebLog}
|
WHERE p.{Document.Query.whereByWebLog}
|
||||||
ORDER BY as_of DESC"
|
ORDER BY as_of DESC"
|
||||||
[ webLogParam webLogId ]
|
[ webLogParam webLogId ]
|
||||||
|
@ -3,7 +3,6 @@ namespace MyWebLog.Data.SQLite
|
|||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
|
||||||
open Microsoft.Data.Sqlite
|
open Microsoft.Data.Sqlite
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
@ -19,7 +18,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
let pgListName = nameof Page.Empty.IsInPageList
|
let pgListName = nameof Page.Empty.IsInPageList
|
||||||
|
|
||||||
/// The JSON field for the title of the page
|
/// The JSON field for the title of the page
|
||||||
let titleField = $"data ->> '{nameof Page.Empty.Title}'"
|
let titleField = $"data->>'{nameof Page.Empty.Title}'"
|
||||||
|
|
||||||
// SUPPORT FUNCTIONS
|
// SUPPORT FUNCTIONS
|
||||||
|
|
||||||
@ -51,9 +50,10 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Get all pages for a web log (without text, metadata, revisions, or prior permalinks)
|
/// Get all pages for a web log (without text, metadata, revisions, or prior permalinks)
|
||||||
let all webLogId =
|
let all webLogId =
|
||||||
log.LogTrace "Page.all"
|
log.LogTrace "Page.all"
|
||||||
|
let field = [ webLogField webLogId ]
|
||||||
conn.customList
|
conn.customList
|
||||||
$"{Query.selectFromTable Table.Page} WHERE {Document.Query.whereByWebLog} ORDER BY LOWER({titleField})"
|
$"{Query.byFields (Query.find Table.Page) Any field} ORDER BY LOWER({titleField})"
|
||||||
[ webLogParam webLogId ]
|
(addFieldParams field [])
|
||||||
(fun rdr -> { fromData<Page> rdr with Text = ""; Metadata = []; PriorPermalinks = [] })
|
(fun rdr -> { fromData<Page> rdr with Text = ""; Metadata = []; PriorPermalinks = [] })
|
||||||
|
|
||||||
/// Count all pages for the given web log
|
/// Count all pages for the given web log
|
||||||
@ -64,23 +64,22 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Count all pages shown in the page list for the given web log
|
/// Count all pages shown in the page list for the given web log
|
||||||
let countListed webLogId =
|
let countListed webLogId =
|
||||||
log.LogTrace "Page.countListed"
|
log.LogTrace "Page.countListed"
|
||||||
|
let fields = [ webLogField webLogId; Field.EQ pgListName true ]
|
||||||
conn.customScalar
|
conn.customScalar
|
||||||
$"""{Document.Query.countByWebLog Table.Page} AND {Query.whereByField (Field.EQ pgListName "") "true"}"""
|
(Query.byFields (Query.count Table.Page) All fields) (addFieldParams fields []) (toCount >> int)
|
||||||
[ webLogParam webLogId ]
|
|
||||||
(toCount >> int)
|
|
||||||
|
|
||||||
/// Find a page by its ID (without revisions and prior permalinks)
|
/// Find a page by its ID (without revisions and prior permalinks)
|
||||||
let findById pageId webLogId = backgroundTask {
|
let findById (pageId: PageId) webLogId = backgroundTask {
|
||||||
log.LogTrace "Page.findById"
|
log.LogTrace "Page.findById"
|
||||||
match! Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId conn with
|
match! conn.findFirstByFields<Page> Table.Page All [ idField pageId; webLogField webLogId ] with
|
||||||
| Some page -> return Some { page with PriorPermalinks = [] }
|
| Some page -> return Some { page with PriorPermalinks = [] }
|
||||||
| None -> return None
|
| None -> return None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a complete page by its ID
|
/// Find a complete page by its ID
|
||||||
let findFullById pageId webLogId = backgroundTask {
|
let findFullById (pageId: PageId) webLogId = backgroundTask {
|
||||||
log.LogTrace "Page.findFullById"
|
log.LogTrace "Page.findFullById"
|
||||||
match! Document.findByIdAndWebLog<PageId, Page> Table.Page pageId webLogId conn with
|
match! conn.findFirstByFields<Page> Table.Page All [ idField pageId; webLogField webLogId ] with
|
||||||
| Some page ->
|
| Some page ->
|
||||||
let! page = appendPageRevisions page
|
let! page = appendPageRevisions page
|
||||||
return Some page
|
return Some page
|
||||||
@ -94,7 +93,7 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
match! findById pageId webLogId with
|
match! findById pageId webLogId with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
do! conn.customNonQuery
|
do! conn.customNonQuery
|
||||||
$"DELETE FROM {Table.PageRevision} WHERE page_id = @id;
|
$"{Query.delete Table.PageRevision} WHERE page_id = @id;
|
||||||
{Query.byId (Query.delete Table.Page) (string pageId)}"
|
{Query.byId (Query.delete Table.Page) (string pageId)}"
|
||||||
[ idParam pageId ]
|
[ idParam pageId ]
|
||||||
return true
|
return true
|
||||||
@ -104,18 +103,16 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Find a page by its permalink for the given web log
|
/// Find a page by its permalink for the given web log
|
||||||
let findByPermalink (permalink: Permalink) webLogId =
|
let findByPermalink (permalink: Permalink) webLogId =
|
||||||
log.LogTrace "Page.findByPermalink"
|
log.LogTrace "Page.findByPermalink"
|
||||||
let linkParam = Field.EQ linkName (string permalink)
|
let fields = [ webLogField webLogId; Field.EQ linkName (string permalink) ]
|
||||||
conn.customSingle
|
conn.customSingle
|
||||||
$"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField linkParam "@link"}"""
|
(Query.byFields (Query.find Table.Page) All fields) (addFieldParams fields []) pageWithoutLinks
|
||||||
(addFieldParam "@link" linkParam [ webLogParam webLogId ])
|
|
||||||
pageWithoutLinks
|
|
||||||
|
|
||||||
/// Find the current permalink within a set of potential prior permalinks for the given web log
|
/// Find the current permalink within a set of potential prior permalinks for the given web log
|
||||||
let findCurrentPermalink (permalinks: Permalink list) webLogId =
|
let findCurrentPermalink (permalinks: Permalink list) webLogId =
|
||||||
log.LogTrace "Page.findCurrentPermalink"
|
log.LogTrace "Page.findCurrentPermalink"
|
||||||
let linkSql, linkParams = inJsonArray Table.Page (nameof Page.Empty.PriorPermalinks) "link" permalinks
|
let linkSql, linkParams = inJsonArray Table.Page (nameof Page.Empty.PriorPermalinks) "link" permalinks
|
||||||
conn.customSingle
|
conn.customSingle
|
||||||
$"SELECT data ->> '{linkName}' AS permalink
|
$"SELECT data->>'{linkName}' AS permalink
|
||||||
FROM {Table.Page}
|
FROM {Table.Page}
|
||||||
WHERE {Document.Query.whereByWebLog} AND {linkSql}"
|
WHERE {Document.Query.whereByWebLog} AND {linkSql}"
|
||||||
(webLogParam webLogId :: linkParams)
|
(webLogParam webLogId :: linkParams)
|
||||||
@ -124,7 +121,7 @@ type SQLitePageData(conn: SqliteConnection, 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 conn
|
let! pages = conn.findByFields<Page> Table.Page Any [ webLogField webLogId ]
|
||||||
let! withRevs = pages |> List.map appendPageRevisions |> Task.WhenAll
|
let! withRevs = pages |> List.map appendPageRevisions |> Task.WhenAll
|
||||||
return List.ofArray withRevs
|
return List.ofArray withRevs
|
||||||
}
|
}
|
||||||
@ -132,18 +129,20 @@ type SQLitePageData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Get all listed pages for the given web log (without revisions or text)
|
/// Get all listed pages for the given web log (without revisions or text)
|
||||||
let findListed webLogId =
|
let findListed webLogId =
|
||||||
log.LogTrace "Page.findListed"
|
log.LogTrace "Page.findListed"
|
||||||
|
let fields = [ webLogField webLogId; Field.EQ pgListName true ]
|
||||||
conn.customList
|
conn.customList
|
||||||
$"""{Document.Query.selectByWebLog Table.Page} AND {Query.whereByField (Field.EQ pgListName "") "true"}
|
$"{Query.byFields (Query.find Table.Page) All fields} ORDER BY LOWER({titleField})"
|
||||||
ORDER BY LOWER({titleField})"""
|
(addFieldParams fields [])
|
||||||
[ webLogParam webLogId ]
|
|
||||||
(fun rdr -> { fromData<Page> rdr with Text = "" })
|
(fun rdr -> { fromData<Page> rdr with Text = "" })
|
||||||
|
|
||||||
/// Get a page of pages for the given web log (without revisions)
|
/// Get a page of pages for the given web log (without revisions)
|
||||||
let findPageOfPages webLogId pageNbr =
|
let findPageOfPages webLogId pageNbr =
|
||||||
log.LogTrace "Page.findPageOfPages"
|
log.LogTrace "Page.findPageOfPages"
|
||||||
|
let field = [ webLogField webLogId ]
|
||||||
conn.customList
|
conn.customList
|
||||||
$"{Document.Query.selectByWebLog Table.Page} ORDER BY LOWER({titleField}) LIMIT @pageSize OFFSET @toSkip"
|
$"{Query.byFields (Query.find Table.Page) Any field} ORDER BY LOWER({titleField})
|
||||||
[ webLogParam webLogId; SqliteParameter("@pageSize", 26); SqliteParameter("@toSkip", (pageNbr - 1) * 25) ]
|
LIMIT @pageSize OFFSET @toSkip"
|
||||||
|
(addFieldParams field [ sqlParam "@pageSize" 26; sqlParam "@toSkip" ((pageNbr - 1) * 25) ])
|
||||||
(fun rdr -> { pageWithoutLinks rdr with Metadata = [] })
|
(fun rdr -> { pageWithoutLinks rdr with Metadata = [] })
|
||||||
|
|
||||||
/// Update a page
|
/// Update a page
|
||||||
|
@ -3,7 +3,6 @@ namespace MyWebLog.Data.SQLite
|
|||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
|
||||||
open Microsoft.Data.Sqlite
|
open Microsoft.Data.Sqlite
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
@ -17,7 +16,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
let linkName = nameof Post.Empty.Permalink
|
let linkName = nameof Post.Empty.Permalink
|
||||||
|
|
||||||
/// The JSON field for when the post was published
|
/// The JSON field for when the post was published
|
||||||
let publishField = $"data ->> '{nameof Post.Empty.PublishedOn}'"
|
let publishField = $"data->>'{nameof Post.Empty.PublishedOn}'"
|
||||||
|
|
||||||
/// The name of the JSON field for the post's status
|
/// The name of the JSON field for the post's status
|
||||||
let statName = nameof Post.Empty.Status
|
let statName = nameof Post.Empty.Status
|
||||||
@ -44,7 +43,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
|
|
||||||
/// The SELECT statement to retrieve published posts with a web log ID parameter
|
/// The SELECT statement to retrieve published posts with a web log ID parameter
|
||||||
let publishedPostByWebLog =
|
let publishedPostByWebLog =
|
||||||
$"""{postByWebLog} AND {Query.whereByField (Field.EQ statName "") $"'{string Published}'"}"""
|
$"{postByWebLog} AND data->>'{statName}' = '{string Published}'"
|
||||||
|
|
||||||
/// Update a post's revisions
|
/// Update a post's revisions
|
||||||
let updatePostRevisions (postId: PostId) oldRevs newRevs =
|
let updatePostRevisions (postId: PostId) oldRevs newRevs =
|
||||||
@ -63,16 +62,14 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Count posts in a status for the given web log
|
/// Count posts in a status for the given web log
|
||||||
let countByStatus (status: PostStatus) webLogId =
|
let countByStatus (status: PostStatus) webLogId =
|
||||||
log.LogTrace "Post.countByStatus"
|
log.LogTrace "Post.countByStatus"
|
||||||
let statParam = Field.EQ statName (string status)
|
let fields = [ webLogField webLogId; Field.EQ statName (string status) ]
|
||||||
conn.customScalar
|
conn.customScalar
|
||||||
$"""{Document.Query.countByWebLog Table.Post} AND {Query.whereByField statParam "@status"}"""
|
(Query.byFields (Query.count Table.Post) All fields) (addFieldParams fields []) (toCount >> int)
|
||||||
(addFieldParam "@status" statParam [ webLogParam webLogId ])
|
|
||||||
(toCount >> int)
|
|
||||||
|
|
||||||
/// Find a post by its ID for the given web log (excluding revisions)
|
/// Find a post by its ID for the given web log (excluding revisions)
|
||||||
let findById postId webLogId = backgroundTask {
|
let findById (postId: PostId) webLogId = backgroundTask {
|
||||||
log.LogTrace "Post.findById"
|
log.LogTrace "Post.findById"
|
||||||
match! Document.findByIdAndWebLog<PostId, Post> Table.Post postId webLogId conn with
|
match! conn.findFirstByFields<Post> Table.Post All [ idField postId; webLogField webLogId ] with
|
||||||
| Some post -> return Some { post with PriorPermalinks = [] }
|
| Some post -> return Some { post with PriorPermalinks = [] }
|
||||||
| None -> return None
|
| None -> return None
|
||||||
}
|
}
|
||||||
@ -80,16 +77,14 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Find a post by its permalink for the given web log (excluding revisions)
|
/// Find a post by its permalink for the given web log (excluding revisions)
|
||||||
let findByPermalink (permalink: Permalink) webLogId =
|
let findByPermalink (permalink: Permalink) webLogId =
|
||||||
log.LogTrace "Post.findByPermalink"
|
log.LogTrace "Post.findByPermalink"
|
||||||
let linkParam = Field.EQ linkName (string permalink)
|
let fields = [ webLogField webLogId; Field.EQ linkName (string permalink) ]
|
||||||
conn.customSingle
|
conn.customSingle
|
||||||
$"""{Document.Query.selectByWebLog Table.Post} AND {Query.whereByField linkParam "@link"}"""
|
(Query.byFields (Query.find Table.Post) All fields) (addFieldParams fields []) postWithoutLinks
|
||||||
(addFieldParam "@link" linkParam [ webLogParam webLogId ])
|
|
||||||
postWithoutLinks
|
|
||||||
|
|
||||||
/// Find a complete post by its ID for the given web log
|
/// Find a complete post by its ID for the given web log
|
||||||
let findFullById postId webLogId = backgroundTask {
|
let findFullById postId webLogId = backgroundTask {
|
||||||
log.LogTrace "Post.findFullById"
|
log.LogTrace "Post.findFullById"
|
||||||
match! Document.findByIdAndWebLog<PostId, Post> Table.Post postId webLogId conn with
|
match! conn.findFirstByFields<Post> Table.Post All [ idField postId; webLogField webLogId ] with
|
||||||
| Some post ->
|
| Some post ->
|
||||||
let! post = appendPostRevisions post
|
let! post = appendPostRevisions post
|
||||||
return Some post
|
return Some post
|
||||||
@ -102,9 +97,11 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
match! findById postId webLogId with
|
match! findById postId webLogId with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
do! conn.customNonQuery
|
do! conn.customNonQuery
|
||||||
$"""DELETE FROM {Table.PostRevision} WHERE post_id = @id;
|
$"""{Query.delete Table.PostRevision} WHERE post_id = @id;
|
||||||
DELETE FROM {Table.PostComment}
|
{Query.byFields
|
||||||
WHERE {Query.whereByField (Field.EQ (nameof Comment.Empty.PostId) "") "@id"};
|
(Query.delete Table.PostComment)
|
||||||
|
Any
|
||||||
|
[ { Field.EQ (nameof Comment.Empty.PostId) postId with ParameterName = Some "@id" }]};
|
||||||
{Query.byId (Query.delete Table.Post) (string postId)}"""
|
{Query.byId (Query.delete Table.Post) (string postId)}"""
|
||||||
[ idParam postId ]
|
[ idParam postId ]
|
||||||
return true
|
return true
|
||||||
@ -116,7 +113,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
log.LogTrace "Post.findCurrentPermalink"
|
log.LogTrace "Post.findCurrentPermalink"
|
||||||
let linkSql, linkParams = inJsonArray Table.Post (nameof Post.Empty.PriorPermalinks) "link" permalinks
|
let linkSql, linkParams = inJsonArray Table.Post (nameof Post.Empty.PriorPermalinks) "link" permalinks
|
||||||
conn.customSingle
|
conn.customSingle
|
||||||
$"SELECT data ->> '{linkName}' AS permalink
|
$"SELECT data->>'{linkName}' AS permalink
|
||||||
FROM {Table.Post}
|
FROM {Table.Post}
|
||||||
WHERE {Document.Query.whereByWebLog} AND {linkSql}"
|
WHERE {Document.Query.whereByWebLog} AND {linkSql}"
|
||||||
(webLogParam webLogId :: linkParams)
|
(webLogParam webLogId :: linkParams)
|
||||||
@ -125,7 +122,7 @@ type SQLitePostData(conn: SqliteConnection, 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 conn
|
let! posts = conn.findByFields<Post> Table.Post Any [ webLogField webLogId ]
|
||||||
let! withRevs = posts |> List.map appendPostRevisions |> Task.WhenAll
|
let! withRevs = posts |> List.map appendPostRevisions |> Task.WhenAll
|
||||||
return List.ofArray withRevs
|
return List.ofArray withRevs
|
||||||
}
|
}
|
||||||
@ -146,7 +143,7 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
log.LogTrace "Post.findPageOfPosts"
|
log.LogTrace "Post.findPageOfPosts"
|
||||||
conn.customList
|
conn.customList
|
||||||
$"{postByWebLog}
|
$"{postByWebLog}
|
||||||
ORDER BY {publishField} DESC NULLS FIRST, data ->> '{nameof Post.Empty.UpdatedOn}'
|
ORDER BY {publishField} DESC NULLS FIRST, data->>'{nameof Post.Empty.UpdatedOn}'
|
||||||
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
|
LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}"
|
||||||
[ webLogParam webLogId ]
|
[ webLogParam webLogId ]
|
||||||
postWithoutText
|
postWithoutText
|
||||||
@ -175,15 +172,16 @@ type SQLitePostData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Find the next newest and oldest post from a publish date for the given web log
|
/// Find the next newest and oldest post from a publish date for the given web log
|
||||||
let findSurroundingPosts webLogId (publishedOn : Instant) = backgroundTask {
|
let findSurroundingPosts webLogId (publishedOn : Instant) = backgroundTask {
|
||||||
log.LogTrace "Post.findSurroundingPosts"
|
log.LogTrace "Post.findSurroundingPosts"
|
||||||
|
let parameters = [ webLogParam webLogId; sqlParam "@publishedOn" (instantParam publishedOn) ]
|
||||||
let! older =
|
let! older =
|
||||||
conn.customSingle
|
conn.customSingle
|
||||||
$"{publishedPostByWebLog} AND {publishField} < @publishedOn ORDER BY {publishField} DESC LIMIT 1"
|
$"{publishedPostByWebLog} AND {publishField} < @publishedOn ORDER BY {publishField} DESC LIMIT 1"
|
||||||
[ webLogParam webLogId; SqliteParameter("@publishedOn", instantParam publishedOn) ]
|
parameters
|
||||||
postWithoutLinks
|
postWithoutLinks
|
||||||
let! newer =
|
let! newer =
|
||||||
conn.customSingle
|
conn.customSingle
|
||||||
$"{publishedPostByWebLog} AND {publishField} > @publishedOn ORDER BY {publishField} LIMIT 1"
|
$"{publishedPostByWebLog} AND {publishField} > @publishedOn ORDER BY {publishField} LIMIT 1"
|
||||||
[ webLogParam webLogId; SqliteParameter("@publishedOn", instantParam publishedOn) ]
|
parameters
|
||||||
postWithoutLinks
|
postWithoutLinks
|
||||||
return older, newer
|
return older, newer
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ namespace MyWebLog.Data.SQLite
|
|||||||
|
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
|
||||||
open Microsoft.Data.Sqlite
|
open Microsoft.Data.Sqlite
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
@ -12,9 +11,9 @@ open MyWebLog.Data
|
|||||||
type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) =
|
type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) =
|
||||||
|
|
||||||
/// Find a tag mapping by its ID for the given web log
|
/// Find a tag mapping by its ID for the given web log
|
||||||
let findById tagMapId webLogId =
|
let findById (tagMapId: TagMapId) webLogId =
|
||||||
log.LogTrace "TagMap.findById"
|
log.LogTrace "TagMap.findById"
|
||||||
Document.findByIdAndWebLog<TagMapId, TagMap> Table.TagMap tagMapId webLogId conn
|
conn.findFirstByFields<TagMap> Table.TagMap All [ idField tagMapId; webLogField webLogId ]
|
||||||
|
|
||||||
/// Delete a tag mapping for the given web log
|
/// Delete a tag mapping for the given web log
|
||||||
let delete tagMapId webLogId = backgroundTask {
|
let delete tagMapId webLogId = backgroundTask {
|
||||||
@ -29,21 +28,18 @@ type SQLiteTagMapData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Find a tag mapping by its URL value for the given web log
|
/// Find a tag mapping by its URL value for the given web log
|
||||||
let findByUrlValue (urlValue: string) webLogId =
|
let findByUrlValue (urlValue: string) webLogId =
|
||||||
log.LogTrace "TagMap.findByUrlValue"
|
log.LogTrace "TagMap.findByUrlValue"
|
||||||
let urlParam = Field.EQ (nameof TagMap.Empty.UrlValue) urlValue
|
conn.findFirstByFields<TagMap>
|
||||||
conn.customSingle
|
Table.TagMap All [ webLogField webLogId; Field.EQ (nameof TagMap.Empty.UrlValue) urlValue ]
|
||||||
$"""{Document.Query.selectByWebLog Table.TagMap} AND {Query.whereByField urlParam "@urlValue"}"""
|
|
||||||
(addFieldParam "@urlValue" urlParam [ webLogParam webLogId ])
|
|
||||||
fromData<TagMap>
|
|
||||||
|
|
||||||
/// 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"
|
||||||
Document.findByWebLog<TagMap> Table.TagMap webLogId conn
|
conn.findByFields<TagMap> Table.TagMap Any [ webLogField webLogId ]
|
||||||
|
|
||||||
/// 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: string list) webLogId =
|
let findMappingForTags (tags: string list) webLogId =
|
||||||
log.LogTrace "TagMap.findMappingForTags"
|
log.LogTrace "TagMap.findMappingForTags"
|
||||||
let mapSql, mapParams = inClause $"AND data ->> '{nameof TagMap.Empty.Tag}'" "tag" id tags
|
let mapSql, mapParams = inClause $"AND data->>'{nameof TagMap.Empty.Tag}'" "tag" id tags
|
||||||
conn.customList
|
conn.customList
|
||||||
$"{Document.Query.selectByWebLog Table.TagMap} {mapSql}"
|
$"{Document.Query.selectByWebLog Table.TagMap} {mapSql}"
|
||||||
(webLogParam webLogId :: mapParams)
|
(webLogParam webLogId :: mapParams)
|
||||||
|
@ -11,7 +11,7 @@ open MyWebLog.Data
|
|||||||
type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
|
type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
|
||||||
|
|
||||||
/// The JSON field for the theme ID
|
/// The JSON field for the theme ID
|
||||||
let idField = $"data ->> '{nameof Theme.Empty.Id}'"
|
let idField = $"data->>'{nameof Theme.Empty.Id}'"
|
||||||
|
|
||||||
/// Convert a document to a theme with no template text
|
/// Convert a document to a theme with no template text
|
||||||
let withoutTemplateText (rdr: SqliteDataReader) =
|
let withoutTemplateText (rdr: SqliteDataReader) =
|
||||||
@ -48,7 +48,7 @@ type SQLiteThemeData(conn : SqliteConnection, log: ILogger) =
|
|||||||
match! findByIdWithoutText themeId with
|
match! findByIdWithoutText themeId with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
do! conn.customNonQuery
|
do! conn.customNonQuery
|
||||||
$"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id;
|
$"{Query.delete Table.ThemeAsset} WHERE theme_id = @id;
|
||||||
{Query.byId (Query.delete Table.Theme) (string themeId)}"
|
{Query.byId (Query.delete Table.Theme) (string themeId)}"
|
||||||
[ idParam themeId ]
|
[ idParam themeId ]
|
||||||
return true
|
return true
|
||||||
@ -87,7 +87,7 @@ type SQLiteThemeAssetData(conn : SqliteConnection, 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"
|
||||||
conn.customNonQuery $"DELETE FROM {Table.ThemeAsset} WHERE theme_id = @id" [ idParam themeId ]
|
conn.customNonQuery $"{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 =
|
||||||
|
@ -2,7 +2,6 @@ namespace MyWebLog.Data.SQLite
|
|||||||
|
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
|
||||||
open Microsoft.Data.Sqlite
|
open Microsoft.Data.Sqlite
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
@ -24,25 +23,25 @@ type SQLiteWebLogData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Delete a web log by its ID
|
/// Delete a web log by its ID
|
||||||
let delete webLogId =
|
let delete webLogId =
|
||||||
log.LogTrace "WebLog.delete"
|
log.LogTrace "WebLog.delete"
|
||||||
let webLogMatches = Query.whereByField (Field.EQ "WebLogId" "") "@webLogId"
|
let webLogMatches = Query.whereByFields Any [ { Field.EQ "WebLogId" "" with ParameterName = Some "@webLogId" } ]
|
||||||
let subQuery table = $"(SELECT data ->> 'Id' FROM {table} WHERE {webLogMatches})"
|
let subQuery table = $"(SELECT data->>'Id' FROM {table} WHERE {webLogMatches})"
|
||||||
Custom.nonQuery
|
Custom.nonQuery
|
||||||
$"""DELETE FROM {Table.PostComment} WHERE data ->> 'PostId' IN {subQuery Table.Post};
|
$"""{Query.delete Table.PostComment} WHERE data ->> 'PostId' IN {subQuery Table.Post};
|
||||||
DELETE FROM {Table.PostRevision} WHERE post_id IN {subQuery Table.Post};
|
{Query.delete Table.PostRevision} WHERE post_id IN {subQuery Table.Post};
|
||||||
DELETE FROM {Table.PageRevision} WHERE page_id IN {subQuery Table.Page};
|
{Query.delete Table.PageRevision} WHERE page_id IN {subQuery Table.Page};
|
||||||
DELETE FROM {Table.Post} WHERE {webLogMatches};
|
{Query.delete Table.Post} WHERE {webLogMatches};
|
||||||
DELETE FROM {Table.Page} WHERE {webLogMatches};
|
{Query.delete Table.Page} WHERE {webLogMatches};
|
||||||
DELETE FROM {Table.Category} WHERE {webLogMatches};
|
{Query.delete Table.Category} WHERE {webLogMatches};
|
||||||
DELETE FROM {Table.TagMap} WHERE {webLogMatches};
|
{Query.delete Table.TagMap} WHERE {webLogMatches};
|
||||||
DELETE FROM {Table.Upload} WHERE web_log_id = @webLogId;
|
{Query.delete Table.Upload} WHERE web_log_id = @webLogId;
|
||||||
DELETE FROM {Table.WebLogUser} WHERE {webLogMatches};
|
{Query.delete Table.WebLogUser} WHERE {webLogMatches};
|
||||||
DELETE FROM {Table.WebLog} WHERE {Query.whereById "@webLogId"}"""
|
{Query.delete Table.WebLog} WHERE {Query.whereById "@webLogId"}"""
|
||||||
[ webLogParam webLogId ]
|
[ webLogParam webLogId ]
|
||||||
|
|
||||||
/// Find a web log by its host (URL base)
|
/// Find a web log by its host (URL base)
|
||||||
let findByHost (url: string) =
|
let findByHost (url: string) =
|
||||||
log.LogTrace "WebLog.findByHost"
|
log.LogTrace "WebLog.findByHost"
|
||||||
conn.findFirstByField<WebLog> Table.WebLog (Field.EQ (nameof WebLog.Empty.UrlBase) url)
|
conn.findFirstByFields<WebLog> Table.WebLog Any [ Field.EQ (nameof WebLog.Empty.UrlBase) url ]
|
||||||
|
|
||||||
/// Find a web log by its ID
|
/// Find a web log by its ID
|
||||||
let findById webLogId =
|
let findById webLogId =
|
||||||
|
@ -2,7 +2,6 @@ namespace MyWebLog.Data.SQLite
|
|||||||
|
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Sqlite.Compat
|
|
||||||
open Microsoft.Data.Sqlite
|
open Microsoft.Data.Sqlite
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MyWebLog
|
open MyWebLog
|
||||||
@ -17,17 +16,18 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) =
|
|||||||
conn.insert<WebLogUser> Table.WebLogUser user
|
conn.insert<WebLogUser> Table.WebLogUser user
|
||||||
|
|
||||||
/// Find a user by their ID for the given web log
|
/// Find a user by their ID for the given web log
|
||||||
let findById userId webLogId =
|
let findById (userId: WebLogUserId) webLogId =
|
||||||
log.LogTrace "WebLogUser.findById"
|
log.LogTrace "WebLogUser.findById"
|
||||||
Document.findByIdAndWebLog<WebLogUserId, WebLogUser> Table.WebLogUser userId webLogId conn
|
conn.findFirstByFields<WebLogUser> Table.WebLogUser All [ idField userId; webLogField webLogId ]
|
||||||
|
|
||||||
/// Delete a user if they have no posts or pages
|
/// Delete a user if they have no posts or pages
|
||||||
let delete userId webLogId = backgroundTask {
|
let delete userId webLogId = backgroundTask {
|
||||||
log.LogTrace "WebLogUser.delete"
|
log.LogTrace "WebLogUser.delete"
|
||||||
match! findById userId webLogId with
|
match! findById userId webLogId with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
let! pageCount = conn.countByField Table.Page (Field.EQ (nameof Page.Empty.AuthorId) (string userId))
|
let author = [ Field.EQ (nameof Page.Empty.AuthorId) (string userId) ]
|
||||||
let! postCount = conn.countByField Table.Post (Field.EQ (nameof Post.Empty.AuthorId) (string userId))
|
let! pageCount = conn.countByFields Table.Page Any author
|
||||||
|
let! postCount = conn.countByFields Table.Post Any author
|
||||||
if pageCount + postCount > 0 then
|
if pageCount + postCount > 0 then
|
||||||
return Error "User has pages or posts; cannot delete"
|
return Error "User has pages or posts; cannot delete"
|
||||||
else
|
else
|
||||||
@ -39,24 +39,20 @@ type SQLiteWebLogUserData(conn: SqliteConnection, log: ILogger) =
|
|||||||
/// Find a user by their e-mail address for the given web log
|
/// Find a user by their e-mail address for the given web log
|
||||||
let findByEmail (email: string) webLogId =
|
let findByEmail (email: string) webLogId =
|
||||||
log.LogTrace "WebLogUser.findByEmail"
|
log.LogTrace "WebLogUser.findByEmail"
|
||||||
let emailParam = Field.EQ (nameof WebLogUser.Empty.Email) email
|
conn.findFirstByFields
|
||||||
conn.customSingle
|
Table.WebLogUser All [ webLogField webLogId; Field.EQ (nameof WebLogUser.Empty.Email) email ]
|
||||||
$"""{Document.Query.selectByWebLog Table.WebLogUser}
|
|
||||||
AND {Query.whereByField emailParam "@email"}"""
|
|
||||||
(addFieldParam "@email" emailParam [ webLogParam webLogId ])
|
|
||||||
fromData<WebLogUser>
|
|
||||||
|
|
||||||
/// Get all users for the given web log
|
/// Get all users for the given web log
|
||||||
let findByWebLog webLogId = backgroundTask {
|
let findByWebLog webLogId = backgroundTask {
|
||||||
log.LogTrace "WebLogUser.findByWebLog"
|
log.LogTrace "WebLogUser.findByWebLog"
|
||||||
let! users = Document.findByWebLog<WebLogUser> Table.WebLogUser webLogId conn
|
let! users = conn.findByFields<WebLogUser> Table.WebLogUser Any [ webLogField webLogId ]
|
||||||
return users |> List.sortBy _.PreferredName.ToLowerInvariant()
|
return users |> List.sortBy _.PreferredName.ToLowerInvariant()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) =
|
let findNames webLogId (userIds: WebLogUserId list) =
|
||||||
log.LogTrace "WebLogUser.findNames"
|
log.LogTrace "WebLogUser.findNames"
|
||||||
let nameSql, nameParams = inClause $"AND data ->> '{nameof WebLogUser.Empty.Id}'" "id" string userIds
|
let nameSql, nameParams = inClause $"AND data->>'{nameof WebLogUser.Empty.Id}'" "id" string userIds
|
||||||
conn.customList
|
conn.customList
|
||||||
$"{Document.Query.selectByWebLog Table.WebLogUser} {nameSql}"
|
$"{Document.Query.selectByWebLog Table.WebLogUser} {nameSql}"
|
||||||
(webLogParam webLogId :: nameParams)
|
(webLogParam webLogId :: nameParams)
|
||||||
|
Loading…
Reference in New Issue
Block a user