Daniel J. Summers 202fca272e Prefer seq over list for parameters
- This greatly reduces the duplicated functions needed
between F# and C#; F# lists satisfy the sequence reqs
2024-08-08 17:32:44 -04:00

446 lines
24 KiB
Forth

namespace BitBadger.Documents.Postgres
open Npgsql
open Npgsql.FSharp
/// F# Extensions for the NpgsqlConnection type
[<AutoOpen>]
module Extensions =
type NpgsqlConnection with
/// Execute a query that returns a list of results
member conn.customList<'TDoc> query parameters (mapFunc: RowReader -> 'TDoc) =
WithProps.Custom.list<'TDoc> query parameters mapFunc (Sql.existingConnection conn)
/// Execute a query that returns one or no results; returns None if not found
member conn.customSingle<'TDoc> query parameters (mapFunc: RowReader -> 'TDoc) =
WithProps.Custom.single<'TDoc> query parameters mapFunc (Sql.existingConnection conn)
/// Execute a query that returns no results
member conn.customNonQuery query parameters =
WithProps.Custom.nonQuery query parameters (Sql.existingConnection conn)
/// Execute a query that returns a scalar value
member conn.customScalar<'T when 'T: struct> query parameters (mapFunc: RowReader -> 'T) =
WithProps.Custom.scalar query parameters mapFunc (Sql.existingConnection conn)
/// Create a document table
member conn.ensureTable name =
WithProps.Definition.ensureTable name (Sql.existingConnection conn)
/// Create an index on documents in the specified table
member conn.ensureDocumentIndex name idxType =
WithProps.Definition.ensureDocumentIndex name idxType (Sql.existingConnection conn)
/// Create an index on field(s) within documents in the specified table
member conn.ensureFieldIndex tableName indexName fields =
WithProps.Definition.ensureFieldIndex tableName indexName fields (Sql.existingConnection conn)
/// Insert a new document
member conn.insert<'TDoc> tableName (document: 'TDoc) =
WithProps.Document.insert<'TDoc> tableName document (Sql.existingConnection conn)
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
member conn.save<'TDoc> tableName (document: 'TDoc) =
WithProps.Document.save<'TDoc> tableName document (Sql.existingConnection conn)
/// Count all documents in a table
member conn.countAll tableName =
WithProps.Count.all tableName (Sql.existingConnection conn)
/// Count matching documents using a JSON field comparison query (->> =)
member conn.countByFields tableName howMatched fields =
WithProps.Count.byFields tableName howMatched fields (Sql.existingConnection conn)
/// Count matching documents using a JSON field comparison query (->> =)
[<System.Obsolete "Use countByFields instead; will be removed in v4">]
member conn.countByField tableName field =
WithProps.Count.byField tableName field (Sql.existingConnection conn)
/// Count matching documents using a JSON containment query (@>)
member conn.countByContains tableName criteria =
WithProps.Count.byContains tableName criteria (Sql.existingConnection conn)
/// Count matching documents using a JSON Path match query (@?)
member conn.countByJsonPath tableName jsonPath =
WithProps.Count.byJsonPath tableName jsonPath (Sql.existingConnection conn)
/// Determine if a document exists for the given ID
member conn.existsById tableName docId =
WithProps.Exists.byId tableName docId (Sql.existingConnection conn)
/// Determine if documents exist using a JSON field comparison query (->> =)
member conn.existsByFields tableName howMatched fields =
WithProps.Exists.byFields tableName howMatched fields (Sql.existingConnection conn)
/// Determine if documents exist using a JSON field comparison query (->> =)
[<System.Obsolete "Use existsByFields instead; will be removed in v4">]
member conn.existsByField tableName field =
WithProps.Exists.byField tableName field (Sql.existingConnection conn)
/// Determine if documents exist using a JSON containment query (@>)
member conn.existsByContains tableName criteria =
WithProps.Exists.byContains tableName criteria (Sql.existingConnection conn)
/// Determine if documents exist using a JSON Path match query (@?)
member conn.existsByJsonPath tableName jsonPath =
WithProps.Exists.byJsonPath tableName jsonPath (Sql.existingConnection conn)
/// Retrieve all documents in the given table
member conn.findAll<'TDoc> tableName =
WithProps.Find.all<'TDoc> tableName (Sql.existingConnection conn)
/// Retrieve a document by its ID; returns None if not found
member conn.findById<'TKey, 'TDoc> tableName docId =
WithProps.Find.byId<'TKey, 'TDoc> tableName docId (Sql.existingConnection conn)
/// Retrieve documents matching a JSON field comparison query (->> =)
member conn.findByFields<'TDoc> tableName howMatched fields =
WithProps.Find.byFields<'TDoc> tableName howMatched fields (Sql.existingConnection conn)
/// Retrieve documents matching a JSON field comparison query (->> =)
[<System.Obsolete "Use findByFields instead; will be removed in v4">]
member conn.findByField<'TDoc> tableName field =
WithProps.Find.byField<'TDoc> tableName field (Sql.existingConnection conn)
/// Retrieve documents matching a JSON containment query (@>)
member conn.findByContains<'TDoc> tableName (criteria: obj) =
WithProps.Find.byContains<'TDoc> tableName criteria (Sql.existingConnection conn)
/// Retrieve documents matching a JSON Path match query (@?)
member conn.findByJsonPath<'TDoc> tableName jsonPath =
WithProps.Find.byJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn)
/// Retrieve the first document matching a JSON field comparison query (->> =); returns None if not found
member conn.findFirstByFields<'TDoc> tableName howMatched fields =
WithProps.Find.firstByFields<'TDoc> tableName howMatched fields (Sql.existingConnection conn)
/// Retrieve the first document matching a JSON field comparison query (->> =); returns None if not found
[<System.Obsolete "Use findFirstByFields instead; will be removed in v4">]
member conn.findFirstByField<'TDoc> tableName field =
WithProps.Find.firstByField<'TDoc> tableName field (Sql.existingConnection conn)
/// Retrieve the first document matching a JSON containment query (@>); returns None if not found
member conn.findFirstByContains<'TDoc> tableName (criteria: obj) =
WithProps.Find.firstByContains<'TDoc> tableName criteria (Sql.existingConnection conn)
/// Retrieve the first document matching a JSON Path match query (@?); returns None if not found
member conn.findFirstByJsonPath<'TDoc> tableName jsonPath =
WithProps.Find.firstByJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn)
/// Update an entire document by its ID
member conn.updateById tableName (docId: 'TKey) (document: 'TDoc) =
WithProps.Update.byId tableName docId document (Sql.existingConnection conn)
/// Update an entire document by its ID, using the provided function to obtain the ID from the document
member conn.updateByFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) =
WithProps.Update.byFunc tableName idFunc document (Sql.existingConnection conn)
/// Patch a document by its ID
member conn.patchById tableName (docId: 'TKey) (patch: 'TPatch) =
WithProps.Patch.byId tableName docId patch (Sql.existingConnection conn)
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
member conn.patchByFields tableName howMatched fields (patch: 'TPatch) =
WithProps.Patch.byFields tableName howMatched fields patch (Sql.existingConnection conn)
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<System.Obsolete "Use patchByFields instead; will be removed in v4">]
member conn.patchByField tableName field (patch: 'TPatch) =
WithProps.Patch.byField tableName field patch (Sql.existingConnection conn)
/// Patch documents using a JSON containment query in the WHERE clause (@>)
member conn.patchByContains tableName (criteria: 'TCriteria) (patch: 'TPatch) =
WithProps.Patch.byContains tableName criteria patch (Sql.existingConnection conn)
/// Patch documents using a JSON Path match query in the WHERE clause (@?)
member conn.patchByJsonPath tableName jsonPath (patch: 'TPatch) =
WithProps.Patch.byJsonPath tableName jsonPath patch (Sql.existingConnection conn)
/// Remove fields from a document by the document's ID
member conn.removeFieldsById tableName (docId: 'TKey) fieldNames =
WithProps.RemoveFields.byId tableName docId fieldNames (Sql.existingConnection conn)
/// Remove fields from documents via a comparison on JSON fields in the document
member conn.removeFieldsByFields tableName howMatched fields fieldNames =
WithProps.RemoveFields.byFields tableName howMatched fields fieldNames (Sql.existingConnection conn)
/// Remove fields from documents via a comparison on a JSON field in the document
[<System.Obsolete "Use removeFieldsByFields instead; will be removed in v4">]
member conn.removeFieldsByField tableName field fieldNames =
WithProps.RemoveFields.byField tableName field fieldNames (Sql.existingConnection conn)
/// Remove fields from documents via a JSON containment query (@>)
member conn.removeFieldsByContains tableName (criteria: 'TContains) fieldNames =
WithProps.RemoveFields.byContains tableName criteria fieldNames (Sql.existingConnection conn)
/// Remove fields from documents via a JSON Path match query (@?)
member conn.removeFieldsByJsonPath tableName jsonPath fieldNames =
WithProps.RemoveFields.byJsonPath tableName jsonPath fieldNames (Sql.existingConnection conn)
/// Delete a document by its ID
member conn.deleteById tableName (docId: 'TKey) =
WithProps.Delete.byId tableName docId (Sql.existingConnection conn)
member conn.deleteByFields tableName howMatched fields =
WithProps.Delete.byFields tableName howMatched fields (Sql.existingConnection conn)
/// Delete documents by matching a JSON field comparison query (->> =)
[<System.Obsolete "Use deleteByFields instead; will be removed in v4">]
member conn.deleteByField tableName field =
WithProps.Delete.byField tableName field (Sql.existingConnection conn)
/// Delete documents by matching a JSON containment query (@>)
member conn.deleteByContains tableName (criteria: 'TContains) =
WithProps.Delete.byContains tableName criteria (Sql.existingConnection conn)
/// Delete documents by matching a JSON Path match query (@?)
member conn.deleteByJsonPath tableName path =
WithProps.Delete.byJsonPath tableName path (Sql.existingConnection conn)
open System.Runtime.CompilerServices
/// C# extensions on the NpgsqlConnection type
type NpgsqlConnectionCSharpExtensions =
/// Execute a query that returns a list of results
[<Extension>]
static member inline CustomList<'TDoc>(conn, query, parameters, mapFunc: System.Func<RowReader, 'TDoc>) =
WithProps.Custom.List<'TDoc>(query, parameters, mapFunc, Sql.existingConnection conn)
/// Execute a query that returns one or no results; returns None if not found
[<Extension>]
static member inline CustomSingle<'TDoc when 'TDoc: null>(
conn, query, parameters, mapFunc: System.Func<RowReader, 'TDoc>) =
WithProps.Custom.Single<'TDoc>(query, parameters, mapFunc, Sql.existingConnection conn)
/// Execute a query that returns no results
[<Extension>]
static member inline CustomNonQuery(conn, query, parameters) =
WithProps.Custom.nonQuery query parameters (Sql.existingConnection conn)
/// Execute a query that returns a scalar value
[<Extension>]
static member inline CustomScalar<'T when 'T: struct>(
conn, query, parameters, mapFunc: System.Func<RowReader, 'T>) =
WithProps.Custom.Scalar(query, parameters, mapFunc, Sql.existingConnection conn)
/// Create a document table
[<Extension>]
static member inline EnsureTable(conn, name) =
WithProps.Definition.ensureTable name (Sql.existingConnection conn)
/// Create an index on documents in the specified table
[<Extension>]
static member inline EnsureDocumentIndex(conn, name, idxType) =
WithProps.Definition.ensureDocumentIndex name idxType (Sql.existingConnection conn)
/// Create an index on field(s) within documents in the specified table
[<Extension>]
static member inline EnsureFieldIndex(conn, tableName, indexName, fields) =
WithProps.Definition.ensureFieldIndex tableName indexName fields (Sql.existingConnection conn)
/// Insert a new document
[<Extension>]
static member inline Insert<'TDoc>(conn, tableName, document: 'TDoc) =
WithProps.Document.insert<'TDoc> tableName document (Sql.existingConnection conn)
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
[<Extension>]
static member inline Save<'TDoc>(conn, tableName, document: 'TDoc) =
WithProps.Document.save<'TDoc> tableName document (Sql.existingConnection conn)
/// Count all documents in a table
[<Extension>]
static member inline CountAll(conn, tableName) =
WithProps.Count.all tableName (Sql.existingConnection conn)
/// Count matching documents using a JSON field comparison query (->> =)
[<Extension>]
static member inline CountByFields(conn, tableName, howMatched, fields) =
WithProps.Count.byFields tableName howMatched fields (Sql.existingConnection conn)
/// Count matching documents using a JSON field comparison query (->> =)
[<Extension>]
[<System.Obsolete "Use CountByFields instead; will be removed in v4">]
static member inline CountByField(conn, tableName, field) =
WithProps.Count.byField tableName field (Sql.existingConnection conn)
/// Count matching documents using a JSON containment query (@>)
[<Extension>]
static member inline CountByContains(conn, tableName, criteria: 'TCriteria) =
WithProps.Count.byContains tableName criteria (Sql.existingConnection conn)
/// Count matching documents using a JSON Path match query (@?)
[<Extension>]
static member inline CountByJsonPath(conn, tableName, jsonPath) =
WithProps.Count.byJsonPath tableName jsonPath (Sql.existingConnection conn)
/// Determine if a document exists for the given ID
[<Extension>]
static member inline ExistsById(conn, tableName, docId) =
WithProps.Exists.byId tableName docId (Sql.existingConnection conn)
/// Determine if documents exist using a JSON field comparison query (->> =)
[<Extension>]
static member inline ExistsByFields(conn, tableName, howMatched, fields) =
WithProps.Exists.byFields tableName howMatched fields (Sql.existingConnection conn)
/// Determine if documents exist using a JSON field comparison query (->> =)
[<Extension>]
[<System.Obsolete "Use ExistsByFields instead; will be removed in v4">]
static member inline ExistsByField(conn, tableName, field) =
WithProps.Exists.byField tableName field (Sql.existingConnection conn)
/// Determine if documents exist using a JSON containment query (@>)
[<Extension>]
static member inline ExistsByContains(conn, tableName, criteria: 'TCriteria) =
WithProps.Exists.byContains tableName criteria (Sql.existingConnection conn)
/// Determine if documents exist using a JSON Path match query (@?)
[<Extension>]
static member inline ExistsByJsonPath(conn, tableName, jsonPath) =
WithProps.Exists.byJsonPath tableName jsonPath (Sql.existingConnection conn)
/// Retrieve all documents in the given table
[<Extension>]
static member inline FindAll<'TDoc>(conn, tableName) =
WithProps.Find.All<'TDoc>(tableName, Sql.existingConnection conn)
/// Retrieve a document by its ID; returns None if not found
[<Extension>]
static member inline FindById<'TKey, 'TDoc when 'TDoc: null>(conn, tableName, docId: 'TKey) =
WithProps.Find.ById<'TKey, 'TDoc>(tableName, docId, Sql.existingConnection conn)
/// Retrieve documents matching a JSON field comparison query (->> =)
[<Extension>]
static member inline FindByFields<'TDoc>(conn, tableName, howMatched, fields) =
WithProps.Find.ByFields<'TDoc>(tableName, howMatched, fields, Sql.existingConnection conn)
/// Retrieve documents matching a JSON field comparison query (->> =)
[<Extension>]
[<System.Obsolete "Use FindByFields instead; will be removed in v4">]
static member inline FindByField<'TDoc>(conn, tableName, field) =
WithProps.Find.ByField<'TDoc>(tableName, field, Sql.existingConnection conn)
/// Retrieve documents matching a JSON containment query (@>)
[<Extension>]
static member inline FindByContains<'TDoc>(conn, tableName, criteria: obj) =
WithProps.Find.ByContains<'TDoc>(tableName, criteria, Sql.existingConnection conn)
/// Retrieve documents matching a JSON Path match query (@?)
[<Extension>]
static member inline FindByJsonPath<'TDoc>(conn, tableName, jsonPath) =
WithProps.Find.ByJsonPath<'TDoc>(tableName, jsonPath, Sql.existingConnection conn)
/// Retrieve the first document matching a JSON field comparison query (->> =); returns null if not found
[<Extension>]
static member inline FindFirstByFields<'TDoc when 'TDoc: null>(conn, tableName, howMatched, fields) =
WithProps.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, Sql.existingConnection conn)
/// Retrieve the first document matching a JSON field comparison query (->> =); returns null if not found
[<Extension>]
[<System.Obsolete "Use FindFirstByFields instead; will be removed in v4">]
static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) =
WithProps.Find.FirstByField<'TDoc>(tableName, field, Sql.existingConnection conn)
/// Retrieve the first document matching a JSON containment query (@>); returns None if not found
[<Extension>]
static member inline FindFirstByContains<'TDoc when 'TDoc: null>(conn, tableName, criteria: obj) =
WithProps.Find.FirstByContains<'TDoc>(tableName, criteria, Sql.existingConnection conn)
/// Retrieve the first document matching a JSON Path match query (@?); returns None if not found
[<Extension>]
static member inline FindFirstByJsonPath<'TDoc when 'TDoc: null>(conn, tableName, jsonPath) =
WithProps.Find.FirstByJsonPath<'TDoc>(tableName, jsonPath, Sql.existingConnection conn)
/// Update an entire document by its ID
[<Extension>]
static member inline UpdateById(conn, tableName, docId: 'TKey, document: 'TDoc) =
WithProps.Update.byId tableName docId document (Sql.existingConnection conn)
/// Update an entire document by its ID, using the provided function to obtain the ID from the document
[<Extension>]
static member inline UpdateByFunc(conn, tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) =
WithProps.Update.ByFunc(tableName, idFunc, document, Sql.existingConnection conn)
/// Patch a document by its ID
[<Extension>]
static member inline PatchById(conn, tableName, docId: 'TKey, patch: 'TPatch) =
WithProps.Patch.byId tableName docId patch (Sql.existingConnection conn)
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<Extension>]
static member inline PatchByFields(conn, tableName, howMatched, fields, patch: 'TPatch) =
WithProps.Patch.byFields tableName howMatched fields patch (Sql.existingConnection conn)
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<Extension>]
[<System.Obsolete "Use PatchByFields instead; will be removed in v4">]
static member inline PatchByField(conn, tableName, field, patch: 'TPatch) =
WithProps.Patch.byField tableName field patch (Sql.existingConnection conn)
/// Patch documents using a JSON containment query in the WHERE clause (@>)
[<Extension>]
static member inline PatchByContains(conn, tableName, criteria: 'TCriteria, patch: 'TPatch) =
WithProps.Patch.byContains tableName criteria patch (Sql.existingConnection conn)
/// Patch documents using a JSON Path match query in the WHERE clause (@?)
[<Extension>]
static member inline PatchByJsonPath(conn, tableName, jsonPath, patch: 'TPatch) =
WithProps.Patch.byJsonPath tableName jsonPath patch (Sql.existingConnection conn)
/// Remove fields from a document by the document's ID
[<Extension>]
static member inline RemoveFieldsById(conn, tableName, docId: 'TKey, fieldNames) =
WithProps.RemoveFields.ById(tableName, docId, fieldNames, Sql.existingConnection conn)
/// Remove fields from documents via a comparison on JSON fields in the document
[<Extension>]
static member inline RemoveFieldsByFields(conn, tableName, howMatched, fields, fieldNames) =
WithProps.RemoveFields.byFields tableName howMatched fields fieldNames (Sql.existingConnection conn)
/// Remove fields from documents via a comparison on a JSON field in the document
[<Extension>]
[<System.Obsolete "Use RemoveFieldsByFields instead; will be removed in v4">]
static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) =
WithProps.RemoveFields.byField tableName field fieldNames (Sql.existingConnection conn)
/// Remove fields from documents via a JSON containment query (@>)
[<Extension>]
static member inline RemoveFieldsByContains(conn, tableName, criteria: 'TContains, fieldNames) =
WithProps.RemoveFields.ByContains(tableName, criteria, fieldNames, Sql.existingConnection conn)
/// Remove fields from documents via a JSON Path match query (@?)
[<Extension>]
static member inline RemoveFieldsByJsonPath(conn, tableName, jsonPath, fieldNames) =
WithProps.RemoveFields.ByJsonPath(tableName, jsonPath, fieldNames, Sql.existingConnection conn)
/// Delete a document by its ID
[<Extension>]
static member inline DeleteById(conn, tableName, docId: 'TKey) =
WithProps.Delete.byId tableName docId (Sql.existingConnection conn)
/// Delete documents by matching a JSON field comparison query (->> =)
[<Extension>]
static member inline DeleteByFields(conn, tableName, howMatched, fields) =
WithProps.Delete.byFields tableName howMatched fields (Sql.existingConnection conn)
/// Delete documents by matching a JSON field comparison query (->> =)
[<Extension>]
[<System.Obsolete "Use DeleteByFields instead; will be removed in v4">]
static member inline DeleteByField(conn, tableName, field) =
WithProps.Delete.byField tableName field (Sql.existingConnection conn)
/// Delete documents by matching a JSON containment query (@>)
[<Extension>]
static member inline DeleteByContains(conn, tableName, criteria: 'TContains) =
WithProps.Delete.byContains tableName criteria (Sql.existingConnection conn)
/// Delete documents by matching a JSON Path match query (@?)
[<Extension>]
static member inline DeleteByJsonPath(conn, tableName, path) =
WithProps.Delete.byJsonPath tableName path (Sql.existingConnection conn)