Version 4 #6
src
@ -214,11 +214,6 @@ module Query =
 | 
				
			|||||||
    let statementWhere statement where =
 | 
					    let statementWhere statement where =
 | 
				
			||||||
        $"%s{statement} WHERE %s{where}"
 | 
					        $"%s{statement} WHERE %s{where}"
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Create a SELECT clause to retrieve the document data from the given table
 | 
					 | 
				
			||||||
    [<CompiledName "SelectFromTable">]
 | 
					 | 
				
			||||||
    let selectFromTable tableName =
 | 
					 | 
				
			||||||
        $"SELECT data FROM %s{tableName}"
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Queries to define tables and indexes
 | 
					    /// Queries to define tables and indexes
 | 
				
			||||||
    module Definition =
 | 
					    module Definition =
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -263,11 +258,6 @@ module Query =
 | 
				
			|||||||
            "INSERT INTO %s VALUES (@data) ON CONFLICT ((data->>'%s')) DO UPDATE SET data = EXCLUDED.data"
 | 
					            "INSERT INTO %s VALUES (@data) ON CONFLICT ((data->>'%s')) DO UPDATE SET data = EXCLUDED.data"
 | 
				
			||||||
            tableName (Configuration.idField ()) 
 | 
					            tableName (Configuration.idField ()) 
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Query to update a document (no WHERE clause)
 | 
					 | 
				
			||||||
    [<CompiledName "Update">]
 | 
					 | 
				
			||||||
    let update tableName =
 | 
					 | 
				
			||||||
        $"UPDATE %s{tableName} SET data = @data"
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Query to count documents in a table (no WHERE clause)
 | 
					    /// Query to count documents in a table (no WHERE clause)
 | 
				
			||||||
    [<CompiledName "Count">]
 | 
					    [<CompiledName "Count">]
 | 
				
			||||||
    let count tableName =
 | 
					    let count tableName =
 | 
				
			||||||
@ -277,3 +267,24 @@ module Query =
 | 
				
			|||||||
    [<CompiledName "Exists">]
 | 
					    [<CompiledName "Exists">]
 | 
				
			||||||
    let exists tableName where =
 | 
					    let exists tableName where =
 | 
				
			||||||
        $"SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE %s{where}) AS it"
 | 
					        $"SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE %s{where}) AS it"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Query to select documents from a table (no WHERE clause)
 | 
				
			||||||
 | 
					    [<CompiledName "Find">]
 | 
				
			||||||
 | 
					    let find tableName =
 | 
				
			||||||
 | 
					        $"SELECT data FROM %s{tableName}"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Query to update a document (no WHERE clause)
 | 
				
			||||||
 | 
					    [<CompiledName "Update">]
 | 
				
			||||||
 | 
					    let update tableName =
 | 
				
			||||||
 | 
					        $"UPDATE %s{tableName} SET data = @data"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Query to delete documents from a table (no WHERE clause)
 | 
				
			||||||
 | 
					    [<CompiledName "Delete">]
 | 
				
			||||||
 | 
					    let delete tableName =
 | 
				
			||||||
 | 
					        $"DELETE FROM %s{tableName}"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Create a SELECT clause to retrieve the document data from the given table
 | 
				
			||||||
 | 
					    [<CompiledName "SelectFromTable">]
 | 
				
			||||||
 | 
					    [<System.Obsolete "Use Find instead">]
 | 
				
			||||||
 | 
					    let selectFromTable tableName =
 | 
				
			||||||
 | 
					        find tableName
 | 
				
			||||||
 | 
				
			|||||||
@ -396,7 +396,7 @@ type NpgsqlConnectionCSharpExtensions =
 | 
				
			|||||||
    /// Remove fields from a document by the document's ID
 | 
					    /// Remove fields from a document by the document's ID
 | 
				
			||||||
    [<Extension>]
 | 
					    [<Extension>]
 | 
				
			||||||
    static member inline RemoveFieldsById(conn, tableName, docId: 'TKey, fieldNames) =
 | 
					    static member inline RemoveFieldsById(conn, tableName, docId: 'TKey, fieldNames) =
 | 
				
			||||||
        WithProps.RemoveFields.ById(tableName, docId, fieldNames, Sql.existingConnection conn)
 | 
					        WithProps.RemoveFields.byId tableName docId fieldNames (Sql.existingConnection conn)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Remove fields from documents via a comparison on JSON fields in the document
 | 
					    /// Remove fields from documents via a comparison on JSON fields in the document
 | 
				
			||||||
    [<Extension>]
 | 
					    [<Extension>]
 | 
				
			||||||
@ -412,12 +412,12 @@ type NpgsqlConnectionCSharpExtensions =
 | 
				
			|||||||
    /// Remove fields from documents via a JSON containment query (@>)
 | 
					    /// Remove fields from documents via a JSON containment query (@>)
 | 
				
			||||||
    [<Extension>]
 | 
					    [<Extension>]
 | 
				
			||||||
    static member inline RemoveFieldsByContains(conn, tableName, criteria: 'TContains, fieldNames) =
 | 
					    static member inline RemoveFieldsByContains(conn, tableName, criteria: 'TContains, fieldNames) =
 | 
				
			||||||
        WithProps.RemoveFields.ByContains(tableName, criteria, fieldNames, Sql.existingConnection conn)
 | 
					        WithProps.RemoveFields.byContains tableName criteria fieldNames (Sql.existingConnection conn)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    /// Remove fields from documents via a JSON Path match query (@?)
 | 
					    /// Remove fields from documents via a JSON Path match query (@?)
 | 
				
			||||||
    [<Extension>]
 | 
					    [<Extension>]
 | 
				
			||||||
    static member inline RemoveFieldsByJsonPath(conn, tableName, jsonPath, fieldNames) =
 | 
					    static member inline RemoveFieldsByJsonPath(conn, tableName, jsonPath, fieldNames) =
 | 
				
			||||||
        WithProps.RemoveFields.ByJsonPath(tableName, jsonPath, fieldNames, Sql.existingConnection conn)
 | 
					        WithProps.RemoveFields.byJsonPath tableName jsonPath fieldNames (Sql.existingConnection conn)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Delete a document by its ID
 | 
					    /// Delete a document by its ID
 | 
				
			||||||
    [<Extension>]
 | 
					    [<Extension>]
 | 
				
			||||||
 | 
				
			|||||||
@ -56,6 +56,7 @@ module Parameters =
 | 
				
			|||||||
    /// Create an ID parameter (name "@id", key will be treated as a string)
 | 
					    /// Create an ID parameter (name "@id", key will be treated as a string)
 | 
				
			||||||
    [<CompiledName "Id">]
 | 
					    [<CompiledName "Id">]
 | 
				
			||||||
    let idParam (key: 'TKey) =
 | 
					    let idParam (key: 'TKey) =
 | 
				
			||||||
 | 
					        // TODO: bind key by numeric types
 | 
				
			||||||
        "@id", Sql.string (string key)
 | 
					        "@id", Sql.string (string key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Create a parameter with a JSON value
 | 
					    /// Create a parameter with a JSON value
 | 
				
			||||||
@ -170,142 +171,38 @@ module Query =
 | 
				
			|||||||
    let whereJsonPathMatches paramName =
 | 
					    let whereJsonPathMatches paramName =
 | 
				
			||||||
        $"data @? %s{paramName}::jsonpath"
 | 
					        $"data @? %s{paramName}::jsonpath"
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    /// Create an UPDATE statement to patch documents
 | 
				
			||||||
 | 
					    [<CompiledName "Patch">]
 | 
				
			||||||
 | 
					    let patch tableName =
 | 
				
			||||||
 | 
					        $"UPDATE %s{tableName} SET data = data || @data"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Create an UPDATE statement to remove fields from documents
 | 
				
			||||||
 | 
					    [<CompiledName "RemoveFields">]
 | 
				
			||||||
 | 
					    let removeFields tableName =
 | 
				
			||||||
 | 
					        $"UPDATE %s{tableName} SET data = data - @name"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Create a query by a document's ID
 | 
				
			||||||
 | 
					    [<CompiledName "ById">]
 | 
				
			||||||
 | 
					    let byId<'TKey> statement (docId: 'TKey) =
 | 
				
			||||||
 | 
					        Query.statementWhere
 | 
				
			||||||
 | 
					            statement
 | 
				
			||||||
 | 
					            (whereByFields Any [ { Field.EQ (Configuration.idField ()) docId with ParameterName = Some "@id" } ])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /// Create a query on JSON fields
 | 
					    /// Create a query on JSON fields
 | 
				
			||||||
    let fieldQuery statement howMatched fields =
 | 
					    [<CompiledName "ByFields">]
 | 
				
			||||||
 | 
					    let byFields statement howMatched fields =
 | 
				
			||||||
        Query.statementWhere statement (whereByFields howMatched fields)
 | 
					        Query.statementWhere statement (whereByFields howMatched fields)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Create a JSON containment query
 | 
					    /// Create a JSON containment query
 | 
				
			||||||
    let containQuery statement =
 | 
					    [<CompiledName "ByContains">]
 | 
				
			||||||
 | 
					    let byContains statement =
 | 
				
			||||||
        Query.statementWhere statement (whereDataContains "@criteria")
 | 
					        Query.statementWhere statement (whereDataContains "@criteria")
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Create a JSON Path match query
 | 
					    /// Create a JSON Path match query
 | 
				
			||||||
    let pathMatchQuery statement =
 | 
					    [<CompiledName "ByPathMatch">]
 | 
				
			||||||
 | 
					    let byPathMatch statement =
 | 
				
			||||||
        Query.statementWhere statement (whereJsonPathMatches "@path")
 | 
					        Query.statementWhere statement (whereJsonPathMatches "@path")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Queries for retrieving documents
 | 
					 | 
				
			||||||
    module Find =
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Query to retrieve a document by its ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            $"""{Query.selectFromTable tableName} WHERE {whereById "@id"}"""
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to retrieve documents using a comparison on JSON fields
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            $"{Query.selectFromTable tableName} WHERE {whereByFields howMatched fields}"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to retrieve documents using a comparison on a JSON field
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to retrieve documents using a JSON containment query (@>)
 | 
					 | 
				
			||||||
        [<CompiledName "ByContains">]
 | 
					 | 
				
			||||||
        let byContains tableName =
 | 
					 | 
				
			||||||
            $"""{Query.selectFromTable tableName} WHERE {whereDataContains "@criteria"}"""
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to retrieve documents using a JSON Path match (@?)
 | 
					 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					 | 
				
			||||||
        let byJsonPath tableName =
 | 
					 | 
				
			||||||
            $"""{Query.selectFromTable tableName} WHERE {whereJsonPathMatches "@path"}"""
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Queries to patch (partially update) documents
 | 
					 | 
				
			||||||
    module Patch =
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Create an UPDATE statement to patch documents
 | 
					 | 
				
			||||||
        let private update tableName whereClause =
 | 
					 | 
				
			||||||
            $"UPDATE %s{tableName} SET data = data || @data WHERE {whereClause}"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch a document by its ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            whereById "@id" |> update tableName
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch documents match JSON field comparisons (->> =)
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            whereByFields howMatched fields |> update tableName
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        /// Query to patch documents match a JSON field comparison (->> =)
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch documents matching a JSON containment query (@>)
 | 
					 | 
				
			||||||
        [<CompiledName "ByContains">]
 | 
					 | 
				
			||||||
        let byContains tableName =
 | 
					 | 
				
			||||||
            whereDataContains "@criteria" |> update tableName
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Query to patch documents matching a JSON containment query (@>)
 | 
					 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					 | 
				
			||||||
        let byJsonPath tableName =
 | 
					 | 
				
			||||||
            whereJsonPathMatches "@path" |> update tableName
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Queries to remove fields from documents
 | 
					 | 
				
			||||||
    module RemoveFields =
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Create an UPDATE statement to remove parameters
 | 
					 | 
				
			||||||
        let private update tableName whereClause =
 | 
					 | 
				
			||||||
            $"UPDATE %s{tableName} SET data = data - @name WHERE {whereClause}"
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        /// Query to remove fields from a document by the document's ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            whereById "@id" |> update tableName
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to remove fields from documents via a comparison on JSON fields within the document
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            whereByFields howMatched fields |> update tableName
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to remove fields from documents via a comparison on a JSON field within the document
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch documents matching a JSON containment query (@>)
 | 
					 | 
				
			||||||
        [<CompiledName "ByContains">]
 | 
					 | 
				
			||||||
        let byContains tableName =
 | 
					 | 
				
			||||||
            whereDataContains "@criteria" |> update tableName
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Query to patch documents matching a JSON containment query (@>)
 | 
					 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					 | 
				
			||||||
        let byJsonPath tableName =
 | 
					 | 
				
			||||||
            whereJsonPathMatches "@path" |> update tableName
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Queries to delete documents
 | 
					 | 
				
			||||||
    module Delete =
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to delete a document by its ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            $"""DELETE FROM %s{tableName} WHERE {whereById "@id"}"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Query to delete documents using a comparison on JSON fields
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            $"DELETE FROM %s{tableName} WHERE {whereByFields howMatched fields}"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to delete documents using a comparison on a JSON field
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to delete documents using a JSON containment query (@>)
 | 
					 | 
				
			||||||
        [<CompiledName "ByContains">]
 | 
					 | 
				
			||||||
        let byContains tableName =
 | 
					 | 
				
			||||||
            $"""DELETE FROM %s{tableName} WHERE {whereDataContains "@criteria"}"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Query to delete documents using a JSON Path match (@?)
 | 
					 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					 | 
				
			||||||
        let byJsonPath tableName =
 | 
					 | 
				
			||||||
            $"""DELETE FROM %s{tableName} WHERE {whereJsonPathMatches "@path"}"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Functions for dealing with results
 | 
					/// Functions for dealing with results
 | 
				
			||||||
[<AutoOpen>]
 | 
					[<AutoOpen>]
 | 
				
			||||||
@ -434,19 +331,19 @@ module WithProps =
 | 
				
			|||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields sqlProps =
 | 
					        let byFields tableName howMatched fields sqlProps =
 | 
				
			||||||
            Custom.scalar
 | 
					            Custom.scalar
 | 
				
			||||||
                (Query.fieldQuery (Query.count tableName) howMatched fields) (addFieldParams fields []) toCount sqlProps
 | 
					                (Query.byFields (Query.count tableName) howMatched fields) (addFieldParams fields []) toCount sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Count matching documents using a JSON containment query (@>)
 | 
					        /// Count matching documents using a JSON containment query (@>)
 | 
				
			||||||
        [<CompiledName "ByContains">]
 | 
					        [<CompiledName "ByContains">]
 | 
				
			||||||
        let byContains tableName (criteria: 'TContains) sqlProps =
 | 
					        let byContains tableName (criteria: 'TContains) sqlProps =
 | 
				
			||||||
            Custom.scalar
 | 
					            Custom.scalar
 | 
				
			||||||
                (Query.containQuery (Query.count tableName)) [ jsonParam "@criteria" criteria ] toCount sqlProps
 | 
					                (Query.byContains (Query.count tableName)) [ jsonParam "@criteria" criteria ] toCount sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Count matching documents using a JSON Path match query (@?)
 | 
					        /// Count matching documents using a JSON Path match query (@?)
 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					        [<CompiledName "ByJsonPath">]
 | 
				
			||||||
        let byJsonPath tableName jsonPath sqlProps =
 | 
					        let byJsonPath tableName jsonPath sqlProps =
 | 
				
			||||||
            Custom.scalar
 | 
					            Custom.scalar
 | 
				
			||||||
                (Query.pathMatchQuery (Query.count tableName)) [ "@path", Sql.string jsonPath ] toCount sqlProps
 | 
					                (Query.byPathMatch (Query.count tableName)) [ "@path", Sql.string jsonPath ] toCount sqlProps
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Commands to determine if documents exist
 | 
					    /// Commands to determine if documents exist
 | 
				
			||||||
    [<RequireQualifiedAccess>]
 | 
					    [<RequireQualifiedAccess>]
 | 
				
			||||||
@ -491,26 +388,30 @@ module WithProps =
 | 
				
			|||||||
        /// Retrieve all documents in the given table
 | 
					        /// Retrieve all documents in the given table
 | 
				
			||||||
        [<CompiledName "FSharpAll">]
 | 
					        [<CompiledName "FSharpAll">]
 | 
				
			||||||
        let all<'TDoc> tableName sqlProps =
 | 
					        let all<'TDoc> tableName sqlProps =
 | 
				
			||||||
            Custom.list<'TDoc> (Query.selectFromTable tableName) [] fromData<'TDoc> sqlProps
 | 
					            Custom.list<'TDoc> (Query.find tableName) [] fromData<'TDoc> sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve all documents in the given table
 | 
					        /// Retrieve all documents in the given table
 | 
				
			||||||
        let All<'TDoc>(tableName, sqlProps) =
 | 
					        let All<'TDoc>(tableName, sqlProps) =
 | 
				
			||||||
            Custom.List<'TDoc>(Query.selectFromTable tableName, [], fromData<'TDoc>, sqlProps)
 | 
					            Custom.List<'TDoc>(Query.find tableName, [], fromData<'TDoc>, sqlProps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve a document by its ID (returns None if not found)
 | 
					        /// Retrieve a document by its ID (returns None if not found)
 | 
				
			||||||
        [<CompiledName "FSharpById">]
 | 
					        [<CompiledName "FSharpById">]
 | 
				
			||||||
        let byId<'TKey, 'TDoc> tableName (docId: 'TKey) sqlProps =
 | 
					        let byId<'TKey, 'TDoc> tableName (docId: 'TKey) sqlProps =
 | 
				
			||||||
            Custom.single (Query.Find.byId tableName) [ idParam docId ] fromData<'TDoc> sqlProps
 | 
					            Custom.single (Query.byId (Query.find tableName) docId) [ idParam docId ] fromData<'TDoc> sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve a document by its ID (returns null if not found)
 | 
					        /// Retrieve a document by its ID (returns null if not found)
 | 
				
			||||||
        let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, sqlProps) =
 | 
					        let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, sqlProps) =
 | 
				
			||||||
            Custom.Single<'TDoc>(Query.Find.byId tableName, [ idParam docId ], fromData<'TDoc>, sqlProps)
 | 
					            Custom.Single<'TDoc>(
 | 
				
			||||||
 | 
					                Query.byId (Query.find tableName) docId, [ idParam docId ], fromData<'TDoc>, sqlProps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve documents matching JSON field comparisons (->> =)
 | 
					        /// Retrieve documents matching JSON field comparisons (->> =)
 | 
				
			||||||
        [<CompiledName "FSharpByFields">]
 | 
					        [<CompiledName "FSharpByFields">]
 | 
				
			||||||
        let byFields<'TDoc> tableName howMatched fields sqlProps =
 | 
					        let byFields<'TDoc> tableName howMatched fields sqlProps =
 | 
				
			||||||
            Custom.list<'TDoc>
 | 
					            Custom.list<'TDoc>
 | 
				
			||||||
                (Query.Find.byFields tableName howMatched fields) (addFieldParams fields []) fromData<'TDoc> sqlProps
 | 
					                (Query.byFields (Query.find tableName) howMatched fields)
 | 
				
			||||||
 | 
					                (addFieldParams fields [])
 | 
				
			||||||
 | 
					                fromData<'TDoc>
 | 
				
			||||||
 | 
					                sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Retrieve documents matching a JSON field comparison (->> =)
 | 
					        /// Retrieve documents matching a JSON field comparison (->> =)
 | 
				
			||||||
        [<CompiledName "FSharpByField">]
 | 
					        [<CompiledName "FSharpByField">]
 | 
				
			||||||
@ -521,7 +422,10 @@ module WithProps =
 | 
				
			|||||||
        /// Retrieve documents matching JSON field comparisons (->> =)
 | 
					        /// Retrieve documents matching JSON field comparisons (->> =)
 | 
				
			||||||
        let ByFields<'TDoc>(tableName, howMatched, fields, sqlProps) =
 | 
					        let ByFields<'TDoc>(tableName, howMatched, fields, sqlProps) =
 | 
				
			||||||
            Custom.List<'TDoc>(
 | 
					            Custom.List<'TDoc>(
 | 
				
			||||||
                Query.Find.byFields tableName howMatched fields, addFieldParams fields [], fromData<'TDoc>, sqlProps)
 | 
					                Query.byFields (Query.find tableName) howMatched fields,
 | 
				
			||||||
 | 
					                addFieldParams fields [],
 | 
				
			||||||
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
 | 
					                sqlProps)
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        /// Retrieve documents matching a JSON field comparison (->> =)
 | 
					        /// Retrieve documents matching a JSON field comparison (->> =)
 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
				
			||||||
@ -532,29 +436,35 @@ module WithProps =
 | 
				
			|||||||
        [<CompiledName "FSharpByContains">]
 | 
					        [<CompiledName "FSharpByContains">]
 | 
				
			||||||
        let byContains<'TDoc> tableName (criteria: obj) sqlProps =
 | 
					        let byContains<'TDoc> tableName (criteria: obj) sqlProps =
 | 
				
			||||||
            Custom.list<'TDoc>
 | 
					            Custom.list<'TDoc>
 | 
				
			||||||
                (Query.Find.byContains tableName) [ jsonParam "@criteria" criteria ] fromData<'TDoc> sqlProps
 | 
					                (Query.byContains (Query.find tableName)) [ jsonParam "@criteria" criteria ] fromData<'TDoc> sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve documents matching a JSON containment query (@>)
 | 
					        /// Retrieve documents matching a JSON containment query (@>)
 | 
				
			||||||
        let ByContains<'TDoc>(tableName, criteria: obj, sqlProps) =
 | 
					        let ByContains<'TDoc>(tableName, criteria: obj, sqlProps) =
 | 
				
			||||||
            Custom.List<'TDoc>(
 | 
					            Custom.List<'TDoc>(
 | 
				
			||||||
                Query.Find.byContains tableName, [ jsonParam "@criteria" criteria ], fromData<'TDoc>, sqlProps)
 | 
					                Query.byContains (Query.find tableName),
 | 
				
			||||||
 | 
					                [ jsonParam "@criteria" criteria ],
 | 
				
			||||||
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
 | 
					                sqlProps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve documents matching a JSON Path match query (@?)
 | 
					        /// Retrieve documents matching a JSON Path match query (@?)
 | 
				
			||||||
        [<CompiledName "FSharpByJsonPath">]
 | 
					        [<CompiledName "FSharpByJsonPath">]
 | 
				
			||||||
        let byJsonPath<'TDoc> tableName jsonPath sqlProps =
 | 
					        let byJsonPath<'TDoc> tableName jsonPath sqlProps =
 | 
				
			||||||
            Custom.list<'TDoc>
 | 
					            Custom.list<'TDoc>
 | 
				
			||||||
                (Query.Find.byJsonPath tableName) [ "@path", Sql.string jsonPath ] fromData<'TDoc> sqlProps
 | 
					                (Query.byPathMatch (Query.find tableName)) [ "@path", Sql.string jsonPath ] fromData<'TDoc> sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Retrieve documents matching a JSON Path match query (@?)
 | 
					        /// Retrieve documents matching a JSON Path match query (@?)
 | 
				
			||||||
        let ByJsonPath<'TDoc>(tableName, jsonPath, sqlProps) =
 | 
					        let ByJsonPath<'TDoc>(tableName, jsonPath, sqlProps) =
 | 
				
			||||||
            Custom.List<'TDoc>(
 | 
					            Custom.List<'TDoc>(
 | 
				
			||||||
                Query.Find.byJsonPath tableName, [ "@path", Sql.string jsonPath ], fromData<'TDoc>, sqlProps)
 | 
					                Query.byPathMatch (Query.find tableName),
 | 
				
			||||||
 | 
					                [ "@path", Sql.string jsonPath ],
 | 
				
			||||||
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
 | 
					                sqlProps)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Retrieve the first document matching JSON field comparisons (->> =); returns None if not found
 | 
					        /// Retrieve the first document matching JSON field comparisons (->> =); returns None if not found
 | 
				
			||||||
        [<CompiledName "FSharpFirstByFields">]
 | 
					        [<CompiledName "FSharpFirstByFields">]
 | 
				
			||||||
        let firstByFields<'TDoc> tableName howMatched fields sqlProps =
 | 
					        let firstByFields<'TDoc> tableName howMatched fields sqlProps =
 | 
				
			||||||
            Custom.single<'TDoc>
 | 
					            Custom.single<'TDoc>
 | 
				
			||||||
                $"{Query.Find.byFields tableName howMatched fields} LIMIT 1"
 | 
					                $"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1"
 | 
				
			||||||
                (addFieldParams fields [])
 | 
					                (addFieldParams fields [])
 | 
				
			||||||
                fromData<'TDoc>
 | 
					                fromData<'TDoc>
 | 
				
			||||||
                sqlProps
 | 
					                sqlProps
 | 
				
			||||||
@ -568,7 +478,7 @@ module WithProps =
 | 
				
			|||||||
        /// Retrieve the first document matching JSON field comparisons (->> =); returns null if not found
 | 
					        /// Retrieve the first document matching JSON field comparisons (->> =); returns null if not found
 | 
				
			||||||
        let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, sqlProps) =
 | 
					        let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, sqlProps) =
 | 
				
			||||||
            Custom.Single<'TDoc>(
 | 
					            Custom.Single<'TDoc>(
 | 
				
			||||||
                $"{Query.Find.byFields tableName howMatched fields} LIMIT 1",
 | 
					                $"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1",
 | 
				
			||||||
                addFieldParams fields [],
 | 
					                addFieldParams fields [],
 | 
				
			||||||
                fromData<'TDoc>,
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
                sqlProps)
 | 
					                sqlProps)
 | 
				
			||||||
@ -582,12 +492,15 @@ module WithProps =
 | 
				
			|||||||
        [<CompiledName "FSharpFirstByContains">]
 | 
					        [<CompiledName "FSharpFirstByContains">]
 | 
				
			||||||
        let firstByContains<'TDoc> tableName (criteria: obj) sqlProps =
 | 
					        let firstByContains<'TDoc> tableName (criteria: obj) sqlProps =
 | 
				
			||||||
            Custom.single<'TDoc>
 | 
					            Custom.single<'TDoc>
 | 
				
			||||||
                $"{Query.Find.byContains tableName} LIMIT 1" [ jsonParam "@criteria" criteria ] fromData<'TDoc> sqlProps
 | 
					                $"{Query.byContains (Query.find tableName)} LIMIT 1"
 | 
				
			||||||
 | 
					                [ jsonParam "@criteria" criteria ]
 | 
				
			||||||
 | 
					                fromData<'TDoc>
 | 
				
			||||||
 | 
					                sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve the first document matching a JSON containment query (@>); returns null if not found
 | 
					        /// Retrieve the first document matching a JSON containment query (@>); returns null if not found
 | 
				
			||||||
        let FirstByContains<'TDoc when 'TDoc: null>(tableName, criteria: obj, sqlProps) =
 | 
					        let FirstByContains<'TDoc when 'TDoc: null>(tableName, criteria: obj, sqlProps) =
 | 
				
			||||||
            Custom.Single<'TDoc>(
 | 
					            Custom.Single<'TDoc>(
 | 
				
			||||||
                $"{Query.Find.byContains tableName} LIMIT 1",
 | 
					                $"{Query.byContains (Query.find tableName)} LIMIT 1",
 | 
				
			||||||
                [ jsonParam "@criteria" criteria ],
 | 
					                [ jsonParam "@criteria" criteria ],
 | 
				
			||||||
                fromData<'TDoc>,
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
                sqlProps)
 | 
					                sqlProps)
 | 
				
			||||||
@ -596,12 +509,15 @@ module WithProps =
 | 
				
			|||||||
        [<CompiledName "FSharpFirstByJsonPath">]
 | 
					        [<CompiledName "FSharpFirstByJsonPath">]
 | 
				
			||||||
        let firstByJsonPath<'TDoc> tableName jsonPath sqlProps =
 | 
					        let firstByJsonPath<'TDoc> tableName jsonPath sqlProps =
 | 
				
			||||||
            Custom.single<'TDoc>
 | 
					            Custom.single<'TDoc>
 | 
				
			||||||
                $"{Query.Find.byJsonPath tableName} LIMIT 1" [ "@path", Sql.string jsonPath ] fromData<'TDoc> sqlProps
 | 
					                $"{Query.byPathMatch (Query.find tableName)} LIMIT 1"
 | 
				
			||||||
 | 
					                [ "@path", Sql.string jsonPath ]
 | 
				
			||||||
 | 
					                fromData<'TDoc>
 | 
				
			||||||
 | 
					                sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve the first document matching a JSON Path match query (@?); returns null if not found
 | 
					        /// Retrieve the first document matching a JSON Path match query (@?); returns null if not found
 | 
				
			||||||
        let FirstByJsonPath<'TDoc when 'TDoc: null>(tableName, jsonPath, sqlProps) =
 | 
					        let FirstByJsonPath<'TDoc when 'TDoc: null>(tableName, jsonPath, sqlProps) =
 | 
				
			||||||
            Custom.Single<'TDoc>(
 | 
					            Custom.Single<'TDoc>(
 | 
				
			||||||
                $"{Query.Find.byJsonPath tableName} LIMIT 1",
 | 
					                $"{Query.byPathMatch (Query.find tableName)} LIMIT 1",
 | 
				
			||||||
                [ "@path", Sql.string jsonPath ],
 | 
					                [ "@path", Sql.string jsonPath ],
 | 
				
			||||||
                fromData<'TDoc>,
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
                sqlProps)
 | 
					                sqlProps)
 | 
				
			||||||
@ -634,13 +550,14 @@ module WithProps =
 | 
				
			|||||||
        /// Patch a document by its ID
 | 
					        /// Patch a document by its ID
 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					        [<CompiledName "ById">]
 | 
				
			||||||
        let byId tableName (docId: 'TKey) (patch: 'TPatch) sqlProps =
 | 
					        let byId tableName (docId: 'TKey) (patch: 'TPatch) sqlProps =
 | 
				
			||||||
            Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] sqlProps
 | 
					            Custom.nonQuery
 | 
				
			||||||
 | 
					                (Query.byId (Query.patch tableName) docId) [ idParam docId; jsonParam "@data" patch ] sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
 | 
					        /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields (patch: 'TPatch) sqlProps =
 | 
					        let byFields tableName howMatched fields (patch: 'TPatch) sqlProps =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.Patch.byFields tableName howMatched fields)
 | 
					                (Query.byFields (Query.patch tableName) howMatched fields)
 | 
				
			||||||
                (addFieldParams fields [ jsonParam "@data" patch ])
 | 
					                (addFieldParams fields [ jsonParam "@data" patch ])
 | 
				
			||||||
                sqlProps
 | 
					                sqlProps
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@ -654,32 +571,33 @@ module WithProps =
 | 
				
			|||||||
        [<CompiledName "ByContains">]
 | 
					        [<CompiledName "ByContains">]
 | 
				
			||||||
        let byContains tableName (criteria: 'TContains) (patch: 'TPatch) sqlProps =
 | 
					        let byContains tableName (criteria: 'TContains) (patch: 'TPatch) sqlProps =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.Patch.byContains tableName) [ jsonParam "@data" patch; jsonParam "@criteria" criteria ] sqlProps
 | 
					                (Query.byContains (Query.patch tableName))
 | 
				
			||||||
 | 
					                [ jsonParam "@data" patch; jsonParam "@criteria" criteria ]
 | 
				
			||||||
 | 
					                sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Patch documents using a JSON Path match query in the WHERE clause (@?)
 | 
					        /// Patch documents using a JSON Path match query in the WHERE clause (@?)
 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					        [<CompiledName "ByJsonPath">]
 | 
				
			||||||
        let byJsonPath tableName jsonPath (patch: 'TPatch) sqlProps =
 | 
					        let byJsonPath tableName jsonPath (patch: 'TPatch) sqlProps =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.Patch.byJsonPath tableName) [ jsonParam "@data" patch; "@path", Sql.string jsonPath ] sqlProps
 | 
					                (Query.byPathMatch (Query.patch tableName))
 | 
				
			||||||
 | 
					                [ jsonParam "@data" patch; "@path", Sql.string jsonPath ]
 | 
				
			||||||
 | 
					                sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Commands to remove fields from documents
 | 
					    /// Commands to remove fields from documents
 | 
				
			||||||
    [<RequireQualifiedAccess>]
 | 
					    [<RequireQualifiedAccess>]
 | 
				
			||||||
    module RemoveFields =
 | 
					    module RemoveFields =
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Remove fields from a document by the document's ID
 | 
					        /// Remove fields from a document by the document's ID
 | 
				
			||||||
        [<CompiledName "FSharpById">]
 | 
					        [<CompiledName "ById">]
 | 
				
			||||||
        let byId tableName (docId: 'TKey) fieldNames sqlProps =
 | 
					        let byId tableName (docId: 'TKey) fieldNames sqlProps =
 | 
				
			||||||
            Custom.nonQuery (Query.RemoveFields.byId tableName) [ idParam docId; fieldNameParams fieldNames ] sqlProps
 | 
					            Custom.nonQuery
 | 
				
			||||||
        
 | 
					                (Query.byId (Query.removeFields tableName) docId) [ idParam docId; fieldNameParams fieldNames ] sqlProps
 | 
				
			||||||
        /// Remove fields from a document by the document's ID
 | 
					 | 
				
			||||||
        let ById(tableName, docId: 'TKey, fieldNames, sqlProps) =
 | 
					 | 
				
			||||||
            byId tableName docId (List.ofSeq fieldNames) sqlProps
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Remove fields from documents via a comparison on JSON fields in the document
 | 
					        /// Remove fields from documents via a comparison on JSON fields in the document
 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields fieldNames sqlProps =
 | 
					        let byFields tableName howMatched fields fieldNames sqlProps =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.RemoveFields.byFields tableName howMatched fields)
 | 
					                (Query.byFields (Query.removeFields tableName) howMatched fields)
 | 
				
			||||||
                (addFieldParams fields [ fieldNameParams fieldNames ])
 | 
					                (addFieldParams fields [ fieldNameParams fieldNames ])
 | 
				
			||||||
                sqlProps
 | 
					                sqlProps
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@ -690,29 +608,21 @@ module WithProps =
 | 
				
			|||||||
            byFields tableName Any [ field ] fieldNames sqlProps
 | 
					            byFields tableName Any [ field ] fieldNames sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Remove fields from documents via a JSON containment query (@>)
 | 
					        /// Remove fields from documents via a JSON containment query (@>)
 | 
				
			||||||
        [<CompiledName "FSharpByContains">]
 | 
					        [<CompiledName "ByContains">]
 | 
				
			||||||
        let byContains tableName (criteria: 'TContains) fieldNames sqlProps =
 | 
					        let byContains tableName (criteria: 'TContains) fieldNames sqlProps =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.RemoveFields.byContains tableName)
 | 
					                (Query.byContains (Query.removeFields tableName))
 | 
				
			||||||
                [ jsonParam "@criteria" criteria; fieldNameParams fieldNames ]
 | 
					                [ jsonParam "@criteria" criteria; fieldNameParams fieldNames ]
 | 
				
			||||||
                sqlProps
 | 
					                sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Remove fields from documents via a JSON containment query (@>)
 | 
					 | 
				
			||||||
        let ByContains(tableName, criteria: 'TContains, fieldNames, sqlProps) =
 | 
					 | 
				
			||||||
            byContains tableName criteria (List.ofSeq fieldNames) sqlProps
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
        /// Remove fields from documents via a JSON Path match query (@?)
 | 
					        /// Remove fields from documents via a JSON Path match query (@?)
 | 
				
			||||||
        [<CompiledName "FSharpByJsonPath">]
 | 
					        [<CompiledName "FSharpByJsonPath">]
 | 
				
			||||||
        let byJsonPath tableName jsonPath fieldNames sqlProps =
 | 
					        let byJsonPath tableName jsonPath fieldNames sqlProps =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.RemoveFields.byJsonPath tableName)
 | 
					                (Query.byPathMatch (Query.removeFields tableName))
 | 
				
			||||||
                [ "@path", Sql.string jsonPath; fieldNameParams fieldNames ]
 | 
					                [ "@path", Sql.string jsonPath; fieldNameParams fieldNames ]
 | 
				
			||||||
                sqlProps
 | 
					                sqlProps
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        /// Remove fields from documents via a JSON Path match query (@?)
 | 
					 | 
				
			||||||
        let ByJsonPath(tableName, jsonPath, fieldNames, sqlProps) =
 | 
					 | 
				
			||||||
            byJsonPath tableName jsonPath (List.ofSeq fieldNames) sqlProps
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Commands to delete documents
 | 
					    /// Commands to delete documents
 | 
				
			||||||
    [<RequireQualifiedAccess>]
 | 
					    [<RequireQualifiedAccess>]
 | 
				
			||||||
    module Delete =
 | 
					    module Delete =
 | 
				
			||||||
@ -720,12 +630,13 @@ module WithProps =
 | 
				
			|||||||
        /// Delete a document by its ID
 | 
					        /// Delete a document by its ID
 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					        [<CompiledName "ById">]
 | 
				
			||||||
        let byId tableName (docId: 'TKey) sqlProps =
 | 
					        let byId tableName (docId: 'TKey) sqlProps =
 | 
				
			||||||
            Custom.nonQuery (Query.Delete.byId tableName) [ idParam docId ] sqlProps
 | 
					            Custom.nonQuery (Query.byId (Query.delete tableName) docId) [ idParam docId ] sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Delete documents by matching a JSON field comparison query (->> =)
 | 
					        /// Delete documents by matching a JSON field comparison query (->> =)
 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields sqlProps =
 | 
					        let byFields tableName howMatched fields sqlProps =
 | 
				
			||||||
            Custom.nonQuery (Query.Delete.byFields tableName howMatched fields) (addFieldParams fields []) sqlProps
 | 
					            Custom.nonQuery
 | 
				
			||||||
 | 
					                (Query.byFields (Query.delete tableName) howMatched fields) (addFieldParams fields []) sqlProps
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Delete documents by matching a JSON field comparison query (->> =)
 | 
					        /// Delete documents by matching a JSON field comparison query (->> =)
 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					        [<CompiledName "ByField">]
 | 
				
			||||||
@ -736,12 +647,12 @@ module WithProps =
 | 
				
			|||||||
        /// Delete documents by matching a JSON contains query (@>)
 | 
					        /// Delete documents by matching a JSON contains query (@>)
 | 
				
			||||||
        [<CompiledName "ByContains">]
 | 
					        [<CompiledName "ByContains">]
 | 
				
			||||||
        let byContains tableName (criteria: 'TCriteria) sqlProps =
 | 
					        let byContains tableName (criteria: 'TCriteria) sqlProps =
 | 
				
			||||||
            Custom.nonQuery (Query.Delete.byContains tableName) [ jsonParam "@criteria" criteria ] sqlProps
 | 
					            Custom.nonQuery (Query.byContains (Query.delete tableName)) [ jsonParam "@criteria" criteria ] sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Delete documents by matching a JSON Path match query (@?)
 | 
					        /// Delete documents by matching a JSON Path match query (@?)
 | 
				
			||||||
        [<CompiledName "ByJsonPath">]
 | 
					        [<CompiledName "ByJsonPath">]
 | 
				
			||||||
        let byJsonPath tableName path sqlProps =
 | 
					        let byJsonPath tableName path sqlProps =
 | 
				
			||||||
            Custom.nonQuery (Query.Delete.byJsonPath tableName) [ "@path", Sql.string path ] sqlProps
 | 
					            Custom.nonQuery (Query.byPathMatch (Query.delete tableName)) [ "@path", Sql.string path ] sqlProps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Commands to execute custom SQL queries
 | 
					/// Commands to execute custom SQL queries
 | 
				
			||||||
@ -1032,14 +943,10 @@ module Patch =
 | 
				
			|||||||
module RemoveFields =
 | 
					module RemoveFields =
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Remove fields from a document by the document's ID
 | 
					    /// Remove fields from a document by the document's ID
 | 
				
			||||||
    [<CompiledName "FSharpById">]
 | 
					    [<CompiledName "ById">]
 | 
				
			||||||
    let byId tableName (docId: 'TKey) fieldNames =
 | 
					    let byId tableName (docId: 'TKey) fieldNames =
 | 
				
			||||||
        WithProps.RemoveFields.byId tableName docId fieldNames (fromDataSource ())
 | 
					        WithProps.RemoveFields.byId tableName docId fieldNames (fromDataSource ())
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Remove fields from a document by the document's ID
 | 
					 | 
				
			||||||
    let ById(tableName, docId: 'TKey, fieldNames) =
 | 
					 | 
				
			||||||
        WithProps.RemoveFields.ById(tableName, docId, fieldNames, fromDataSource ())
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Remove fields from documents via a comparison on JSON fields in the document
 | 
					    /// Remove fields from documents via a comparison on JSON fields in the document
 | 
				
			||||||
    [<CompiledName "ByFields">]
 | 
					    [<CompiledName "ByFields">]
 | 
				
			||||||
    let byFields tableName howMatched fields fieldNames =
 | 
					    let byFields tableName howMatched fields fieldNames =
 | 
				
			||||||
@ -1052,23 +959,15 @@ module RemoveFields =
 | 
				
			|||||||
        byFields tableName Any [ field ] fieldNames
 | 
					        byFields tableName Any [ field ] fieldNames
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Remove fields from documents via a JSON containment query (@>)
 | 
					    /// Remove fields from documents via a JSON containment query (@>)
 | 
				
			||||||
    [<CompiledName "FSharpByContains">]
 | 
					    [<CompiledName "ByContains">]
 | 
				
			||||||
    let byContains tableName (criteria: 'TContains) fieldNames =
 | 
					    let byContains tableName (criteria: 'TContains) fieldNames =
 | 
				
			||||||
        WithProps.RemoveFields.byContains tableName criteria fieldNames (fromDataSource ())
 | 
					        WithProps.RemoveFields.byContains tableName criteria fieldNames (fromDataSource ())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Remove fields from documents via a JSON containment query (@>)
 | 
					 | 
				
			||||||
    let ByContains(tableName, criteria: 'TContains, fieldNames) =
 | 
					 | 
				
			||||||
        WithProps.RemoveFields.ByContains(tableName, criteria, fieldNames, fromDataSource ())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Remove fields from documents via a JSON Path match query (@?)
 | 
					    /// Remove fields from documents via a JSON Path match query (@?)
 | 
				
			||||||
    [<CompiledName "FSharpByJsonPath">]
 | 
					    [<CompiledName "ByJsonPath">]
 | 
				
			||||||
    let byJsonPath tableName jsonPath fieldNames =
 | 
					    let byJsonPath tableName jsonPath fieldNames =
 | 
				
			||||||
        WithProps.RemoveFields.byJsonPath tableName jsonPath fieldNames (fromDataSource ())
 | 
					        WithProps.RemoveFields.byJsonPath tableName jsonPath fieldNames (fromDataSource ())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Remove fields from documents via a JSON Path match query (@?)
 | 
					 | 
				
			||||||
    let ByJsonPath(tableName, jsonPath, fieldNames) =
 | 
					 | 
				
			||||||
        WithProps.RemoveFields.ByJsonPath(tableName, jsonPath, fieldNames, fromDataSource ())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Commands to delete documents
 | 
					/// Commands to delete documents
 | 
				
			||||||
[<RequireQualifiedAccess>]
 | 
					[<RequireQualifiedAccess>]
 | 
				
			||||||
 | 
				
			|||||||
@ -56,6 +56,29 @@ module Query =
 | 
				
			|||||||
    let whereById paramName =
 | 
					    let whereById paramName =
 | 
				
			||||||
        whereByFields Any [ { Field.EQ (Configuration.idField ()) 0 with ParameterName = Some paramName } ]
 | 
					        whereByFields Any [ { Field.EQ (Configuration.idField ()) 0 with ParameterName = Some paramName } ]
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    /// Create an UPDATE statement to patch documents
 | 
				
			||||||
 | 
					    [<CompiledName "Patch">]
 | 
				
			||||||
 | 
					    let patch tableName =
 | 
				
			||||||
 | 
					        $"UPDATE %s{tableName} SET data = json_patch(data, json(@data))"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Create an UPDATE statement to remove fields from documents
 | 
				
			||||||
 | 
					    [<CompiledName "RemoveFields">]
 | 
				
			||||||
 | 
					    let removeFields tableName (parameters: SqliteParameter seq) =
 | 
				
			||||||
 | 
					        let paramNames = parameters |> Seq.map _.ParameterName |> String.concat ", "
 | 
				
			||||||
 | 
					        $"UPDATE %s{tableName} SET data = json_remove(data, {paramNames})"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Create a query by a document's ID
 | 
				
			||||||
 | 
					    [<CompiledName "ById">]
 | 
				
			||||||
 | 
					    let byId<'TKey> statement (docId: 'TKey) =
 | 
				
			||||||
 | 
					        Query.statementWhere
 | 
				
			||||||
 | 
					            statement
 | 
				
			||||||
 | 
					            (whereByFields Any [ { Field.EQ (Configuration.idField ()) docId with ParameterName = Some "@id" } ])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Create a query on JSON fields
 | 
				
			||||||
 | 
					    [<CompiledName "ByFields">]
 | 
				
			||||||
 | 
					    let byFields statement howMatched fields =
 | 
				
			||||||
 | 
					        Query.statementWhere statement (whereByFields howMatched fields)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /// Data definition
 | 
					    /// Data definition
 | 
				
			||||||
    module Definition =
 | 
					    module Definition =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,91 +87,6 @@ module Query =
 | 
				
			|||||||
        let ensureTable name =
 | 
					        let ensureTable name =
 | 
				
			||||||
            Query.Definition.ensureTableFor name "TEXT"
 | 
					            Query.Definition.ensureTableFor name "TEXT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Queries for retrieving documents
 | 
					 | 
				
			||||||
    module Find =
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// Query to retrieve a document by its ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            $"""{Query.selectFromTable tableName} WHERE {whereById "@id"}"""
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to retrieve documents using a comparison on JSON fields
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            $"{Query.selectFromTable tableName} WHERE {whereByFields howMatched fields}"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to retrieve documents using a comparison on a JSON field
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Document patching (partial update) queries
 | 
					 | 
				
			||||||
    module Patch =
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Create an UPDATE statement to patch documents
 | 
					 | 
				
			||||||
        let internal update tableName whereClause =
 | 
					 | 
				
			||||||
            $"UPDATE %s{tableName} SET data = json_patch(data, json(@data)) WHERE %s{whereClause}"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch (partially update) a document by its ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            whereById "@id" |> update tableName
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch (partially update) a document via a comparison on JSON fields
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            whereByFields howMatched fields |> update tableName
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to patch (partially update) a document via a comparison on a JSON field
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    /// Queries to remove fields from documents
 | 
					 | 
				
			||||||
    module RemoveFields =
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Create an UPDATE statement to remove parameters
 | 
					 | 
				
			||||||
        let internal update tableName (parameters: SqliteParameter seq) whereClause =
 | 
					 | 
				
			||||||
            let paramNames = parameters |> Seq.map _.ParameterName |> String.concat ", "
 | 
					 | 
				
			||||||
            $"UPDATE %s{tableName} SET data = json_remove(data, {paramNames}) WHERE %s{whereClause}"
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        /// Query to remove fields from a document by the document's ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName parameters =
 | 
					 | 
				
			||||||
            whereById "@id" |> update tableName parameters
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to remove fields from documents via a comparison on JSON fields within the document
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields parameters =
 | 
					 | 
				
			||||||
            whereByFields howMatched fields |> update tableName parameters
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to remove fields from documents via a comparison on a JSON field within the document
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field parameters =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ] parameters
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Queries to delete documents
 | 
					 | 
				
			||||||
    module Delete =
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to delete a document by its ID
 | 
					 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					 | 
				
			||||||
        let byId tableName =
 | 
					 | 
				
			||||||
            $"""DELETE FROM %s{tableName} WHERE {whereById "@id"}"""
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to delete documents using a comparison on JSON fields
 | 
					 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					 | 
				
			||||||
        let byFields tableName howMatched fields =
 | 
					 | 
				
			||||||
            $"DELETE FROM %s{tableName} WHERE {whereByFields howMatched fields}"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /// Query to delete documents using a comparison on a JSON field
 | 
					 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					 | 
				
			||||||
        let byField tableName field =
 | 
					 | 
				
			||||||
            byFields tableName Any [ field ]
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Parameter handling helpers
 | 
					/// Parameter handling helpers
 | 
				
			||||||
[<AutoOpen>]
 | 
					[<AutoOpen>]
 | 
				
			||||||
@ -349,10 +287,7 @@ module WithConn =
 | 
				
			|||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields conn =
 | 
					        let byFields tableName howMatched fields conn =
 | 
				
			||||||
            Custom.scalar
 | 
					            Custom.scalar
 | 
				
			||||||
                (Query.statementWhere (Query.count tableName) (Query.whereByFields howMatched fields))
 | 
					                (Query.byFields (Query.count tableName) howMatched fields) (addFieldParams fields []) toCount conn
 | 
				
			||||||
                (addFieldParams fields [])
 | 
					 | 
				
			||||||
                toCount
 | 
					 | 
				
			||||||
                conn
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Commands to determine if documents exist
 | 
					    /// Commands to determine if documents exist
 | 
				
			||||||
    [<RequireQualifiedAccess>]
 | 
					    [<RequireQualifiedAccess>]
 | 
				
			||||||
@ -379,26 +314,29 @@ module WithConn =
 | 
				
			|||||||
        /// Retrieve all documents in the given table
 | 
					        /// Retrieve all documents in the given table
 | 
				
			||||||
        [<CompiledName "FSharpAll">]
 | 
					        [<CompiledName "FSharpAll">]
 | 
				
			||||||
        let all<'TDoc> tableName conn =
 | 
					        let all<'TDoc> tableName conn =
 | 
				
			||||||
            Custom.list<'TDoc> (Query.selectFromTable tableName) [] fromData<'TDoc> conn
 | 
					            Custom.list<'TDoc> (Query.find tableName) [] fromData<'TDoc> conn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve all documents in the given table
 | 
					        /// Retrieve all documents in the given table
 | 
				
			||||||
        let All<'TDoc>(tableName, conn) =
 | 
					        let All<'TDoc>(tableName, conn) =
 | 
				
			||||||
            Custom.List(Query.selectFromTable tableName, [], fromData<'TDoc>, conn)
 | 
					            Custom.List(Query.find tableName, [], fromData<'TDoc>, conn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve a document by its ID (returns None if not found)
 | 
					        /// Retrieve a document by its ID (returns None if not found)
 | 
				
			||||||
        [<CompiledName "FSharpById">]
 | 
					        [<CompiledName "FSharpById">]
 | 
				
			||||||
        let byId<'TKey, 'TDoc> tableName (docId: 'TKey) conn =
 | 
					        let byId<'TKey, 'TDoc> tableName (docId: 'TKey) conn =
 | 
				
			||||||
            Custom.single<'TDoc> (Query.Find.byId tableName) [ idParam docId ] fromData<'TDoc> conn
 | 
					            Custom.single<'TDoc> (Query.byId (Query.find tableName) docId) [ idParam docId ] fromData<'TDoc> conn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Retrieve a document by its ID (returns null if not found)
 | 
					        /// Retrieve a document by its ID (returns null if not found)
 | 
				
			||||||
        let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, conn) =
 | 
					        let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, conn) =
 | 
				
			||||||
            Custom.Single<'TDoc>(Query.Find.byId tableName, [ idParam docId ], fromData<'TDoc>, conn)
 | 
					            Custom.Single<'TDoc>(Query.byId (Query.find tableName) docId, [ idParam docId ], fromData<'TDoc>, conn)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Retrieve documents via a comparison on JSON fields
 | 
					        /// Retrieve documents via a comparison on JSON fields
 | 
				
			||||||
        [<CompiledName "FSharpByFields">]
 | 
					        [<CompiledName "FSharpByFields">]
 | 
				
			||||||
        let byFields<'TDoc> tableName howMatched fields conn =
 | 
					        let byFields<'TDoc> tableName howMatched fields conn =
 | 
				
			||||||
            Custom.list<'TDoc>
 | 
					            Custom.list<'TDoc>
 | 
				
			||||||
                (Query.Find.byFields tableName howMatched fields) (addFieldParams fields []) fromData<'TDoc> conn 
 | 
					                (Query.byFields (Query.find tableName) howMatched fields)
 | 
				
			||||||
 | 
					                (addFieldParams fields [])
 | 
				
			||||||
 | 
					                fromData<'TDoc>
 | 
				
			||||||
 | 
					                conn 
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Retrieve documents via a comparison on a JSON field
 | 
					        /// Retrieve documents via a comparison on a JSON field
 | 
				
			||||||
        [<CompiledName "FSharpByField">]
 | 
					        [<CompiledName "FSharpByField">]
 | 
				
			||||||
@ -409,7 +347,10 @@ module WithConn =
 | 
				
			|||||||
        /// Retrieve documents via a comparison on JSON fields
 | 
					        /// Retrieve documents via a comparison on JSON fields
 | 
				
			||||||
        let ByFields<'TDoc>(tableName, howMatched, fields, conn) =
 | 
					        let ByFields<'TDoc>(tableName, howMatched, fields, conn) =
 | 
				
			||||||
            Custom.List<'TDoc>(
 | 
					            Custom.List<'TDoc>(
 | 
				
			||||||
                Query.Find.byFields tableName howMatched fields, addFieldParams fields [], fromData<'TDoc>, conn) 
 | 
					                Query.byFields (Query.find tableName) howMatched fields,
 | 
				
			||||||
 | 
					                addFieldParams fields [],
 | 
				
			||||||
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
 | 
					                conn) 
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Retrieve documents via a comparison on a JSON field
 | 
					        /// Retrieve documents via a comparison on a JSON field
 | 
				
			||||||
        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
					        [<System.Obsolete "Use ByFields instead; will be removed in v4">]
 | 
				
			||||||
@ -420,7 +361,7 @@ module WithConn =
 | 
				
			|||||||
        [<CompiledName "FSharpFirstByFields">]
 | 
					        [<CompiledName "FSharpFirstByFields">]
 | 
				
			||||||
        let firstByFields<'TDoc> tableName howMatched fields conn =
 | 
					        let firstByFields<'TDoc> tableName howMatched fields conn =
 | 
				
			||||||
            Custom.single
 | 
					            Custom.single
 | 
				
			||||||
                $"{Query.Find.byFields tableName howMatched fields} LIMIT 1"
 | 
					                $"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1"
 | 
				
			||||||
                (addFieldParams fields [])
 | 
					                (addFieldParams fields [])
 | 
				
			||||||
                fromData<'TDoc>
 | 
					                fromData<'TDoc>
 | 
				
			||||||
                conn
 | 
					                conn
 | 
				
			||||||
@ -434,7 +375,7 @@ module WithConn =
 | 
				
			|||||||
        /// Retrieve documents via a comparison on JSON fields, returning only the first result
 | 
					        /// Retrieve documents via a comparison on JSON fields, returning only the first result
 | 
				
			||||||
        let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, conn) =
 | 
					        let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, conn) =
 | 
				
			||||||
            Custom.Single(
 | 
					            Custom.Single(
 | 
				
			||||||
                $"{Query.Find.byFields tableName howMatched fields} LIMIT 1",
 | 
					                $"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1",
 | 
				
			||||||
                addFieldParams fields [],
 | 
					                addFieldParams fields [],
 | 
				
			||||||
                fromData<'TDoc>,
 | 
					                fromData<'TDoc>,
 | 
				
			||||||
                conn)
 | 
					                conn)
 | 
				
			||||||
@ -472,13 +413,14 @@ module WithConn =
 | 
				
			|||||||
        /// Patch a document by its ID
 | 
					        /// Patch a document by its ID
 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					        [<CompiledName "ById">]
 | 
				
			||||||
        let byId tableName (docId: 'TKey) (patch: 'TPatch) conn =
 | 
					        let byId tableName (docId: 'TKey) (patch: 'TPatch) conn =
 | 
				
			||||||
            Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] conn
 | 
					            Custom.nonQuery
 | 
				
			||||||
 | 
					                (Query.byId (Query.patch tableName) docId) [ idParam docId; jsonParam "@data" patch ] conn
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Patch documents using a comparison on JSON fields
 | 
					        /// Patch documents using a comparison on JSON fields
 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields (patch: 'TPatch) conn =
 | 
					        let byFields tableName howMatched fields (patch: 'TPatch) conn =
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.Patch.byFields tableName howMatched fields)
 | 
					                (Query.byFields (Query.patch tableName) howMatched fields)
 | 
				
			||||||
                (addFieldParams fields [ jsonParam "@data" patch ])
 | 
					                (addFieldParams fields [ jsonParam "@data" patch ])
 | 
				
			||||||
                conn
 | 
					                conn
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@ -497,7 +439,7 @@ module WithConn =
 | 
				
			|||||||
        let byId tableName (docId: 'TKey) fieldNames conn =
 | 
					        let byId tableName (docId: 'TKey) fieldNames conn =
 | 
				
			||||||
            let nameParams = fieldNameParams "@name" fieldNames
 | 
					            let nameParams = fieldNameParams "@name" fieldNames
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.RemoveFields.byId tableName nameParams)
 | 
					                (Query.byId (Query.removeFields tableName nameParams) docId)
 | 
				
			||||||
                (idParam docId |> Seq.singleton |> Seq.append nameParams)
 | 
					                (idParam docId |> Seq.singleton |> Seq.append nameParams)
 | 
				
			||||||
                conn
 | 
					                conn
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -506,7 +448,7 @@ module WithConn =
 | 
				
			|||||||
        let byFields tableName howMatched fields fieldNames conn =
 | 
					        let byFields tableName howMatched fields fieldNames conn =
 | 
				
			||||||
            let nameParams = fieldNameParams "@name" fieldNames
 | 
					            let nameParams = fieldNameParams "@name" fieldNames
 | 
				
			||||||
            Custom.nonQuery
 | 
					            Custom.nonQuery
 | 
				
			||||||
                (Query.RemoveFields.byFields tableName howMatched fields nameParams)
 | 
					                (Query.byFields (Query.removeFields tableName nameParams) howMatched fields)
 | 
				
			||||||
                (addFieldParams fields nameParams)
 | 
					                (addFieldParams fields nameParams)
 | 
				
			||||||
                conn
 | 
					                conn
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -523,12 +465,12 @@ module WithConn =
 | 
				
			|||||||
        /// Delete a document by its ID
 | 
					        /// Delete a document by its ID
 | 
				
			||||||
        [<CompiledName "ById">]
 | 
					        [<CompiledName "ById">]
 | 
				
			||||||
        let byId tableName (docId: 'TKey) conn =
 | 
					        let byId tableName (docId: 'TKey) conn =
 | 
				
			||||||
            Custom.nonQuery (Query.Delete.byId tableName) [ idParam docId ] conn
 | 
					            Custom.nonQuery (Query.byId (Query.delete tableName) docId) [ idParam docId ] conn
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Delete documents by matching a comparison on JSON fields
 | 
					        /// Delete documents by matching a comparison on JSON fields
 | 
				
			||||||
        [<CompiledName "ByFields">]
 | 
					        [<CompiledName "ByFields">]
 | 
				
			||||||
        let byFields tableName howMatched fields conn =
 | 
					        let byFields tableName howMatched fields conn =
 | 
				
			||||||
            Custom.nonQuery (Query.Delete.byFields tableName howMatched fields) (addFieldParams fields []) conn
 | 
					            Custom.nonQuery (Query.byFields (Query.delete tableName) howMatched fields) (addFieldParams fields []) conn
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /// Delete documents by matching a comparison on a JSON field
 | 
					        /// Delete documents by matching a comparison on a JSON field
 | 
				
			||||||
        [<CompiledName "ByField">]
 | 
					        [<CompiledName "ByField">]
 | 
				
			||||||
 | 
				
			|||||||
@ -238,10 +238,9 @@ public static class CommonCSharpTests
 | 
				
			|||||||
        ]),
 | 
					        ]),
 | 
				
			||||||
        TestList("Query",
 | 
					        TestList("Query",
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
            TestCase("SelectFromTable succeeds", () =>
 | 
					            TestCase("StatementWhere succeeds", () =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Expect.equal(Query.SelectFromTable("test.table"), "SELECT data FROM test.table",
 | 
					                Expect.equal(Query.StatementWhere("q", "r"), "q WHERE r", "Statements not combined correctly");
 | 
				
			||||||
                    "SELECT statement not correct");
 | 
					 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
            TestList("Definition",
 | 
					            TestList("Definition",
 | 
				
			||||||
            [
 | 
					            [
 | 
				
			||||||
@ -266,7 +265,9 @@ public static class CommonCSharpTests
 | 
				
			|||||||
                            "CREATE INDEX for key statement without schema not constructed correctly");
 | 
					                            "CREATE INDEX for key statement without schema not constructed correctly");
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                ]),
 | 
					                ]),
 | 
				
			||||||
                TestCase("EnsureIndexOn succeeds for multiple fields and directions", () =>
 | 
					                TestList("EnsureIndexOn",
 | 
				
			||||||
 | 
					                [
 | 
				
			||||||
 | 
					                    TestCase("succeeds for multiple fields and directions", () =>
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        Expect.equal(
 | 
					                        Expect.equal(
 | 
				
			||||||
                            Query.Definition.EnsureIndexOn("test.table", "gibberish",
 | 
					                            Query.Definition.EnsureIndexOn("test.table", "gibberish",
 | 
				
			||||||
@ -274,7 +275,22 @@ public static class CommonCSharpTests
 | 
				
			|||||||
                            "CREATE INDEX IF NOT EXISTS idx_table_gibberish ON test.table "
 | 
					                            "CREATE INDEX IF NOT EXISTS idx_table_gibberish ON test.table "
 | 
				
			||||||
                            + "((data->>'taco'), (data->>'guac') DESC, (data->>'salsa') ASC)",
 | 
					                            + "((data->>'taco'), (data->>'guac') DESC, (data->>'salsa') ASC)",
 | 
				
			||||||
                            "CREATE INDEX for multiple field statement incorrect");
 | 
					                            "CREATE INDEX for multiple field statement incorrect");
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    TestCase("succeeds for nested PostgreSQL field", () =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Expect.equal(
 | 
				
			||||||
 | 
					                            Query.Definition.EnsureIndexOn("tbl", "nest", ["a.b.c"], Dialect.PostgreSQL),
 | 
				
			||||||
 | 
					                            "CREATE INDEX IF NOT EXISTS idx_tbl_nest ON tbl ((data#>>'{a,b,c}'))",
 | 
				
			||||||
 | 
					                            "CREATE INDEX for nested PostgreSQL field incorrect");
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    TestCase("succeeds for nested SQLite field", () =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Expect.equal(
 | 
				
			||||||
 | 
					                            Query.Definition.EnsureIndexOn("tbl", "nest", ["a.b.c"], Dialect.SQLite),
 | 
				
			||||||
 | 
					                            "CREATE INDEX IF NOT EXISTS idx_tbl_nest ON tbl ((data->>'a'->>'b'->>'c'))",
 | 
				
			||||||
 | 
					                            "CREATE INDEX for nested SQLite field incorrect");
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
 | 
					                ])
 | 
				
			||||||
            ]),
 | 
					            ]),
 | 
				
			||||||
            TestCase("Insert succeeds", () =>
 | 
					            TestCase("Insert succeeds", () =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -285,6 +301,27 @@ public static class CommonCSharpTests
 | 
				
			|||||||
                Expect.equal(Query.Save("tbl"),
 | 
					                Expect.equal(Query.Save("tbl"),
 | 
				
			||||||
                    "INSERT INTO tbl VALUES (@data) ON CONFLICT ((data->>'Id')) DO UPDATE SET data = EXCLUDED.data",
 | 
					                    "INSERT INTO tbl VALUES (@data) ON CONFLICT ((data->>'Id')) DO UPDATE SET data = EXCLUDED.data",
 | 
				
			||||||
                    "INSERT ON CONFLICT UPDATE statement not correct");
 | 
					                    "INSERT ON CONFLICT UPDATE statement not correct");
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            TestCase("Count succeeds", () =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Expect.equal(Query.Count("tbl"), "SELECT COUNT(*) AS it FROM tbl", "Count query not correct");
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            TestCase("Exists succeeds", () =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Expect.equal(Query.Exists("tbl", "chicken"), "SELECT EXISTS (SELECT 1 FROM tbl WHERE chicken) AS it",
 | 
				
			||||||
 | 
					                    "Exists query not correct");
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            TestCase("Find succeeds", () =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Expect.equal(Query.Find("test.table"), "SELECT data FROM test.table", "Find query not correct");
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            TestCase("Update succeeds", () =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Expect.equal(Query.Update("tbl"), "UPDATE tbl SET data = @data", "Update query not correct");
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            TestCase("Delete succeeds", () =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Expect.equal(Query.Delete("tbl"), "DELETE FROM tbl", "Delete query not correct");
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
 | 
				
			|||||||
@ -279,153 +279,7 @@ public static class PostgresCSharpTests
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                Expect.equal(Postgres.Query.WhereJsonPathMatches("@path"), "data @? @path::jsonpath",
 | 
					                Expect.equal(Postgres.Query.WhereJsonPathMatches("@path"), "data @? @path::jsonpath",
 | 
				
			||||||
                    "WHERE clause not correct");
 | 
					                    "WHERE clause not correct");
 | 
				
			||||||
            }),
 | 
					 | 
				
			||||||
            TestList("Find",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Find.ById(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "SELECT by ID query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("ByFields succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(
 | 
					 | 
				
			||||||
                        Postgres.Query.Find.ByFields("x", FieldMatch.Any, [Field.GE("Golf", 0), Field.LE("Flog", 1)]),
 | 
					 | 
				
			||||||
                        $"SELECT data FROM x WHERE data->>'Golf' >= @field0 OR data->>'Flog' <= @field1",
 | 
					 | 
				
			||||||
                        "SELECT by JSON comparison query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Find.ByField(PostgresDb.TableName, Field.GE("Golf", 0)),
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data->>'Golf' >= @field0",
 | 
					 | 
				
			||||||
                        "SELECT by JSON comparison query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
                TestCase("byContains succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Find.ByContains(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data @> @criteria",
 | 
					 | 
				
			||||||
                        "SELECT by JSON containment query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("byJsonPath succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Find.ByJsonPath(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath",
 | 
					 | 
				
			||||||
                        "SELECT by JSON Path match query not correct");
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
            TestList("Patch",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Patch.ById(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("ByFields succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(
 | 
					 | 
				
			||||||
                        Postgres.Query.Patch.ByFields("x", FieldMatch.All,
 | 
					 | 
				
			||||||
                            [Field.LT("Snail", 0), Field.BT("Slug", 8, 14)]),
 | 
					 | 
				
			||||||
                        $"UPDATE x SET data = data || @data WHERE data->>'Snail' < @field0 AND (data->>'Slug')::numeric BETWEEN @field1min AND @field1max",
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Patch.ByField(PostgresDb.TableName, Field.LT("Snail", 0)),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data->>'Snail' < @field0",
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
                TestCase("ByContains succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Patch.ByContains(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @> @criteria",
 | 
					 | 
				
			||||||
                        "UPDATE partial by JSON containment statement not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("ByJsonPath succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Patch.ByJsonPath(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @? @path::jsonpath",
 | 
					 | 
				
			||||||
                        "UPDATE partial by JSON Path statement not correct");
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
            TestList("RemoveFields",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.RemoveFields.ById(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "Remove field by ID query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("ByFields succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(
 | 
					 | 
				
			||||||
                        Postgres.Query.RemoveFields.ByFields("x", FieldMatch.Any,
 | 
					 | 
				
			||||||
                            [Field.LT("Fly", 0), Field.LT("Ant", 2)]),
 | 
					 | 
				
			||||||
                        $"UPDATE x SET data = data - @name WHERE data->>'Fly' < @field0 OR data->>'Ant' < @field1",
 | 
					 | 
				
			||||||
                        "Remove field by field query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.RemoveFields.ByField(PostgresDb.TableName, Field.LT("Fly", 0)),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data->>'Fly' < @field0",
 | 
					 | 
				
			||||||
                        "Remove field by field query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
                TestCase("ByContains succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.RemoveFields.ByContains(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data @> @criteria",
 | 
					 | 
				
			||||||
                        "Remove field by contains query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("ByJsonPath succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.RemoveFields.ByJsonPath(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data @? @path::jsonpath",
 | 
					 | 
				
			||||||
                        "Remove field by JSON path query not correct");
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
            TestList("Delete",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Delete.ById(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "DELETE by ID query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("ByFields succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(
 | 
					 | 
				
			||||||
                        Postgres.Query.Delete.ByFields("tbl", FieldMatch.All, [Field.NEX("gone"), Field.EX("here")]),
 | 
					 | 
				
			||||||
                        $"DELETE FROM tbl WHERE data->>'gone' IS NULL AND data->>'here' IS NOT NULL",
 | 
					 | 
				
			||||||
                        "DELETE by JSON comparison query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Delete.ByField(PostgresDb.TableName, Field.NEX("gone")),
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data->>'gone' IS NULL",
 | 
					 | 
				
			||||||
                        "DELETE by JSON comparison query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
                TestCase("byContains succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Delete.ByContains(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data @> @criteria",
 | 
					 | 
				
			||||||
                        "DELETE by JSON containment query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
                TestCase("byJsonPath succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Postgres.Query.Delete.ByJsonPath(PostgresDb.TableName),
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath",
 | 
					 | 
				
			||||||
                        "DELETE by JSON Path match query not correct");
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            ])
 | 
					 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -91,73 +91,7 @@ public static class SqliteCSharpTests
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                Expect.equal(Sqlite.Query.Definition.EnsureTable("tbl"),
 | 
					                Expect.equal(Sqlite.Query.Definition.EnsureTable("tbl"),
 | 
				
			||||||
                    "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)", "CREATE TABLE statement not correct");
 | 
					                    "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)", "CREATE TABLE statement not correct");
 | 
				
			||||||
            }),
 | 
					 | 
				
			||||||
            TestList("Find",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.Find.ById("tbl"), "SELECT data FROM tbl WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "SELECT by ID query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.Find.ByField("tbl", Field.GE("Golf", 0)),
 | 
					 | 
				
			||||||
                        "SELECT data FROM tbl WHERE data->>'Golf' >= @field0",
 | 
					 | 
				
			||||||
                        "SELECT by JSON comparison query not correct");
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
            TestList("Patch",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.Patch.ById("tbl"),
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.Patch.ByField("tbl", Field.NE("Part", 0)),
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Part' <> @field0",
 | 
					 | 
				
			||||||
                        "UPDATE partial by JSON comparison query not correct");
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
            TestList("RemoveFields",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.RemoveFields.ById("tbl", new[] { new SqliteParameter("@name", "one") }),
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_remove(data, @name) WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "Remove field by ID query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.RemoveFields.ByField("tbl", Field.LT("Fly", 0),
 | 
					 | 
				
			||||||
                            new[] { new SqliteParameter("@name0", "one"), new SqliteParameter("@name1", "two") }),
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_remove(data, @name0, @name1) WHERE data->>'Fly' < @field0",
 | 
					 | 
				
			||||||
                        "Remove field by field query not correct");
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
            TestList("Delete",
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                TestCase("ById succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.Delete.ById("tbl"), "DELETE FROM tbl WHERE data->>'Id' = @id",
 | 
					 | 
				
			||||||
                        "DELETE by ID query not correct");
 | 
					 | 
				
			||||||
                }),
 | 
					 | 
				
			||||||
#pragma warning disable CS0618
 | 
					 | 
				
			||||||
                TestCase("ByField succeeds", () =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Expect.equal(Sqlite.Query.Delete.ByField("tbl", Field.NEX("gone")),
 | 
					 | 
				
			||||||
                        "DELETE FROM tbl WHERE data->>'gone' IS NULL", "DELETE by JSON comparison query not correct");
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
#pragma warning restore CS0618
 | 
					 | 
				
			||||||
            ])
 | 
					 | 
				
			||||||
        ]),
 | 
					        ]),
 | 
				
			||||||
        TestList("Parameters",
 | 
					        TestList("Parameters",
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
 | 
				
			|||||||
@ -170,8 +170,8 @@ let all =
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        testList "Query" [
 | 
					        testList "Query" [
 | 
				
			||||||
            test "selectFromTable succeeds" {
 | 
					            test "statementWhere succeeds" {
 | 
				
			||||||
                Expect.equal (Query.selectFromTable tbl) $"SELECT data FROM {tbl}" "SELECT statement not correct"
 | 
					                Expect.equal (Query.statementWhere "x" "y") "x WHERE y" "Statements not combined correctly"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            testList "Definition" [
 | 
					            testList "Definition" [
 | 
				
			||||||
                test "ensureTableFor succeeds" {
 | 
					                test "ensureTableFor succeeds" {
 | 
				
			||||||
@ -194,7 +194,8 @@ let all =
 | 
				
			|||||||
                            "CREATE INDEX for key statement without schema not constructed correctly"
 | 
					                            "CREATE INDEX for key statement without schema not constructed correctly"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
                test "ensureIndexOn succeeds for multiple fields and directions" {
 | 
					                testList "ensureIndexOn" [
 | 
				
			||||||
 | 
					                    test "succeeds for multiple fields and directions" {
 | 
				
			||||||
                        Expect.equal
 | 
					                        Expect.equal
 | 
				
			||||||
                            (Query.Definition.ensureIndexOn
 | 
					                            (Query.Definition.ensureIndexOn
 | 
				
			||||||
                                 "test.table" "gibberish" [ "taco"; "guac DESC"; "salsa ASC" ] PostgreSQL)
 | 
					                                 "test.table" "gibberish" [ "taco"; "guac DESC"; "salsa ASC" ] PostgreSQL)
 | 
				
			||||||
@ -203,6 +204,19 @@ let all =
 | 
				
			|||||||
                             |> String.concat "")
 | 
					                             |> String.concat "")
 | 
				
			||||||
                            "CREATE INDEX for multiple field statement incorrect"
 | 
					                            "CREATE INDEX for multiple field statement incorrect"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    test "succeeds for nested PostgreSQL field" {
 | 
				
			||||||
 | 
					                        Expect.equal
 | 
				
			||||||
 | 
					                            (Query.Definition.ensureIndexOn tbl "nest" [ "a.b.c" ] PostgreSQL)
 | 
				
			||||||
 | 
					                            $"CREATE INDEX IF NOT EXISTS idx_{tbl}_nest ON {tbl} ((data#>>'{{a,b,c}}'))"
 | 
				
			||||||
 | 
					                            "CREATE INDEX for nested PostgreSQL field incorrect"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    test "succeeds for nested SQLite field" {
 | 
				
			||||||
 | 
					                        Expect.equal
 | 
				
			||||||
 | 
					                            (Query.Definition.ensureIndexOn tbl "nest" [ "a.b.c" ] SQLite)
 | 
				
			||||||
 | 
					                            $"CREATE INDEX IF NOT EXISTS idx_{tbl}_nest ON {tbl} ((data->>'a'->>'b'->>'c'))"
 | 
				
			||||||
 | 
					                            "CREATE INDEX for nested SQLite field incorrect"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
            test "insert succeeds" {
 | 
					            test "insert succeeds" {
 | 
				
			||||||
                Expect.equal (Query.insert tbl) $"INSERT INTO {tbl} VALUES (@data)" "INSERT statement not correct"
 | 
					                Expect.equal (Query.insert tbl) $"INSERT INTO {tbl} VALUES (@data)" "INSERT statement not correct"
 | 
				
			||||||
@ -214,7 +228,22 @@ let all =
 | 
				
			|||||||
                    "INSERT ON CONFLICT UPDATE statement not correct"
 | 
					                    "INSERT ON CONFLICT UPDATE statement not correct"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            test "count succeeds" {
 | 
					            test "count succeeds" {
 | 
				
			||||||
                Expect.equal (Query.count "a_table") "SELECT COUNT(*) AS it FROM a_table" "Count query not correct"
 | 
					                Expect.equal (Query.count tbl) $"SELECT COUNT(*) AS it FROM {tbl}" "Count query not correct"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            test "exists succeeds" {
 | 
				
			||||||
 | 
					                Expect.equal
 | 
				
			||||||
 | 
					                    (Query.exists tbl "turkey")
 | 
				
			||||||
 | 
					                    $"SELECT EXISTS (SELECT 1 FROM {tbl} WHERE turkey) AS it"
 | 
				
			||||||
 | 
					                    "Exists query not correct"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            test "find succeeds" {
 | 
				
			||||||
 | 
					                Expect.equal (Query.find tbl) $"SELECT data FROM {tbl}" "Find query not correct"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            test "update succeeds" {
 | 
				
			||||||
 | 
					                Expect.equal (Query.update tbl) $"UPDATE {tbl} SET data = @data" "Update query not correct"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            test "delete succeeds" {
 | 
				
			||||||
 | 
					                Expect.equal (Query.delete tbl) $"DELETE FROM {tbl}" "Delete query not correct"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
				
			|||||||
@ -252,132 +252,6 @@ let unitTests =
 | 
				
			|||||||
            test "whereJsonPathMatches succeeds" {
 | 
					            test "whereJsonPathMatches succeeds" {
 | 
				
			||||||
                Expect.equal (Query.whereJsonPathMatches "@path") "data @? @path::jsonpath" "WHERE clause not correct"
 | 
					                Expect.equal (Query.whereJsonPathMatches "@path") "data @? @path::jsonpath" "WHERE clause not correct"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            testList "Find" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byId PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "SELECT by ID query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byFields succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byFields "tbl" Any [ Field.GE "Golf" 0; Field.LE "Flog" 1 ])
 | 
					 | 
				
			||||||
                        $"SELECT data FROM tbl WHERE data->>'Golf' >= @field0 OR data->>'Flog' <= @field1"
 | 
					 | 
				
			||||||
                        "SELECT by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byField PostgresDb.TableName (Field.GE "Golf" 0))
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data->>'Golf' >= @field0"
 | 
					 | 
				
			||||||
                        "SELECT by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byContains succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byContains PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data @> @criteria"
 | 
					 | 
				
			||||||
                        "SELECT by JSON containment query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byJsonPath succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byJsonPath PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath"
 | 
					 | 
				
			||||||
                        "SELECT by JSON Path match query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
            testList "Patch" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byId PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byFields succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byFields "x" All [ Field.LT "Snail" 0; Field.BT "Slug" 8 12 ])
 | 
					 | 
				
			||||||
                        $"UPDATE x SET data = data || @data WHERE data->>'Snail' < @field0 AND (data->>'Slug')::numeric BETWEEN @field1min AND @field1max"
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byField PostgresDb.TableName (Field.LT "Snail" 0))
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data->>'Snail' < @field0"
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byContains succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byContains PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @> @criteria"
 | 
					 | 
				
			||||||
                        "UPDATE partial by JSON containment statement not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byJsonPath succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byJsonPath PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @? @path::jsonpath"
 | 
					 | 
				
			||||||
                        "UPDATE partial by JSON Path statement not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
            testList "RemoveFields" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byId PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "Remove field by ID query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byFields succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byFields "tbl" Any [ Field.LT "Fly" 0; Field.LT "Ant" 2 ])
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = data - @name WHERE data->>'Fly' < @field0 OR data->>'Ant' < @field1"
 | 
					 | 
				
			||||||
                        "Remove field by field query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byField PostgresDb.TableName (Field.LT "Fly" 0))
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data->>'Fly' < @field0"
 | 
					 | 
				
			||||||
                        "Remove field by field query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byContains succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byContains PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data @> @criteria"
 | 
					 | 
				
			||||||
                        "Remove field by contains query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byJsonPath succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byJsonPath PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data @? @path::jsonpath"
 | 
					 | 
				
			||||||
                        "Remove field by JSON path query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
            testList "Delete" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Delete.byId PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "DELETE by ID query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byFields succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Delete.byFields PostgresDb.TableName All [ Field.NEX "gone"; Field.EX "here" ])
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data->>'gone' IS NULL AND data->>'here' IS NOT NULL"
 | 
					 | 
				
			||||||
                        "DELETE by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Delete.byField PostgresDb.TableName (Field.NEX "gone"))
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data->>'gone' IS NULL"
 | 
					 | 
				
			||||||
                        "DELETE by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byContains succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal (Query.Delete.byContains PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data @> @criteria"
 | 
					 | 
				
			||||||
                        "DELETE by JSON containment query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byJsonPath succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal (Query.Delete.byJsonPath PostgresDb.TableName)
 | 
					 | 
				
			||||||
                        $"DELETE FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath"
 | 
					 | 
				
			||||||
                        "DELETE by JSON Path match query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -81,65 +81,6 @@ let unitTests =
 | 
				
			|||||||
                    "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)"
 | 
					                    "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)"
 | 
				
			||||||
                    "CREATE TABLE statement not correct"
 | 
					                    "CREATE TABLE statement not correct"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            testList "Find" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byId "tbl")
 | 
					 | 
				
			||||||
                        "SELECT data FROM tbl WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "SELECT by ID query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Find.byField "tbl" (Field.GE "Golf" 0))
 | 
					 | 
				
			||||||
                        "SELECT data FROM tbl WHERE data->>'Golf' >= @field0"
 | 
					 | 
				
			||||||
                        "SELECT by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
            testList "Patch" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byId "tbl")
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "UPDATE partial by ID statement not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Patch.byField "tbl" (Field.NE "Part" 0))
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Part' <> @field0"
 | 
					 | 
				
			||||||
                        "UPDATE partial by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
            testList "RemoveFields" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byId "tbl" [ SqliteParameter("@name", "one") ])
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_remove(data, @name) WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "Remove field by ID query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.RemoveFields.byField
 | 
					 | 
				
			||||||
                             "tbl"
 | 
					 | 
				
			||||||
                             (Field.GT "Fly" 0)
 | 
					 | 
				
			||||||
                             [ SqliteParameter("@name0", "one"); SqliteParameter("@name1", "two") ])
 | 
					 | 
				
			||||||
                        "UPDATE tbl SET data = json_remove(data, @name0, @name1) WHERE data->>'Fly' > @field0"
 | 
					 | 
				
			||||||
                        "Remove field by field query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
            testList "Delete" [
 | 
					 | 
				
			||||||
                test "byId succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Delete.byId "tbl")
 | 
					 | 
				
			||||||
                        "DELETE FROM tbl WHERE data->>'Id' = @id"
 | 
					 | 
				
			||||||
                        "DELETE by ID query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                test "byField succeeds" {
 | 
					 | 
				
			||||||
                    Expect.equal
 | 
					 | 
				
			||||||
                        (Query.Delete.byField "tbl" (Field.NEX "gone"))
 | 
					 | 
				
			||||||
                        "DELETE FROM tbl WHERE data->>'gone' IS NULL"
 | 
					 | 
				
			||||||
                        "DELETE by JSON comparison query not correct"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        testList "Parameters" [
 | 
					        testList "Parameters" [
 | 
				
			||||||
            test "idParam succeeds" {
 | 
					            test "idParam succeeds" {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user