diff --git a/src/Postgres/Extensions.fs b/src/Postgres/Extensions.fs index e53536c..da0d24d 100644 --- a/src/Postgres/Extensions.fs +++ b/src/Postgres/Extensions.fs @@ -38,7 +38,7 @@ module Extensions = /// The query to retrieve the results /// Parameters to use for the query /// The mapping function between the document and the domain item - /// Some with the first matching result, or None if not found + /// Some with the first matching result, or None if not found member conn.customSingle<'TDoc> query parameters (mapFunc: RowReader -> 'TDoc) = Custom.single<'TDoc> query parameters mapFunc (Sql.existingConnection conn) @@ -102,7 +102,7 @@ module Extensions = member conn.countAll tableName = Count.all tableName (Sql.existingConnection conn) - /// Count matching documents using JSON field comparisons (->> =, etc.) + /// Count matching documents using JSON field comparisons (->> =, etc.) /// The table in which documents should be counted (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -110,14 +110,14 @@ module Extensions = member conn.countByFields tableName howMatched fields = Count.byFields tableName howMatched fields (Sql.existingConnection conn) - /// Count matching documents using a JSON containment query (@>) + /// Count matching documents using a JSON containment query (@>) /// The table in which documents should be counted (may include schema) /// The document to match with the containment query /// The count of the documents in the table member conn.countByContains tableName criteria = Count.byContains tableName criteria (Sql.existingConnection conn) - /// Count matching documents using a JSON Path match query (@?) + /// Count matching documents using a JSON Path match query (@?) /// The table in which documents should be counted (may include schema) /// The JSON Path expression to be matched /// The count of the documents in the table @@ -131,7 +131,7 @@ module Extensions = member conn.existsById tableName docId = Exists.byId tableName docId (Sql.existingConnection conn) - /// Determine if a document exists using JSON field comparisons (->> =, etc.) + /// Determine if a document exists using JSON field comparisons (->> =, etc.) /// The table in which existence should be checked (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -139,14 +139,14 @@ module Extensions = member conn.existsByFields tableName howMatched fields = Exists.byFields tableName howMatched fields (Sql.existingConnection conn) - /// Determine if a document exists using a JSON containment query (@>) + /// Determine if a document exists using a JSON containment query (@>) /// The table in which existence should be checked (may include schema) /// The document to match with the containment query /// True if any matching documents exist, false if not member conn.existsByContains tableName criteria = Exists.byContains tableName criteria (Sql.existingConnection conn) - /// Determine if a document exists using a JSON Path match query (@?) + /// Determine if a document exists using a JSON Path match query (@?) /// The table in which existence should be checked (may include schema) /// The JSON Path expression to be matched /// True if any matching documents exist, false if not @@ -169,11 +169,11 @@ module Extensions = /// Retrieve a document by its ID /// The table from which a document should be retrieved (may include schema) /// The ID of the document to retrieve - /// Some with the document if found, None otherwise + /// Some with the document if found, None otherwise member conn.findById<'TKey, 'TDoc> tableName docId = Find.byId<'TKey, 'TDoc> tableName docId (Sql.existingConnection conn) - /// Retrieve documents matching JSON field comparisons (->> =, etc.) + /// Retrieve documents matching JSON field comparisons (->> =, etc.) /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -182,8 +182,8 @@ module Extensions = Find.byFields<'TDoc> tableName howMatched fields (Sql.existingConnection conn) /// - /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields - /// in the document + /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in + /// the document /// /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions @@ -194,7 +194,7 @@ module Extensions = Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields (Sql.existingConnection conn) - /// Retrieve documents matching a JSON containment query (@>) + /// Retrieve documents matching a JSON containment query (@>) /// The table from which documents should be retrieved (may include schema) /// The document to match with the containment query /// All documents matching the given containment query @@ -202,7 +202,7 @@ module Extensions = Find.byContains<'TDoc> tableName criteria (Sql.existingConnection conn) /// - /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the + /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the /// document /// /// The table from which documents should be retrieved (may include schema) @@ -212,7 +212,7 @@ module Extensions = member conn.findByContainsOrdered<'TDoc> tableName (criteria: obj) orderFields = Find.byContainsOrdered<'TDoc> tableName criteria orderFields (Sql.existingConnection conn) - /// Retrieve documents matching a JSON Path match query (@?) + /// Retrieve documents matching a JSON Path match query (@?) /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match /// All documents matching the given JSON Path expression @@ -220,8 +220,7 @@ module Extensions = Find.byJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn) /// - /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the - /// document + /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document /// /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match @@ -230,65 +229,65 @@ module Extensions = member conn.findByJsonPathOrdered<'TDoc> tableName jsonPath orderFields = Find.byJsonPathOrdered<'TDoc> tableName jsonPath orderFields (Sql.existingConnection conn) - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match - /// Some with the first document, or None if not found + /// Some with the first document, or None if not found member conn.findFirstByFields<'TDoc> tableName howMatched fields = Find.firstByFields<'TDoc> tableName howMatched fields (Sql.existingConnection conn) /// - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the - /// given fields in the document + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given + /// fields in the document /// /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match /// Fields by which the results should be ordered /// - /// Some with the first document ordered by the given fields, or None if not found + /// Some with the first document ordered by the given fields, or None if not found /// member conn.findFirstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields = Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields (Sql.existingConnection conn) - /// Retrieve the first document matching a JSON containment query (@>) + /// Retrieve the first document matching a JSON containment query (@>) /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query - /// Some with the first document, or None if not found + /// Some with the first document, or None if not found member conn.findFirstByContains<'TDoc> tableName (criteria: obj) = Find.firstByContains<'TDoc> tableName criteria (Sql.existingConnection conn) /// - /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields - /// in the document + /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in + /// the document /// /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query /// Fields by which the results should be ordered /// - /// Some with the first document ordered by the given fields, or None if not found + /// Some with the first document ordered by the given fields, or None if not found /// member conn.findFirstByContainsOrdered<'TDoc> tableName (criteria: obj) orderFields = Find.firstByContainsOrdered<'TDoc> tableName criteria orderFields (Sql.existingConnection conn) - /// Retrieve the first document matching a JSON Path match query (@?) + /// Retrieve the first document matching a JSON Path match query (@?) /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match - /// Some with the first document, or None if not found + /// Some with the first document, or None if not found member conn.findFirstByJsonPath<'TDoc> tableName jsonPath = Find.firstByJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn) /// - /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in - /// the document + /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the + /// document /// /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match /// Fields by which the results should be ordered /// - /// Some with the first document ordered by the given fields, or None if not found + /// Some with the first document ordered by the given fields, or None if not found /// member conn.findFirstByJsonPathOrdered<'TDoc> tableName jsonPath orderFields = Find.firstByJsonPathOrdered<'TDoc> tableName jsonPath orderFields (Sql.existingConnection conn) @@ -605,7 +604,7 @@ module Extensions = Patch.byId tableName docId patch (Sql.existingConnection conn) /// - /// Patch documents using a JSON field comparison query in the WHERE clause (->> =, + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =, /// etc.) /// /// The table in which documents should be patched (may include schema) @@ -616,7 +615,7 @@ module Extensions = Patch.byFields tableName howMatched fields patch (Sql.existingConnection conn) /// - /// Patch documents using a JSON containment query in the WHERE clause (@>) + /// Patch documents using a JSON containment query in the WHERE clause (@>) /// /// The table in which documents should be patched (may include schema) /// The document to match the containment query @@ -624,7 +623,7 @@ module Extensions = member conn.patchByContains tableName (criteria: 'TCriteria) (patch: 'TPatch) = Patch.byContains tableName criteria patch (Sql.existingConnection conn) - /// Patch documents using a JSON Path match query in the WHERE clause (@?) + /// Patch documents using a JSON Path match query in the WHERE clause (@?) /// The table in which documents should be patched (may include schema) /// The JSON Path expression to match /// The partial document to patch the existing document @@ -646,14 +645,14 @@ module Extensions = member conn.removeFieldsByFields tableName howMatched fields fieldNames = RemoveFields.byFields tableName howMatched fields fieldNames (Sql.existingConnection conn) - /// Remove fields from documents via a JSON containment query (@>) + /// Remove fields from documents via a JSON containment query (@>) /// The table in which documents should be modified (may include schema) /// The document to match the containment query /// One or more field names to remove from the matching documents member conn.removeFieldsByContains tableName (criteria: 'TContains) fieldNames = 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 (@?) /// The table in which documents should be modified (may include schema) /// The JSON Path expression to match /// One or more field names to remove from the matching documents @@ -666,14 +665,14 @@ module Extensions = member conn.deleteById tableName (docId: 'TKey) = Delete.byId tableName docId (Sql.existingConnection conn) - /// Delete documents by matching a JSON field comparison query (->> =, etc.) + /// Delete documents by matching a JSON field comparison query (->> =, etc.) /// The table in which documents should be deleted (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match member conn.deleteByFields tableName howMatched fields = Delete.byFields tableName howMatched fields (Sql.existingConnection conn) - /// Delete documents by matching a JSON contains query (@>) + /// Delete documents by matching a JSON contains query (@>) /// The table in which documents should be deleted (may include schema) /// The document to match the containment query member conn.deleteByContains tableName (criteria: 'TContains) = @@ -707,6 +706,7 @@ type NpgsqlConnectionCSharpExtensions = /// Parameters to use for the query /// The mapping function to extract the document /// A JSON array of results for the given query + [] static member inline CustomJsonArray(conn, query, parameters, mapFunc) = Custom.JsonArray(query, parameters, mapFunc, Sql.existingConnection conn) @@ -716,6 +716,7 @@ type NpgsqlConnectionCSharpExtensions = /// Parameters to use for the query /// The StreamWriter to which the results should be written /// The mapping function to extract the document + [] static member inline WriteCustomJsonArray(conn, query, parameters, writer, mapFunc) = Custom.WriteJsonArray(query, parameters, writer, mapFunc, Sql.existingConnection conn) @@ -724,7 +725,7 @@ type NpgsqlConnectionCSharpExtensions = /// The query to retrieve the results /// Parameters to use for the query /// The mapping function between the document and the domain item - /// The first matching result, or null if not found + /// The first matching result, or null if not found [] static member inline CustomSingle<'TDoc when 'TDoc: null and 'TDoc: not struct>( conn, query, parameters, mapFunc: System.Func) = @@ -736,6 +737,7 @@ type NpgsqlConnectionCSharpExtensions = /// Parameters to use for the query /// The mapping function to extract the document /// The JSON document with the first matching result, or an empty document if not found + [] static member inline CustomJsonSingle(conn, query, parameters, mapFunc) = Custom.JsonSingle(query, parameters, mapFunc, Sql.existingConnection conn) @@ -806,7 +808,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline CountAll(conn, tableName) = Count.all tableName (Sql.existingConnection conn) - /// Count matching documents using JSON field comparisons (->> =, etc.) + /// Count matching documents using JSON field comparisons (->> =, etc.) /// The NpgsqlConnection on which to run the query /// The table in which documents should be counted (may include schema) /// Whether to match any or all of the field conditions @@ -816,7 +818,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline CountByFields(conn, tableName, howMatched, fields) = Count.byFields tableName howMatched fields (Sql.existingConnection conn) - /// Count matching documents using a JSON containment query (@>) + /// Count matching documents using a JSON containment query (@>) /// The NpgsqlConnection on which to run the query /// The table in which documents should be counted (may include schema) /// The document to match with the containment query @@ -825,7 +827,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline CountByContains(conn, tableName, criteria: 'TCriteria) = Count.byContains tableName criteria (Sql.existingConnection conn) - /// Count matching documents using a JSON Path match query (@?) + /// Count matching documents using a JSON Path match query (@?) /// The NpgsqlConnection on which to run the query /// The table in which documents should be counted (may include schema) /// The JSON Path expression to be matched @@ -843,7 +845,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline ExistsById(conn, tableName, docId) = Exists.byId tableName docId (Sql.existingConnection conn) - /// Determine if a document exists using JSON field comparisons (->> =, etc.) + /// Determine if a document exists using JSON field comparisons (->> =, etc.) /// The NpgsqlConnection on which to run the query /// The table in which existence should be checked (may include schema) /// Whether to match any or all of the field conditions @@ -853,7 +855,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline ExistsByFields(conn, tableName, howMatched, fields) = Exists.byFields tableName howMatched fields (Sql.existingConnection conn) - /// Determine if a document exists using a JSON containment query (@>) + /// Determine if a document exists using a JSON containment query (@>) /// The NpgsqlConnection on which to run the query /// The table in which existence should be checked (may include schema) /// The document to match with the containment query @@ -862,7 +864,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline ExistsByContains(conn, tableName, criteria: 'TCriteria) = Exists.byContains tableName criteria (Sql.existingConnection conn) - /// Determine if a document exists using a JSON Path match query (@?) + /// Determine if a document exists using a JSON Path match query (@?) /// The NpgsqlConnection on which to run the query /// The table in which existence should be checked (may include schema) /// The JSON Path expression to be matched @@ -892,12 +894,12 @@ type NpgsqlConnectionCSharpExtensions = /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// The ID of the document to retrieve - /// The document if found, null otherwise + /// The document if found, null otherwise [] static member inline FindById<'TKey, 'TDoc when 'TDoc: null and 'TDoc: not struct>(conn, tableName, docId: 'TKey) = Find.ById<'TKey, 'TDoc>(tableName, docId, Sql.existingConnection conn) - /// Retrieve documents matching JSON field comparisons (->> =, etc.) + /// Retrieve documents matching JSON field comparisons (->> =, etc.) /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions @@ -908,8 +910,8 @@ type NpgsqlConnectionCSharpExtensions = Find.ByFields<'TDoc>(tableName, howMatched, fields, Sql.existingConnection conn) /// - /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in - /// the document + /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in the + /// document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -922,7 +924,7 @@ type NpgsqlConnectionCSharpExtensions = Find.ByFieldsOrdered<'TDoc>( tableName, howMatched, queryFields, orderFields, Sql.existingConnection conn) - /// Retrieve documents matching a JSON containment query (@>) + /// Retrieve documents matching a JSON containment query (@>) /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) /// The document to match with the containment query @@ -932,8 +934,7 @@ type NpgsqlConnectionCSharpExtensions = Find.ByContains<'TDoc>(tableName, criteria, Sql.existingConnection conn) /// - /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the - /// document + /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -944,7 +945,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline FindByContainsOrdered<'TDoc>(conn, tableName, criteria: obj, orderFields) = Find.ByContainsOrdered<'TDoc>(tableName, criteria, orderFields, Sql.existingConnection conn) - /// Retrieve documents matching a JSON Path match query (@?) + /// Retrieve documents matching a JSON Path match query (@?) /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match @@ -954,7 +955,7 @@ type NpgsqlConnectionCSharpExtensions = Find.ByJsonPath<'TDoc>(tableName, jsonPath, Sql.existingConnection conn) /// - /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document + /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -965,19 +966,19 @@ type NpgsqlConnectionCSharpExtensions = static member inline FindByJsonPathOrdered<'TDoc>(conn, tableName, jsonPath, orderFields) = Find.ByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields, Sql.existingConnection conn) - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match - /// The first document, or null if not found + /// The first document, or null if not found [] static member inline FindFirstByFields<'TDoc when 'TDoc: null and 'TDoc: not struct>( conn, tableName, howMatched, fields) = Find.FirstByFields<'TDoc>(tableName, howMatched, fields, Sql.existingConnection conn) /// - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given /// fields in the document /// /// The NpgsqlConnection on which to run the query @@ -985,55 +986,55 @@ type NpgsqlConnectionCSharpExtensions = /// Whether to match any or all of the field conditions /// The field conditions to match /// Fields by which the results should be ordered - /// The first document ordered by the given fields, or null if not found + /// The first document ordered by the given fields, or null if not found [] static member inline FindFirstByFieldsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>( conn, tableName, howMatched, queryFields, orderFields) = Find.FirstByFieldsOrdered<'TDoc>( tableName, howMatched, queryFields, orderFields, Sql.existingConnection conn) - /// Retrieve the first document matching a JSON containment query (@>) + /// Retrieve the first document matching a JSON containment query (@>) /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query - /// The first document, or null if not found + /// The first document, or null if not found [] static member inline FindFirstByContains<'TDoc when 'TDoc: null and 'TDoc: not struct>( conn, tableName, criteria: obj) = Find.FirstByContains<'TDoc>(tableName, criteria, Sql.existingConnection conn) /// - /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in - /// the document + /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in the + /// document /// /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query /// Fields by which the results should be ordered - /// The first document ordered by the given fields, or null if not found + /// The first document ordered by the given fields, or null if not found [] static member inline FindFirstByContainsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>( conn, tableName, criteria: obj, orderFields) = Find.FirstByContainsOrdered<'TDoc>(tableName, criteria, orderFields, Sql.existingConnection conn) - /// Retrieve the first document matching a JSON Path match query (@?) + /// Retrieve the first document matching a JSON Path match query (@?) /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match - /// The first document, or null if not found + /// The first document, or null if not found [] static member inline FindFirstByJsonPath<'TDoc when 'TDoc: null and 'TDoc: not struct>(conn, tableName, jsonPath) = Find.FirstByJsonPath<'TDoc>(tableName, jsonPath, Sql.existingConnection conn) /// - /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the + /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the /// document /// /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match /// Fields by which the results should be ordered - /// The first document ordered by the given fields, or null if not found + /// The first document ordered by the given fields, or null if not found [] static member inline FindFirstByJsonPathOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>( conn, tableName, jsonPath, orderFields) = @@ -1107,8 +1108,7 @@ type NpgsqlConnectionCSharpExtensions = Json.byFields tableName howMatched fields (Sql.existingConnection conn) /// - /// Write JSON documents to the given StreamWriter matching JSON field comparisons (->> =, - /// etc.) + /// Write JSON documents to the given StreamWriter matching JSON field comparisons (->> =, etc.) /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -1120,8 +1120,8 @@ type NpgsqlConnectionCSharpExtensions = Json.writeByFields tableName writer howMatched fields (Sql.existingConnection conn) /// - /// Retrieve JSON documents matching JSON field comparisons (->> =, etc.) ordered by the given - /// fields in the document + /// Retrieve JSON documents matching JSON field comparisons (->> =, etc.) ordered by the given fields + /// in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -1134,8 +1134,8 @@ type NpgsqlConnectionCSharpExtensions = Json.byFieldsOrdered tableName howMatched queryFields orderFields (Sql.existingConnection conn) /// - /// Write JSON documents to the given StreamWriter matching JSON field comparisons (->> =, - /// etc.) ordered by the given fields in the document + /// Write JSON documents to the given StreamWriter matching JSON field comparisons (->> =, etc.) + /// ordered by the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -1181,8 +1181,8 @@ type NpgsqlConnectionCSharpExtensions = Json.byContainsOrdered tableName criteria orderFields (Sql.existingConnection conn) /// - /// Write JSON documents to the given StreamWriter matching a JSON containment query (@>) - /// ordered by the given fields in the document + /// Write JSON documents to the given StreamWriter matching a JSON containment query (@>) ordered + /// by the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -1214,8 +1214,7 @@ type NpgsqlConnectionCSharpExtensions = Json.writeByJsonPath tableName writer jsonPath (Sql.existingConnection conn) /// - /// Retrieve JSON documents matching a JSON Path match query (@?) ordered by the given fields in the - /// document + /// Retrieve JSON documents matching a JSON Path match query (@?) ordered by the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -1227,8 +1226,8 @@ type NpgsqlConnectionCSharpExtensions = Json.byJsonPathOrdered tableName jsonPath orderFields (Sql.existingConnection conn) /// - /// Write JSON documents to the given StreamWriter matching a JSON Path match query (@?) ordered - /// by the given fields in the document + /// Write JSON documents to the given StreamWriter matching a JSON Path match query (@?) ordered by + /// the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which documents should be retrieved (may include schema) @@ -1239,9 +1238,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline WriteJsonByJsonPathOrdered(conn, tableName, writer, jsonPath, orderFields) = Json.writeByJsonPathOrdered tableName writer jsonPath orderFields (Sql.existingConnection conn) - /// - /// Retrieve the first JSON document matching JSON field comparisons (->> =, etc.) - /// + /// Retrieve the first JSON document matching JSON field comparisons (->> =, etc.) /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions @@ -1303,8 +1300,7 @@ type NpgsqlConnectionCSharpExtensions = Json.firstByContains tableName criteria (Sql.existingConnection conn) /// - /// Write the first JSON document to the given StreamWriter matching a JSON containment query - /// (@>) + /// Write the first JSON document to the given StreamWriter matching a JSON containment query (@>) /// /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) @@ -1315,8 +1311,8 @@ type NpgsqlConnectionCSharpExtensions = Json.writeFirstByContains tableName writer criteria (Sql.existingConnection conn) /// - /// Retrieve the first JSON document matching a JSON containment query (@>) ordered by the given - /// fields in the document + /// Retrieve the first JSON document matching a JSON containment query (@>) ordered by the given fields in + /// the document /// /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) @@ -1328,8 +1324,8 @@ type NpgsqlConnectionCSharpExtensions = Json.firstByContainsOrdered tableName criteria orderFields (Sql.existingConnection conn) /// - /// Write the first JSON document to the given StreamWriter matching a JSON containment query - /// (@>) ordered by the given fields in the document + /// Write the first JSON document to the given StreamWriter matching a JSON containment query (@>) + /// ordered by the given fields in the document /// /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) @@ -1361,8 +1357,8 @@ type NpgsqlConnectionCSharpExtensions = Json.writeFirstByJsonPath tableName writer jsonPath (Sql.existingConnection conn) /// - /// Retrieve the first JSON document matching a JSON Path match query (@?) ordered by the given fields - /// in the document + /// Retrieve the first JSON document matching a JSON Path match query (@?) ordered by the given fields in the + /// document /// /// The NpgsqlConnection on which to run the query /// The table from which a document should be retrieved (may include schema) @@ -1416,7 +1412,7 @@ type NpgsqlConnectionCSharpExtensions = Patch.byId tableName docId patch (Sql.existingConnection conn) /// - /// Patch documents using a JSON field comparison query in the WHERE clause (->> =, etc.) + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =, etc.) /// /// The NpgsqlConnection on which to run the query /// The table in which documents should be patched (may include schema) @@ -1427,7 +1423,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline PatchByFields(conn, tableName, howMatched, fields, patch: 'TPatch) = Patch.byFields tableName howMatched fields patch (Sql.existingConnection conn) - /// Patch documents using a JSON containment query in the WHERE clause (@>) + /// Patch documents using a JSON containment query in the WHERE clause (@>) /// The NpgsqlConnection on which to run the query /// The table in which documents should be patched (may include schema) /// The document to match the containment query @@ -1436,7 +1432,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline PatchByContains(conn, tableName, criteria: 'TCriteria, patch: 'TPatch) = Patch.byContains tableName criteria patch (Sql.existingConnection conn) - /// Patch documents using a JSON Path match query in the WHERE clause (@?) + /// Patch documents using a JSON Path match query in the WHERE clause (@?) /// The NpgsqlConnection on which to run the query /// The table in which documents should be patched (may include schema) /// The JSON Path expression to match @@ -1464,7 +1460,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline RemoveFieldsByFields(conn, tableName, howMatched, fields, fieldNames) = RemoveFields.byFields tableName howMatched fields fieldNames (Sql.existingConnection conn) - /// Remove fields from documents via a JSON containment query (@>) + /// Remove fields from documents via a JSON containment query (@>) /// The NpgsqlConnection on which to run the query /// The table in which documents should be modified (may include schema) /// The document to match the containment query @@ -1473,7 +1469,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline RemoveFieldsByContains(conn, tableName, criteria: 'TContains, fieldNames) = 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 (@?) /// The NpgsqlConnection on which to run the query /// The table in which documents should be modified (may include schema) /// The JSON Path expression to match @@ -1490,7 +1486,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline DeleteById(conn, tableName, docId: 'TKey) = Delete.byId tableName docId (Sql.existingConnection conn) - /// Delete documents by matching a JSON field comparison query (->> =, etc.) + /// Delete documents by matching a JSON field comparison query (->> =, etc.) /// The NpgsqlConnection on which to run the query /// The table in which documents should be deleted (may include schema) /// Whether to match any or all of the field conditions @@ -1499,7 +1495,7 @@ type NpgsqlConnectionCSharpExtensions = static member inline DeleteByFields(conn, tableName, howMatched, fields) = Delete.byFields tableName howMatched fields (Sql.existingConnection conn) - /// Delete documents by matching a JSON contains query (@>) + /// Delete documents by matching a JSON contains query (@>) /// The NpgsqlConnection on which to run the query /// The table in which documents should be deleted (may include schema) /// The document to match the containment query diff --git a/src/Postgres/Functions.fs b/src/Postgres/Functions.fs index 7ffca97..f9f0eae 100644 --- a/src/Postgres/Functions.fs +++ b/src/Postgres/Functions.fs @@ -59,7 +59,7 @@ module Custom = /// The query to retrieve the results /// Parameters to use for the query /// The mapping function between the document and the domain item - /// Some with the first matching result, or None if not found + /// Some with the first matching result, or None if not found [] let single<'TDoc> query parameters (mapFunc: RowReader -> 'TDoc) = WithProps.Custom.single<'TDoc> query parameters mapFunc (fromDataSource ()) @@ -68,7 +68,7 @@ module Custom = /// The query to retrieve the results /// Parameters to use for the query /// The mapping function between the document and the domain item - /// The first matching result, or null if not found + /// The first matching result, or null if not found let Single<'TDoc when 'TDoc: null and 'TDoc: not struct>( query, parameters, mapFunc: System.Func) = WithProps.Custom.Single<'TDoc>(query, parameters, mapFunc, fromDataSource ()) @@ -171,7 +171,7 @@ module Count = let all tableName = WithProps.Count.all tableName (fromDataSource ()) - /// Count matching documents using JSON field comparisons (->> =, etc.) + /// Count matching documents using JSON field comparisons (->> =, etc.) /// The table in which documents should be counted (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -180,7 +180,7 @@ module Count = let byFields tableName howMatched fields = WithProps.Count.byFields tableName howMatched fields (fromDataSource ()) - /// Count matching documents using a JSON containment query (@>) + /// Count matching documents using a JSON containment query (@>) /// The table in which documents should be counted (may include schema) /// The document to match with the containment query /// The count of the documents in the table @@ -188,7 +188,7 @@ module Count = let byContains tableName criteria = WithProps.Count.byContains tableName criteria (fromDataSource ()) - /// Count matching documents using a JSON Path match query (@?) + /// Count matching documents using a JSON Path match query (@?) /// The table in which documents should be counted (may include schema) /// The JSON Path expression to be matched /// The count of the documents in the table @@ -209,7 +209,7 @@ module Exists = let byId tableName docId = WithProps.Exists.byId tableName docId (fromDataSource ()) - /// Determine if a document exists using JSON field comparisons (->> =, etc.) + /// Determine if a document exists using JSON field comparisons (->> =, etc.) /// The table in which existence should be checked (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -218,7 +218,7 @@ module Exists = let byFields tableName howMatched fields = WithProps.Exists.byFields tableName howMatched fields (fromDataSource ()) - /// Determine if a document exists using a JSON containment query (@>) + /// Determine if a document exists using a JSON containment query (@>) /// The table in which existence should be checked (may include schema) /// The document to match with the containment query /// True if any matching documents exist, false if not @@ -226,7 +226,7 @@ module Exists = let byContains tableName criteria = WithProps.Exists.byContains tableName criteria (fromDataSource ()) - /// Determine if a document exists using a JSON Path match query (@?) + /// Determine if a document exists using a JSON Path match query (@?) /// The table in which existence should be checked (may include schema) /// The JSON Path expression to be matched /// True if any matching documents exist, false if not @@ -270,7 +270,7 @@ module Find = /// Retrieve a document by its ID /// The table from which a document should be retrieved (may include schema) /// The ID of the document to retrieve - /// Some with the document if found, None otherwise + /// Some with the document if found, None otherwise [] let byId<'TKey, 'TDoc> tableName docId = WithProps.Find.byId<'TKey, 'TDoc> tableName docId (fromDataSource ()) @@ -278,11 +278,11 @@ module Find = /// Retrieve a document by its ID /// The table from which a document should be retrieved (may include schema) /// The ID of the document to retrieve - /// The document if found, null otherwise + /// The document if found, null otherwise let ById<'TKey, 'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, docId: 'TKey) = WithProps.Find.ById<'TKey, 'TDoc>(tableName, docId, fromDataSource ()) - /// Retrieve documents matching JSON field comparisons (->> =, etc.) + /// Retrieve documents matching JSON field comparisons (->> =, etc.) /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -291,7 +291,7 @@ module Find = let byFields<'TDoc> tableName howMatched fields = WithProps.Find.byFields<'TDoc> tableName howMatched fields (fromDataSource ()) - /// Retrieve documents matching JSON field comparisons (->> =, etc.) + /// Retrieve documents matching JSON field comparisons (->> =, etc.) /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -300,8 +300,8 @@ module Find = WithProps.Find.ByFields<'TDoc>(tableName, howMatched, fields, fromDataSource ()) /// - /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in - /// the document + /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in the + /// document /// /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions @@ -313,8 +313,8 @@ module Find = WithProps.Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields (fromDataSource ()) /// - /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in - /// the document + /// Retrieve documents matching JSON field comparisons (->> =, etc.) ordered by the given fields in the + /// document /// /// The table from which documents should be retrieved (may include schema) /// Whether to match any or all of the field conditions @@ -324,7 +324,7 @@ module Find = let ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields) = WithProps.Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, fromDataSource ()) - /// Retrieve documents matching a JSON containment query (@>) + /// Retrieve documents matching a JSON containment query (@>) /// The table from which documents should be retrieved (may include schema) /// The document to match with the containment query /// All documents matching the given containment query @@ -332,7 +332,7 @@ module Find = let byContains<'TDoc> tableName (criteria: obj) = WithProps.Find.byContains<'TDoc> tableName criteria (fromDataSource ()) - /// Retrieve documents matching a JSON containment query (@>) + /// Retrieve documents matching a JSON containment query (@>) /// The table from which documents should be retrieved (may include schema) /// The document to match with the containment query /// All documents matching the given containment query @@ -340,8 +340,7 @@ module Find = WithProps.Find.ByContains<'TDoc>(tableName, criteria, fromDataSource ()) /// - /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the - /// document + /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the document /// /// The table from which documents should be retrieved (may include schema) /// The document to match with the containment query @@ -352,8 +351,7 @@ module Find = WithProps.Find.byContainsOrdered<'TDoc> tableName criteria orderFields (fromDataSource ()) /// - /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the - /// document + /// Retrieve documents matching a JSON containment query (@>) ordered by the given fields in the document /// /// The table from which documents should be retrieved (may include schema) /// The document to match with the containment query @@ -362,7 +360,7 @@ module Find = let ByContainsOrdered<'TDoc>(tableName, criteria: obj, orderFields) = WithProps.Find.ByContainsOrdered<'TDoc>(tableName, criteria, orderFields, fromDataSource ()) - /// Retrieve documents matching a JSON Path match query (@?) + /// Retrieve documents matching a JSON Path match query (@?) /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match /// All documents matching the given JSON Path expression @@ -370,7 +368,7 @@ module Find = let byJsonPath<'TDoc> tableName jsonPath = WithProps.Find.byJsonPath<'TDoc> tableName jsonPath (fromDataSource ()) - /// Retrieve documents matching a JSON Path match query (@?) + /// Retrieve documents matching a JSON Path match query (@?) /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match /// All documents matching the given JSON Path expression @@ -378,7 +376,7 @@ module Find = WithProps.Find.ByJsonPath<'TDoc>(tableName, jsonPath, fromDataSource ()) /// - /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document + /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document /// /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match @@ -389,7 +387,7 @@ module Find = WithProps.Find.byJsonPathOrdered<'TDoc> tableName jsonPath orderFields (fromDataSource ()) /// - /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document + /// Retrieve documents matching a JSON Path match query (@?) ordered by the given fields in the document /// /// The table from which documents should be retrieved (may include schema) /// The JSON Path expression to match @@ -398,128 +396,122 @@ module Find = let ByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields) = WithProps.Find.ByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields, fromDataSource ()) - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match - /// Some with the first document, or None if not found + /// Some with the first document, or None if not found [] let firstByFields<'TDoc> tableName howMatched fields = WithProps.Find.firstByFields<'TDoc> tableName howMatched fields (fromDataSource ()) - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match - /// The first document, or null if not found + /// The first document, or null if not found let FirstByFields<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, howMatched, fields) = WithProps.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, fromDataSource ()) /// - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given /// fields in the document /// /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match /// Fields by which the results should be ordered - /// - /// Some with the first document ordered by the given fields, or None if not found - /// + /// Some with the first document ordered by the given fields, or None if not found [] let firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields = WithProps.Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields (fromDataSource ()) /// - /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given + /// Retrieve the first document matching JSON field comparisons (->> =, etc.) ordered by the given /// fields in the document /// /// The table from which a document should be retrieved (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match /// Fields by which the results should be ordered - /// The first document ordered by the given fields, or null if not found + /// The first document ordered by the given fields, or null if not found let FirstByFieldsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>( tableName, howMatched, queryFields, orderFields) = WithProps.Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, fromDataSource ()) - /// Retrieve the first document matching a JSON containment query (@>) + /// Retrieve the first document matching a JSON containment query (@>) /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query - /// Some with the first document, or None if not found + /// Some with the first document, or None if not found [] let firstByContains<'TDoc> tableName (criteria: obj) = WithProps.Find.firstByContains<'TDoc> tableName criteria (fromDataSource ()) - /// Retrieve the first document matching a JSON containment query (@>) + /// Retrieve the first document matching a JSON containment query (@>) /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query - /// The first document, or null if not found + /// The first document, or null if not found let FirstByContains<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, criteria: obj) = WithProps.Find.FirstByContains<'TDoc>(tableName, criteria, fromDataSource ()) /// - /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in - /// the document + /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in the + /// document /// /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query /// Fields by which the results should be ordered - /// - /// Some with the first document ordered by the given fields, or None if not found - /// + /// Some with the first document ordered by the given fields, or None if not found [] let firstByContainsOrdered<'TDoc> tableName (criteria: obj) orderFields = WithProps.Find.firstByContainsOrdered<'TDoc> tableName criteria orderFields (fromDataSource ()) /// - /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in - /// the document + /// Retrieve the first document matching a JSON containment query (@>) ordered by the given fields in the + /// document /// /// The table from which a document should be retrieved (may include schema) /// The document to match with the containment query /// Fields by which the results should be ordered - /// The first document ordered by the given fields, or null if not found + /// The first document ordered by the given fields, or null if not found let FirstByContainsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, criteria: obj, orderFields) = WithProps.Find.FirstByContainsOrdered<'TDoc>(tableName, criteria, orderFields, fromDataSource ()) - /// Retrieve the first document matching a JSON Path match query (@?) + /// Retrieve the first document matching a JSON Path match query (@?) /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match - /// Some with the first document, or None if not found + /// Some with the first document, or None if not found [] let firstByJsonPath<'TDoc> tableName jsonPath = WithProps.Find.firstByJsonPath<'TDoc> tableName jsonPath (fromDataSource ()) - /// Retrieve the first document matching a JSON Path match query (@?) + /// Retrieve the first document matching a JSON Path match query (@?) /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match - /// The first document, or null if not found + /// The first document, or null if not found let FirstByJsonPath<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, jsonPath) = WithProps.Find.FirstByJsonPath<'TDoc>(tableName, jsonPath, fromDataSource ()) /// - /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the + /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the /// document /// /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match /// Fields by which the results should be ordered - /// - /// Some with the first document ordered by the given fields, or None if not found - /// + /// Some with the first document ordered by the given fields, or None if not found [] let firstByJsonPathOrdered<'TDoc> tableName jsonPath orderFields = WithProps.Find.firstByJsonPathOrdered<'TDoc> tableName jsonPath orderFields (fromDataSource ()) /// - /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the + /// Retrieve the first document matching a JSON Path match query (@?) ordered by the given fields in the /// document /// /// The table from which a document should be retrieved (may include schema) /// The JSON Path expression to match /// Fields by which the results should be ordered - /// The first document ordered by the given fields, or null if not found + /// The first document ordered by the given fields, or null if not found let FirstByJsonPathOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, jsonPath, orderFields) = WithProps.Find.FirstByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields, fromDataSource ()) @@ -885,7 +877,7 @@ module Patch = WithProps.Patch.byId tableName docId patch (fromDataSource ()) /// - /// Patch documents using a JSON field comparison query in the WHERE clause (->> =, etc.) + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =, etc.) /// /// The table in which documents should be patched (may include schema) /// Whether to match any or all of the field conditions @@ -895,7 +887,7 @@ module Patch = let byFields tableName howMatched fields (patch: 'TPatch) = WithProps.Patch.byFields tableName howMatched fields patch (fromDataSource ()) - /// Patch documents using a JSON containment query in the WHERE clause (@>) + /// Patch documents using a JSON containment query in the WHERE clause (@>) /// The table in which documents should be patched (may include schema) /// The document to match the containment query /// The partial document to patch the existing document @@ -903,7 +895,7 @@ module Patch = let byContains tableName (criteria: 'TCriteria) (patch: 'TPatch) = WithProps.Patch.byContains tableName criteria patch (fromDataSource ()) - /// Patch documents using a JSON Path match query in the WHERE clause (@?) + /// Patch documents using a JSON Path match query in the WHERE clause (@?) /// The table in which documents should be patched (may include schema) /// The JSON Path expression to match /// The partial document to patch the existing document @@ -933,7 +925,7 @@ module RemoveFields = let byFields tableName howMatched fields fieldNames = WithProps.RemoveFields.byFields tableName howMatched fields fieldNames (fromDataSource ()) - /// Remove fields from documents via a JSON containment query (@>) + /// Remove fields from documents via a JSON containment query (@>) /// The table in which documents should be modified (may include schema) /// The document to match the containment query /// One or more field names to remove from the matching documents @@ -941,7 +933,7 @@ module RemoveFields = 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 (@?) /// The table in which documents should be modified (may include schema) /// The JSON Path expression to match /// One or more field names to remove from the matching documents @@ -961,7 +953,7 @@ module Delete = let byId tableName (docId: 'TKey) = WithProps.Delete.byId tableName docId (fromDataSource ()) - /// Delete documents by matching a JSON field comparison query (->> =, etc.) + /// Delete documents by matching a JSON field comparison query (->> =, etc.) /// The table in which documents should be deleted (may include schema) /// Whether to match any or all of the field conditions /// The field conditions to match @@ -969,7 +961,7 @@ module Delete = let byFields tableName howMatched fields = WithProps.Delete.byFields tableName howMatched fields (fromDataSource ()) - /// Delete documents by matching a JSON contains query (@>) + /// Delete documents by matching a JSON contains query (@>) /// The table in which documents should be deleted (may include schema) /// The document to match the containment query [] diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index 62e38ae..beb9542 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -7,11 +7,11 @@ open System.Text [] type DocumentIndex = - /// A GIN index with standard operations (all operators supported) + /// A GIN index with standard operations (all operators supported) | Full /// - /// A GIN index with JSONPath operations (optimized for @>, @?, @@ operators) + /// A GIN index with JSON Path operations (optimized for @>, @?, @@ operators) /// | Optimized @@ -97,7 +97,7 @@ module Parameters = name, Sql.jsonb (Configuration.serializer().Serialize it) /// Create JSON field parameters - /// The Fields to convert to parameters + /// The Fields to convert to parameters /// The current parameters for the query /// A unified sequence of parameter names and values [] @@ -132,7 +132,7 @@ module Parameters = /// Append JSON field name parameters for the given field names to the given parameters /// The names of fields to be addressed - /// The name (@name) and parameter value for the field names + /// The name (@name) and parameter value for the field names [] let fieldNameParams (fieldNames: string seq) = if Seq.length fieldNames = 1 then "@name", Sql.string (Seq.head fieldNames) @@ -148,12 +148,10 @@ module Parameters = [] module Query = - /// - /// Create a WHERE clause fragment to implement a comparison on fields in a JSON document - /// + /// Create a WHERE clause fragment to implement a comparison on fields in a JSON document /// How the fields should be matched /// The fields for the comparisons - /// A WHERE clause implementing the comparisons for the given fields + /// A WHERE clause implementing the comparisons for the given fields [] let whereByFields (howMatched: FieldMatch) fields = let name = ParameterName() @@ -182,9 +180,9 @@ module Query = else $"{it.Path PostgreSQL AsSql} {it.Comparison.OpSql} {param}") |> String.concat $" {howMatched} " - /// Create a WHERE clause fragment to implement an ID-based query + /// Create a WHERE clause fragment to implement an ID-based query /// The ID of the document - /// A WHERE clause fragment identifying a document by its ID + /// A WHERE clause fragment identifying a document by its ID [] let whereById<'TKey> (docId: 'TKey) = whereByFields Any [ { Field.Equal (Configuration.idField ()) docId with ParameterName = Some "@id" } ] @@ -209,32 +207,28 @@ module Query = let tableName = name.Split '.' |> Array.last $"CREATE INDEX IF NOT EXISTS idx_{tableName}_document ON {name} USING GIN (data{extraOps})" - /// - /// Create a WHERE clause fragment to implement a @> (JSON contains) condition - /// + /// Create a WHERE clause fragment to implement a @> (JSON contains) condition /// The parameter name for the query - /// A WHERE clause fragment for the contains condition + /// A WHERE clause fragment for the contains condition [] let whereDataContains paramName = $"data @> %s{paramName}" - /// - /// Create a WHERE clause fragment to implement a @? (JSON Path match) condition - /// + /// Create a WHERE clause fragment to implement a @? (JSON Path match) condition /// The parameter name for the query - /// A WHERE clause fragment for the JSON Path match condition + /// A WHERE clause fragment for the JSON Path match condition [] let whereJsonPathMatches paramName = $"data @? %s{paramName}::jsonpath" - /// Create an UPDATE statement to patch documents + /// Create an UPDATE statement to patch documents /// The table to be updated /// A query to patch documents [] let patch tableName = $"UPDATE %s{tableName} SET data = data || @data" - /// Create an UPDATE statement to remove fields from documents + /// Create an UPDATE statement to remove fields from documents /// The table to be updated /// A query to remove fields from documents [] @@ -292,14 +286,14 @@ module Results = let fromData<'T> row : 'T = fromDocument "data" row - /// Extract a count from the column it + /// Extract a count from the column it /// A row reader set to the row with the count to retrieve /// The count from the row [] let toCount (row: RowReader) = row.int "it" - /// Extract a true/false value from the column it + /// Extract a true/false value from the column it /// A row reader set to the row with the true/false value to retrieve /// The true/false value from the row [] diff --git a/src/Postgres/WithProps.fs b/src/Postgres/WithProps.fs index f0f7c39..2a06c96 100644 --- a/src/Postgres/WithProps.fs +++ b/src/Postgres/WithProps.fs @@ -1,4 +1,4 @@ -/// Versions of queries that accept SqlProps as the last parameter +/// Versions of queries that accept SqlProps as the last parameter module BitBadger.Documents.Postgres.WithProps open System.IO diff --git a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs index 65b0743..c0398ed 100644 --- a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs +++ b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs @@ -9,11 +9,14 @@ using static CommonExtensionsAndTypesForNpgsqlFSharp; using static Runner; /// -/// C# tests for the extensions on the NpgsqlConnection type +/// C# tests for the extensions on the NpgsqlConnection type /// public class PostgresCSharpExtensionTests { - private static Task LoadDocs() => PostgresCSharpTests.LoadDocs(); + private static async Task LoadDocs(NpgsqlConnection conn) + { + foreach (var doc in JsonDocument.TestDocuments) await conn.Insert(SqliteDb.TableName, doc); + } /// /// Create a connection to the throwaway database @@ -27,6 +30,93 @@ public class PostgresCSharpExtensionTests return conn; } + /// Set up a stream writer for a test + private static StreamWriter WriteStream(Stream stream) + { + StreamWriter writer = new(stream); + writer.AutoFlush = true; + return writer; + } + + /// Get the text of the given stream + private static string StreamText(Stream stream) + { + stream.Position = 0L; + using StreamReader reader = new(stream); + return reader.ReadToEnd(); + } + + /// Verify a JSON array begins with "[" and ends with "]" + private static void VerifyBeginEnd(string json) + { + Expect.stringStarts(json, "[", "The array should have started with `[`"); + Expect.stringEnds(json, "]", "The array should have ended with `]`"); + } + + /// Verify the presence of a document by its ID + private static void VerifyDocById(string json, string docId) + { + Expect.stringContains(json, $"{{\"Id\": \"{docId}\",", $"Document `{docId}` not present"); + } + + /// Verify the presence of a document by its ID + private static void VerifySingleById(string json, string docId) + { + VerifyBeginEnd(json); + Expect.stringContains(json, $"{{\"Id\": \"{docId}\",", $"Document `{docId}` not present"); + } + + /// Verify the presence of any of the given document IDs in the given JSON + private static void VerifyAnyById(string json, IEnumerable docIds) + { + var theIds = docIds.ToList(); + if (theIds.Any(it => json.Contains($"{{\"Id\": \"{it}\""))) return; + var ids = string.Join(", ", theIds); + Expect.isTrue(false, $"Could not find any of IDs {ids} in {json}"); + } + + /// Verify the JSON for `all` returning data + private static void VerifyAllData(string json) + { + VerifyBeginEnd(json); + IEnumerable ids = ["one", "two", "three", "four", "five"]; + foreach (var docId in ids) VerifyDocById(json, docId); + } + + /// Verify an empty JSON array + private static void VerifyEmpty(string json) + { + Expect.equal(json, "[]", "There should be no documents returned"); + } + + /// Verify an empty JSON document + private static void VerifyNoDoc(string json) + { + Expect.equal(json, "{}", "There should be no document returned"); + } + + /// Verify the JSON for an ordered query + private static void VerifyExpectedOrder(string json, string idFirst, string idSecond, string? idThird = null, + string? idFourth = null, string? idFifth = null) + { + var firstIdx = json.IndexOf($"{{\"Id\": \"{idFirst}\",", StringComparison.Ordinal); + var secondIdx = json.IndexOf($"{{\"Id\": \"{idSecond}\",", StringComparison.Ordinal); + VerifyBeginEnd(json); + Expect.isGreaterThan(secondIdx, firstIdx, $"`{idSecond}` should have been after `{idFirst}`"); + if (idThird is null) return; + + var thirdIdx = json.IndexOf($"{{\"Id\": \"{idThird}\",", StringComparison.Ordinal); + Expect.isGreaterThan(thirdIdx, secondIdx, $"`{idThird}` should have been after `{idSecond}`"); + if (idFourth is null) return; + + var fourthIdx = json.IndexOf($"{{\"Id\": \"{idFourth}\",", StringComparison.Ordinal); + Expect.isGreaterThan(fourthIdx, thirdIdx, $"`{idFourth}` should have been after `{idThird}`"); + if (idFifth is null) return; + + var fifthIdx = json.IndexOf($"{{\"Id\": \"{idFifth}\",", StringComparison.Ordinal); + Expect.isGreaterThan(fifthIdx, fourthIdx, $"`{idFifth}` should have been after `{idFourth}`"); + } + /// /// Integration tests for the SQLite extension methods /// @@ -39,7 +129,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.CustomList(Query.Find(PostgresDb.TableName), Parameters.None, Results.FromData); @@ -49,7 +139,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.CustomList( $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", @@ -58,13 +148,72 @@ public class PostgresCSharpExtensionTests Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), + TestList("CustomJsonArray", + [ + TestCase("succeeds when data is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var docs = await conn.CustomJsonArray(Query.Find(PostgresDb.TableName), Parameters.None, + Results.JsonFromData); + Expect.stringStarts(docs, "[", "The JSON array should have started with `[`"); + Expect.hasLength(docs.Split("{\"Id\":"), 6, "There should have been 5 documents returned"); + Expect.stringEnds(docs, "]", "The JSON array should have ended with `[`"); + }), + TestCase("succeeds when data is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var docs = await conn.CustomJsonArray( + $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", + [Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)"))], Results.JsonFromData); + Expect.equal(docs, "[]", "There should have been no documents returned"); + }) + ]), + TestList("WriteJsonArray", + [ + TestCase("succeeds when data is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteCustomJsonArray(Query.Find(PostgresDb.TableName), Parameters.None, writer, + Results.JsonFromData); + + var docs = StreamText(stream); + Expect.stringStarts(docs, "[", "The JSON array should have started with `[`"); + Expect.hasLength(docs.Split("{\"Id\":"), 6, "There should have been 5 documents returned"); + Expect.stringEnds(docs, "]", "The JSON array should have ended with `[`"); + }), + TestCase("succeeds when data is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteCustomJsonArray( + $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", + [Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)"))], writer, Results.JsonFromData); + + Expect.equal(StreamText(stream), "[]", "There should have been no documents returned"); + }) + ]), TestList("CustomSingle", [ TestCase("succeeds when a row is found", async () => { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.CustomSingle($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", [Tuple.Create("@id", Sql.@string("one"))], Results.FromData); @@ -75,23 +224,50 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.CustomSingle($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", [Tuple.Create("@id", Sql.@string("eighty"))], Results.FromData); Expect.isNull(doc, "There should not have been a document returned"); }) ]), + TestList("CustomJsonSingle", + [ + TestCase("succeeds when a row is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var doc = await conn.CustomJsonSingle( + $"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", + [Tuple.Create("@id", Sql.@string("one"))], Results.JsonFromData); + Expect.stringStarts(doc, "{", "The document should have started with an open brace"); + Expect.stringContains(doc, "\"Id\": \"one\"", "An incorrect document was returned"); + Expect.stringEnds(doc, "}", "The document should have ended with a closing brace"); + }), + TestCase("succeeds when a row is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var doc = await conn.CustomJsonSingle( + $"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", + [Tuple.Create("@id", Sql.@string("eighty"))], Results.JsonFromData); + Expect.equal(doc, "{}", "There should not have been a document returned"); + }) + ]), TestList("CustomNonQuery", [ TestCase("succeeds when operating on data", async () => { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.CustomNonQuery($"DELETE FROM {PostgresDb.TableName}", Parameters.None); - + var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 0, "There should be no documents remaining in the table"); }), @@ -99,11 +275,11 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.CustomNonQuery($"DELETE FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", [Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)"))]); - + var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should be 5 documents remaining in the table"); }) @@ -183,7 +359,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should be no documents in the table"); - + await conn.Insert(PostgresDb.TableName, new JsonDocument { Id = "turkey", Sub = new() { Foo = "gobble", Bar = "gobble" } }); var after = await conn.FindAll(PostgresDb.TableName); @@ -213,7 +389,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should be no documents in the table"); - + await conn.Save(PostgresDb.TableName, new JsonDocument { Id = "test", Sub = new() { Foo = "a", Bar = "b" } }); var after = await conn.FindAll(PostgresDb.TableName); @@ -229,7 +405,7 @@ public class PostgresCSharpExtensionTests var before = await conn.FindById(PostgresDb.TableName, "test"); Expect.isNotNull(before, "There should have been a document returned"); Expect.equal(before.Id, "test", "The document is not correct"); - + await conn.Save(PostgresDb.TableName, new JsonDocument { Id = "test", Sub = new() { Foo = "c", Bar = "d" } }); var after = await conn.FindById(PostgresDb.TableName, "test"); @@ -241,8 +417,8 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); - + await LoadDocs(conn); + var theCount = await conn.CountAll(PostgresDb.TableName); Expect.equal(theCount, 5, "There should have been 5 matching documents"); }), @@ -250,7 +426,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var theCount = await conn.CountByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")]); @@ -260,7 +436,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var theCount = await conn.CountByContains(PostgresDb.TableName, new { Value = "purple" }); Expect.equal(theCount, 2, "There should have been 2 matching documents"); @@ -269,7 +445,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var theCount = await conn.CountByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 5)"); Expect.equal(theCount, 3, "There should have been 3 matching documents"); @@ -280,7 +456,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsById(PostgresDb.TableName, "three"); Expect.isTrue(exists, "There should have been an existing document"); @@ -289,7 +465,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsById(PostgresDb.TableName, "seven"); Expect.isFalse(exists, "There should not have been an existing document"); @@ -301,7 +477,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Exists("Sub")]); Expect.isTrue(exists, "There should have been existing documents"); @@ -310,7 +486,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "six")]); @@ -323,7 +499,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsByContains(PostgresDb.TableName, new { NumValue = 10 }); Expect.isTrue(exists, "There should have been existing documents"); @@ -332,7 +508,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsByContains(PostgresDb.TableName, new { Nothing = "none" }); Expect.isFalse(exists, "There should not have been any existing documents"); @@ -344,7 +520,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsByJsonPath(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")"); Expect.isTrue(exists, "There should have been existing documents"); @@ -353,7 +529,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var exists = await conn.ExistsByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 1000)"); Expect.isFalse(exists, "There should not have been any existing documents"); @@ -387,7 +563,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var results = await conn.FindAllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue")]); @@ -399,7 +575,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var results = await conn.FindAllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue DESC")]); @@ -411,7 +587,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var results = await conn.FindAllOrdered(PostgresDb.TableName, [Field.Named("Id DESC")]); Expect.hasLength(results, 5, "There should have been 5 documents returned"); @@ -425,7 +601,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindById(PostgresDb.TableName, "two"); Expect.isNotNull(doc, "There should have been a document returned"); @@ -435,7 +611,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindById(PostgresDb.TableName, "three hundred eighty-seven"); Expect.isNull(doc, "There should not have been a document returned"); @@ -447,7 +623,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "another")]); @@ -457,7 +633,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "mauve")]); @@ -470,7 +646,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], [Field.Named("Id")]); @@ -482,7 +658,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); @@ -497,7 +673,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }); @@ -507,7 +683,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByContains(PostgresDb.TableName, new { Value = "mauve" }); Expect.isEmpty(docs, "There should have been no documents returned"); @@ -520,7 +696,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Sub.Bar")]); @@ -532,7 +708,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Sub.Bar DESC")]); @@ -547,7 +723,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 15)"); Expect.equal(docs.Count, 3, "There should have been 3 documents returned"); @@ -556,7 +732,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)"); Expect.isEmpty(docs, "There should have been no documents returned"); @@ -569,7 +745,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", [Field.Named("n:NumValue")]); @@ -581,7 +757,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var docs = await conn.FindByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", [Field.Named("n:NumValue DESC")]); @@ -596,7 +772,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "another")]); @@ -607,7 +783,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")]); @@ -618,7 +794,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "absent")]); @@ -631,7 +807,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], [Field.Named("Id")]); @@ -642,7 +818,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); @@ -656,7 +832,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByContains(PostgresDb.TableName, new { Value = "another" }); Expect.isNotNull(doc, "There should have been a document returned"); @@ -666,7 +842,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }); @@ -677,7 +853,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByContains(PostgresDb.TableName, new { Value = "absent" }); Expect.isNull(doc, "There should not have been a document returned"); @@ -689,7 +865,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Value")]); @@ -700,7 +876,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Value DESC")]); @@ -714,7 +890,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByJsonPath(PostgresDb.TableName, "$.Value ? (@ == \"FIRST!\")"); @@ -725,7 +901,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByJsonPath(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")"); @@ -736,7 +912,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByJsonPath(PostgresDb.TableName, "$.Id ? (@ == \"nope\")"); Expect.isNull(doc, "There should not have been a document returned"); @@ -748,7 +924,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByJsonPathOrdered(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")", [Field.Named("Sub.Bar")]); @@ -759,7 +935,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); var doc = await conn.FindFirstByJsonPathOrdered(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")", [Field.Named("Sub.Bar DESC")]); @@ -767,13 +943,848 @@ public class PostgresCSharpExtensionTests Expect.equal("four", doc.Id, "An incorrect document was returned"); }) ]), + TestList("JsonAll", + [ + TestCase("succeeds when there is data", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyAllData(await conn.JsonAll(PostgresDb.TableName)); + }), + TestCase("succeeds when there is no data", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + VerifyEmpty(await conn.JsonAll(PostgresDb.TableName)); + }) + ]), + TestList("JsonAllOrdered", + [ + TestCase("succeeds when ordering numerically", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder(await conn.JsonAllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue")]), + "one", "three", "two", "four", "five"); + }), + TestCase("succeeds when ordering numerically descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder(await conn.JsonAllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue DESC")]), + "five", "four", "two", "three", "one"); + }), + TestCase("succeeds when ordering alphabetically", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder(await conn.JsonAllOrdered(PostgresDb.TableName, [Field.Named("Id DESC")]), + "two", "three", "one", "four", "five"); + }) + ]), + TestList("JsonById", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var json = await conn.JsonById(PostgresDb.TableName, "two"); + Expect.stringStarts(json, """{"Id": "two",""", "An incorrect document was returned"); + Expect.stringEnds(json, "}", "JSON should have ended with this document"); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyNoDoc(await conn.JsonById(PostgresDb.TableName, "three hundred eighty-seven")); + }) + ]), + TestList("JsonByFields", + [ + TestCase("succeeds when documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifySingleById( + await conn.JsonByFields(PostgresDb.TableName, FieldMatch.All, + [Field.In("Value", ["purple", "blue"]), Field.Exists("Sub")]), + "four"); + }), + TestCase("succeeds when documents are found using IN with numeric field", async() => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifySingleById( + await conn.JsonByFields(PostgresDb.TableName, FieldMatch.All, [Field.In("NumValue", [2, 4, 6, 8])]), + "three"); + }), + TestCase("succeeds when documents are not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyEmpty(await conn.JsonByFields(PostgresDb.TableName, FieldMatch.All, + [Field.Equal("Value", "mauve"), Field.NotEqual("NumValue", 40)])); + }), + TestCase("succeeds for InArray when matching documents exist", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await conn.EnsureTable(PostgresDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await conn.Insert(PostgresDb.TableName, doc); + + var json = await conn.JsonByFields(PostgresDb.TableName, FieldMatch.All, + [Field.InArray("Values", PostgresDb.TableName, ["c"])]); + VerifyBeginEnd(json); + VerifyDocById(json, "first"); + VerifyDocById(json, "second"); + }), + TestCase("succeeds for InArray when no matching documents exist", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await conn.EnsureTable(PostgresDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await conn.Insert(PostgresDb.TableName, doc); + VerifyEmpty(await conn.JsonByFields(PostgresDb.TableName, FieldMatch.All, + [Field.InArray("Values", PostgresDb.TableName, ["j"])])); + }) + ]), + TestList("JsonByFieldsOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder( + await conn.JsonByFieldsOrdered(PostgresDb.TableName, FieldMatch.All, + [Field.Equal("Value", "purple")], [Field.Named("Id")]), + "five", "four"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder( + await conn.JsonByFieldsOrdered(PostgresDb.TableName, FieldMatch.All, + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]), + "four", "five"); + }) + ]), + TestList("JsonByContains", + [ + TestCase("succeeds when documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var json = await conn.JsonByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }); + VerifyBeginEnd(json); + VerifyDocById(json, "two"); + VerifyDocById(json, "four"); + }), + TestCase("succeeds when documents are not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyEmpty(await conn.JsonByContains(PostgresDb.TableName, new { Value = "mauve" })); + }) + ]), + TestList("JsonByContainsOrdered", + [ + // Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder( + await conn.JsonByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + [Field.Named("Sub.Bar")]), + "two", "four"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder( + await conn.JsonByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + [Field.Named("Sub.Bar DESC")]), + "four", "two"); + }) + ]), + TestList("JsonByJsonPath", + [ + TestCase("succeeds when documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + var json = await conn.JsonByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 15)"); + VerifyBeginEnd(json); + VerifyDocById(json, "one"); + VerifyDocById(json, "two"); + VerifyDocById(json, "three"); + }), + TestCase("succeeds when documents are not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyEmpty(await conn.JsonByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)")); + }) + ]), + TestList("JsonByJsonPathOrdered", + [ + // Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4 + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder( + await conn.JsonByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", + [Field.Named("n:NumValue")]), + "one", "three", "two"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyExpectedOrder( + await conn.JsonByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", + [Field.Named("n:NumValue DESC")]), + "two", "three", "one"); + }) + ]), + TestList("JsonFirstByFields", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByFields(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "another")]), + "two"); + }), + TestCase("succeeds when multiple documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyAnyById( + await conn.JsonFirstByFields(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "purple")]), + ["five", "four"]); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyNoDoc(await conn.JsonFirstByFields(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "absent")])); + }) + ]), + TestList("JsonFirstByFieldsOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "purple")], [Field.Named("Id")]), + "five"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]), + "four"); + }) + ]), + TestList("JsonFirstByContains", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById(await conn.JsonFirstByContains(PostgresDb.TableName, new { Value = "another" }), "two"); + }), + TestCase("succeeds when multiple documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyAnyById(await conn.JsonFirstByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }), + ["two", "four"]); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyNoDoc(await conn.JsonFirstByContains(PostgresDb.TableName, new { Value = "absent" })); + }) + ]), + TestList("JsonFirstByContainsOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + [Field.Named("Value")]), + "two"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + [Field.Named("Value DESC")]), + "four"); + }) + ]), + TestList("JsonFirstByJsonPath", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById(await conn.JsonFirstByJsonPath(PostgresDb.TableName, """$.Value ? (@ == "FIRST!")"""), + "one"); + }), + TestCase("succeeds when multiple documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyAnyById(await conn.JsonFirstByJsonPath(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")"""), + ["two", "four"]); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyNoDoc(await conn.JsonFirstByJsonPath(PostgresDb.TableName, """$.Id ? (@ == "nope")""")); + }) + ]), + TestList("JsonFirstByJsonPathOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByJsonPathOrdered(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")""", + [Field.Named("Sub.Bar")]), + "two"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + VerifyDocById( + await conn.JsonFirstByJsonPathOrdered(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")""", + [Field.Named("Sub.Bar DESC")]), + "four"); + }) + ]), + TestList("WriteJsonAll", + [ + TestCase("succeeds when there is data", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonAll(PostgresDb.TableName, writer); + VerifyAllData(StreamText(stream)); + }), + TestCase("succeeds when there is no data", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonAll(PostgresDb.TableName, writer); + VerifyEmpty(StreamText(stream)); + }) + ]), + TestList("WriteJsonAllOrdered", + [ + TestCase("succeeds when ordering numerically", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonAllOrdered(PostgresDb.TableName, writer, [Field.Named("n:NumValue")]); + VerifyExpectedOrder(StreamText(stream), "one", "three", "two", "four", "five"); + }), + TestCase("succeeds when ordering numerically descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonAllOrdered(PostgresDb.TableName, writer, [Field.Named("n:NumValue DESC")]); + VerifyExpectedOrder(StreamText(stream), "five", "four", "two", "three", "one"); + }), + TestCase("succeeds when ordering alphabetically", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonAllOrdered(PostgresDb.TableName, writer, [Field.Named("Id DESC")]); + VerifyExpectedOrder(StreamText(stream), "two", "three", "one", "four", "five"); + }) + ]), + TestList("WriteJsonById", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonById(PostgresDb.TableName, writer, "two"); + var json = StreamText(stream); + Expect.stringStarts(json, """{"Id": "two",""", "An incorrect document was returned"); + Expect.stringEnds(json, "}", "JSON should have ended with this document"); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonById(PostgresDb.TableName, writer, "three hundred eighty-seven"); + VerifyNoDoc(StreamText(stream)); + }) + ]), + TestList("WriteJsonByFields", + [ + TestCase("succeeds when documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFields(PostgresDb.TableName, writer, FieldMatch.All, + [Field.In("Value", ["purple", "blue"]), Field.Exists("Sub")]); + VerifySingleById(StreamText(stream), "four"); + }), + TestCase("succeeds when documents are found using IN with numeric field", async() => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFields(PostgresDb.TableName, writer, FieldMatch.All, + [Field.In("NumValue", [2, 4, 6, 8])]); + VerifySingleById(StreamText(stream), "three"); + }), + TestCase("succeeds when documents are not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFields(PostgresDb.TableName, writer, FieldMatch.All, + [Field.Equal("Value", "mauve"), Field.NotEqual("NumValue", 40)]); + VerifyEmpty(StreamText(stream)); + }), + TestCase("succeeds for InArray when matching documents exist", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await conn.EnsureTable(PostgresDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await conn.Insert(PostgresDb.TableName, doc); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFields(PostgresDb.TableName, writer, FieldMatch.All, + [Field.InArray("Values", PostgresDb.TableName, ["c"])]); + var json = StreamText(stream); + VerifyBeginEnd(json); + VerifyDocById(json, "first"); + VerifyDocById(json, "second"); + }), + TestCase("succeeds for InArray when no matching documents exist", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await conn.EnsureTable(PostgresDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await conn.Insert(PostgresDb.TableName, doc); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFields(PostgresDb.TableName, writer, FieldMatch.All, + [Field.InArray("Values", PostgresDb.TableName, ["j"])]); + VerifyEmpty(StreamText(stream)); + }) + ]), + TestList("WriteJsonByFieldsOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFieldsOrdered(PostgresDb.TableName, writer, FieldMatch.All, + [Field.Equal("Value", "purple")], [Field.Named("Id")]); + VerifyExpectedOrder(StreamText(stream), "five", "four"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByFieldsOrdered(PostgresDb.TableName, writer, FieldMatch.All, + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); + VerifyExpectedOrder(StreamText(stream), "four", "five"); + }) + ]), + TestList("WriteJsonByContains", + [ + TestCase("succeeds when documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByContains(PostgresDb.TableName, writer, new { Sub = new { Foo = "green" } }); + var json = StreamText(stream); + VerifyBeginEnd(json); + VerifyDocById(json, "two"); + VerifyDocById(json, "four"); + }), + TestCase("succeeds when documents are not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByContains(PostgresDb.TableName, writer, new { Value = "mauve" }); + VerifyEmpty(StreamText(stream)); + }) + ]), + TestList("WriteJsonByContainsOrdered", + [ + // Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByContainsOrdered(PostgresDb.TableName, writer, new { Sub = new { Foo = "green" } }, + [Field.Named("Sub.Bar")]); + VerifyExpectedOrder(StreamText(stream), "two", "four"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByContainsOrdered(PostgresDb.TableName, writer, new { Sub = new { Foo = "green" } }, + [Field.Named("Sub.Bar DESC")]); + VerifyExpectedOrder(StreamText(stream), "four", "two"); + }) + ]), + TestList("WriteJsonByJsonPath", + [ + TestCase("succeeds when documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByJsonPath(PostgresDb.TableName, writer, "$.NumValue ? (@ < 15)"); + var json = StreamText(stream); + VerifyBeginEnd(json); + VerifyDocById(json, "one"); + VerifyDocById(json, "two"); + VerifyDocById(json, "three"); + }), + TestCase("succeeds when documents are not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByJsonPath(PostgresDb.TableName, writer, "$.NumValue ? (@ < 0)"); + VerifyEmpty(StreamText(stream)); + }) + ]), + TestList("WriteJsonByJsonPathOrdered", + [ + // Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4 + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByJsonPathOrdered(PostgresDb.TableName, writer, "$.NumValue ? (@ < 15)", + [Field.Named("n:NumValue")]); + VerifyExpectedOrder(StreamText(stream), "one", "three", "two"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonByJsonPathOrdered(PostgresDb.TableName, writer, "$.NumValue ? (@ < 15)", + [Field.Named("n:NumValue DESC")]); + VerifyExpectedOrder(StreamText(stream), "two", "three", "one"); + }) + ]), + TestList("WriteJsonFirstByFields", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByFields(PostgresDb.TableName, writer, FieldMatch.Any, + [Field.Equal("Value", "another")]); + VerifyDocById(StreamText(stream), "two"); + }), + TestCase("succeeds when multiple documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByFields(PostgresDb.TableName, writer, FieldMatch.Any, + [Field.Equal("Value", "purple")]); + VerifyAnyById(StreamText(stream), ["five", "four"]); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByFields(PostgresDb.TableName, writer, FieldMatch.Any, + [Field.Equal("Value", "absent")]); + VerifyNoDoc(StreamText(stream)); + }) + ]), + TestList("WriteJsonFirstByFieldsOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByFieldsOrdered(PostgresDb.TableName, writer, FieldMatch.Any, + [Field.Equal("Value", "purple")], [Field.Named("Id")]); + VerifyDocById(StreamText(stream), "five"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByFieldsOrdered(PostgresDb.TableName, writer, FieldMatch.Any, + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); + VerifyDocById(StreamText(stream), "four"); + }) + ]), + TestList("WriteJsonFirstByContains", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByContains(PostgresDb.TableName, writer, new { Value = "another" }); + VerifyDocById(StreamText(stream), "two"); + }), + TestCase("succeeds when multiple documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByContains(PostgresDb.TableName, writer, new { Sub = new { Foo = "green" } }); + VerifyAnyById(StreamText(stream), ["two", "four"]); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByContains(PostgresDb.TableName, writer, new { Value = "absent" }); + VerifyNoDoc(StreamText(stream)); + }) + ]), + TestList("WriteJsonFirstByContainsOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByContainsOrdered(PostgresDb.TableName, writer, + new { Sub = new { Foo = "green" } }, [Field.Named("Value")]); + VerifyDocById(StreamText(stream), "two"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByContainsOrdered(PostgresDb.TableName, writer, + new { Sub = new { Foo = "green" } }, [Field.Named("Value DESC")]); + VerifyDocById(StreamText(stream), "four"); + }) + ]), + TestList("WriteJsonFirstByJsonPath", + [ + TestCase("succeeds when a document is found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByJsonPath(PostgresDb.TableName, writer, """$.Value ? (@ == "FIRST!")"""); + VerifyDocById(StreamText(stream), "one"); + }), + TestCase("succeeds when multiple documents are found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByJsonPath(PostgresDb.TableName, writer, """$.Sub.Foo ? (@ == "green")"""); + VerifyAnyById(StreamText(stream), ["two", "four"]); + }), + TestCase("succeeds when a document is not found", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByJsonPath(PostgresDb.TableName, writer, """$.Id ? (@ == "nope")"""); + VerifyNoDoc(StreamText(stream)); + }) + ]), + TestList("WriteJsonFirstByJsonPathOrdered", + [ + TestCase("succeeds when sorting ascending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByJsonPathOrdered(PostgresDb.TableName, writer, + """$.Sub.Foo ? (@ == "green")""", [Field.Named("Sub.Bar")]); + VerifyDocById(StreamText(stream), "two"); + }), + TestCase("succeeds when sorting descending", async () => + { + await using var db = PostgresDb.BuildDb(); + await using var conn = MkConn(db); + await LoadDocs(conn); + await using MemoryStream stream = new(); + await using var writer = WriteStream(stream); + await conn.WriteJsonFirstByJsonPathOrdered(PostgresDb.TableName, writer, + """$.Sub.Foo ? (@ == "green")""", [Field.Named("Sub.Bar DESC")]); + VerifyDocById(StreamText(stream), "four"); + }) + ]), TestList("UpdateById", [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.UpdateById(PostgresDb.TableName, "one", new JsonDocument { Id = "one", Sub = new() { Foo = "blue", Bar = "red" } }); @@ -792,7 +1803,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should have been no documents returned"); - + // This not raising an exception is the test await conn.UpdateById(PostgresDb.TableName, "test", new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } }); @@ -804,7 +1815,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.UpdateByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); @@ -821,7 +1832,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should have been no documents returned"); - + // This not raising an exception is the test await conn.UpdateByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); @@ -833,7 +1844,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.PatchById(PostgresDb.TableName, "one", new { NumValue = 44 }); var after = await conn.FindById(PostgresDb.TableName, "one"); @@ -846,7 +1857,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should have been no documents returned"); - + // This not raising an exception is the test await conn.PatchById(PostgresDb.TableName, "test", new { Foo = "green" }); }) @@ -857,7 +1868,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.PatchByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], new { NumValue = 77 }); @@ -871,7 +1882,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should have been no documents returned"); - + // This not raising an exception is the test await conn.PatchByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "burgundy")], new { Foo = "green" }); @@ -883,7 +1894,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.PatchByContains(PostgresDb.TableName, new { Value = "purple" }, new { NumValue = 77 }); var after = await conn.CountByContains(PostgresDb.TableName, new { NumValue = 77 }); @@ -895,7 +1906,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should have been no documents returned"); - + // This not raising an exception is the test await conn.PatchByContains(PostgresDb.TableName, new { Value = "burgundy" }, new { Foo = "green" }); }) @@ -906,7 +1917,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.PatchByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 10)", new { NumValue = 1000 }); var after = await conn.CountByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 999)"); @@ -918,7 +1929,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); var before = await conn.CountAll(PostgresDb.TableName); Expect.equal(before, 0, "There should have been no documents returned"); - + // This not raising an exception is the test await conn.PatchByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" }); }) @@ -929,7 +1940,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsById(PostgresDb.TableName, "two", ["Sub", "Value"]); var updated = await Find.ById(PostgresDb.TableName, "two"); @@ -941,7 +1952,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsById(PostgresDb.TableName, "two", ["Sub"]); var updated = await Find.ById(PostgresDb.TableName, "two"); @@ -953,8 +1964,8 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); - + await LoadDocs(conn); + // This not raising an exception is the test await conn.RemoveFieldsById(PostgresDb.TableName, "two", ["AFieldThatIsNotThere"]); }), @@ -962,7 +1973,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - + // This not raising an exception is the test await conn.RemoveFieldsById(PostgresDb.TableName, "two", ["Value"]); }) @@ -973,7 +1984,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Sub", "Value"]); @@ -986,7 +1997,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Sub"]); @@ -999,8 +2010,8 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); - + await LoadDocs(conn); + // This not raising an exception is the test await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Nothing"]); @@ -1009,7 +2020,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - + // This not raising an exception is the test await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NotEqual("Abracadabra", "apple")], ["Value"]); @@ -1021,7 +2032,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsByContains(PostgresDb.TableName, new { NumValue = 17 }, ["Sub", "Value"]); var updated = await Find.ById(PostgresDb.TableName, "four"); @@ -1033,7 +2044,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsByContains(PostgresDb.TableName, new { NumValue = 17 }, ["Sub"]); var updated = await Find.ById(PostgresDb.TableName, "four"); @@ -1045,8 +2056,8 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); - + await LoadDocs(conn); + // This not raising an exception is the test await conn.RemoveFieldsByContains(PostgresDb.TableName, new { NumValue = 17 }, ["Nothing"]); }), @@ -1054,7 +2065,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - + // This not raising an exception is the test await conn.RemoveFieldsByContains(PostgresDb.TableName, new { Abracadabra = "apple" }, ["Value"]); }) @@ -1065,7 +2076,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ == 17)", ["Sub", "Value"]); var updated = await Find.ById(PostgresDb.TableName, "four"); @@ -1077,7 +2088,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.RemoveFieldsByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ == 17)", ["Sub"]); var updated = await Find.ById(PostgresDb.TableName, "four"); @@ -1089,8 +2100,8 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); - + await LoadDocs(conn); + // This not raising an exception is the test await conn.RemoveFieldsByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ == 17)", ["Nothing"]); }), @@ -1098,7 +2109,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - + // This not raising an exception is the test await conn.RemoveFieldsByJsonPath(PostgresDb.TableName, "$.Abracadabra ? (@ == \"apple\")", ["Value"]); }) @@ -1109,7 +2120,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteById(PostgresDb.TableName, "four"); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1119,7 +2130,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteById(PostgresDb.TableName, "thirty"); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1132,7 +2143,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NotEqual("Value", "purple")]); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1142,7 +2153,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "crimson")]); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1155,7 +2166,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteByContains(PostgresDb.TableName, new { Value = "purple" }); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1165,7 +2176,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteByContains(PostgresDb.TableName, new { Value = "crimson" }); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1178,7 +2189,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteByJsonPath(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")"); var remaining = await conn.CountAll(PostgresDb.TableName); @@ -1188,7 +2199,7 @@ public class PostgresCSharpExtensionTests { await using var db = PostgresDb.BuildDb(); await using var conn = MkConn(db); - await LoadDocs(); + await LoadDocs(conn); await conn.DeleteByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 100)"); var remaining = await conn.CountAll(PostgresDb.TableName); diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index efc7b90..df8ab6d 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -9,7 +9,7 @@ using static CommonExtensionsAndTypesForNpgsqlFSharp; using static Runner; /// -/// C# tests for the PostgreSQL implementation of BitBadger.Documents +/// C# tests for the PostgreSQL implementation of BitBadger.Documents /// public static class PostgresCSharpTests { @@ -323,21 +323,21 @@ public static class PostgresCSharpTests /// /// Add the test documents to the database /// - internal static async Task LoadDocs() + private static async Task LoadDocs() { foreach (var doc in JsonDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc); } /// Set up a stream writer for a test - internal static StreamWriter WriteStream(Stream stream) + private static StreamWriter WriteStream(Stream stream) { StreamWriter writer = new(stream); writer.AutoFlush = true; return writer; } - /// Get the text of the given stream - internal static string StreamText(Stream stream) + /// Get the text of the given stream + private static string StreamText(Stream stream) { stream.Position = 0L; using StreamReader reader = new(stream); @@ -1298,20 +1298,20 @@ public static class PostgresCSharpTests Expect.stringEnds(json, "]", "The array should have ended with `]`"); } - /// Verify the presence of a document by its ID + /// Verify the presence of a document by its ID private static void VerifyDocById(string json, string docId) { Expect.stringContains(json, $"{{\"Id\": \"{docId}\",", $"Document `{docId}` not present"); } - /// Verify the presence of a document by its ID + /// Verify the presence of a document by its ID private static void VerifySingleById(string json, string docId) { VerifyBeginEnd(json); Expect.stringContains(json, $"{{\"Id\": \"{docId}\",", $"Document `{docId}` not present"); } - /// Verify the presence of any of the given document IDs in the given JSON + /// Verify the presence of any of the given document IDs in the given JSON private static void VerifyAnyById(string json, IEnumerable docIds) { var theIds = docIds.ToList(); @@ -1320,7 +1320,7 @@ public static class PostgresCSharpTests Expect.isTrue(false, $"Could not find any of IDs {ids} in {json}"); } - /// Verify the JSON for `all` returning data + /// Verify the JSON for `all` returning data private static void VerifyAllData(string json) { VerifyBeginEnd(json); @@ -1328,19 +1328,19 @@ public static class PostgresCSharpTests foreach (var docId in ids) VerifyDocById(json, docId); } - /// Verify an empty JSON array + /// Verify an empty JSON array private static void VerifyEmpty(string json) { Expect.equal(json, "[]", "There should be no documents returned"); } - /// Verify an empty JSON document + /// Verify an empty JSON document private static void VerifyNoDoc(string json) { Expect.equal(json, "{}", "There should be no document returned"); } - /// Verify the JSON for an ordered query + /// Verify the JSON for an ordered query private static void VerifyExpectedOrder(string json, string idFirst, string idSecond, string? idThird = null, string? idFourth = null, string? idFifth = null) { diff --git a/src/Tests/PostgresExtensionTests.fs b/src/Tests/PostgresExtensionTests.fs index 60fcf31..df675c1 100644 --- a/src/Tests/PostgresExtensionTests.fs +++ b/src/Tests/PostgresExtensionTests.fs @@ -1,5 +1,6 @@ module PostgresExtensionTests +open System.IO open BitBadger.Documents open BitBadger.Documents.Postgres open BitBadger.Documents.Tests @@ -13,6 +14,75 @@ let private mkConn (db: ThrowawayPostgresDb) = conn.Open() conn +/// Set up a stream writer for a test +let private writeStream (stream: Stream) = + let writer = new StreamWriter(stream) + writer.AutoFlush <- true + writer + +/// Get the text of the given stream +let private streamText (stream: Stream) = + stream.Position <- 0L + use reader = new StreamReader(stream) + reader.ReadToEnd() + +/// Verify a JSON array begins with "[" and ends with "]" +let private verifyBeginEnd json = + Expect.stringStarts json "[" "The array should have started with `[`" + Expect.stringEnds json "]" "The array should have ended with `]`" + +/// Verify the presence of a document by its ID +let private verifyDocById json docId = + Expect.stringContains json $"{{\"Id\": \"%s{docId}\"," $"Document `{docId}` not present" + +/// Verify the presence of a document by its ID +let private verifySingleById json docId = + verifyBeginEnd json + Expect.stringContains json $"{{\"Id\": \"%s{docId}\"," $"Document `{docId}` not present" + +/// Verify the presence of any of the given document IDs in the given JSON +let private verifyAnyById (json: string) (docIds: string list) = + match docIds |> List.tryFind (fun it -> json.Contains $"{{\"Id\": \"{it}\"") with + | Some _ -> () + | None -> + let ids = docIds |> String.concat ", " + Expect.isTrue false $"Could not find any of IDs {ids} in {json}" + +/// Verify the JSON for `all` returning data +let private verifyAllData json = + verifyBeginEnd json + [ "one"; "two"; "three"; "four"; "five" ] |> List.iter (verifyDocById json) + +/// Verify an empty JSON array +let private verifyEmpty json = + Expect.equal json "[]" "There should be no documents returned" + +/// Verify an empty JSON document +let private verifyNoDoc json = + Expect.equal json "{}" "There should be no document returned" + +/// Verify the JSON for an ordered query +let private verifyExpectedOrder (json: string) idFirst idSecond idThird idFourth idFifth = + let firstIdx = json.IndexOf $"{{\"Id\": \"%s{idFirst}\"," + let secondIdx = json.IndexOf $"{{\"Id\": \"%s{idSecond}\"," + verifyBeginEnd json + Expect.isGreaterThan secondIdx firstIdx $"`{idSecond}` should have been after `{idFirst}`" + match idThird with + | Some id3 -> + let thirdIdx = json.IndexOf $"{{\"Id\": \"%s{id3}\"," + Expect.isGreaterThan thirdIdx secondIdx $"`{id3}` should have been after `{idSecond}`" + match idFourth with + | Some id4 -> + let fourthIdx = json.IndexOf $"{{\"Id\": \"%s{id4}\"," + Expect.isGreaterThan fourthIdx thirdIdx $"`{id4}` should have been after `{id3}`" + match idFifth with + | Some id5 -> + let fifthIdx = json.IndexOf $"{{\"Id\": \"%s{id5}\"," + Expect.isGreaterThan fifthIdx fourthIdx $"`{id5}` should have been after `{id4}`" + | None -> () + | None -> () + | None -> () + /// Integration tests for the F# extensions on the NpgsqlConnection data type let integrationTests = let loadDocs (conn: NpgsqlConnection) = backgroundTask { @@ -41,6 +111,61 @@ let integrationTests = Expect.isEmpty docs "There should have been no documents returned" } ] + testList "customJsonArray" [ + testTask "succeeds when data is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! docs = conn.customJsonArray (Query.find PostgresDb.TableName) [] jsonFromData + Expect.stringStarts docs "[" "The JSON array should have started with `[`" + Expect.hasLength ((string docs).Split "{\"Id\":") 6 "There should have been 5 documents returned" + Expect.stringEnds docs "]" "The JSON array should have ended with `[`" + } + testTask "succeeds when data is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! docs = + conn.customJsonArray + $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath" + [ "@path", Sql.string "$.NumValue ? (@ > 100)" ] + jsonFromData + Expect.equal docs "[]" "There should have been no documents returned" + } + ] + testList "writeCustomJsonArray" [ + testTask "succeeds when data is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeCustomJsonArray (Query.find PostgresDb.TableName) [] writer jsonFromData + + let docs = streamText stream + Expect.stringStarts docs "[" "The JSON array should have started with `[`" + Expect.hasLength (docs.Split "{\"Id\":") 6 "There should have been 5 documents returned" + Expect.stringEnds docs "]" "The JSON array should have ended with `[`" + } + testTask "succeeds when data is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeCustomJsonArray + $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath" + [ "@path", Sql.string "$.NumValue ? (@ > 100)" ] + writer + jsonFromData + + Expect.equal (streamText stream) "[]" "There should have been no documents returned" + } + ] testList "customSingle" [ testTask "succeeds when a row is found" { use db = PostgresDb.BuildDb() @@ -68,6 +193,34 @@ let integrationTests = Expect.isNone doc "There should not have been a document returned" } ] + testList "customJsonSingle" [ + testTask "succeeds when a row is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! doc = + conn.customJsonSingle + $"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id" + [ "@id", Sql.string "one"] + jsonFromData + Expect.stringStarts doc "{" "The document should have started with an open brace" + Expect.stringContains doc "\"Id\": \"one\"" "An incorrect document was returned" + Expect.stringEnds doc "}" "The document should have ended with a closing brace" + } + testTask "succeeds when a row is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! doc = + conn.customJsonSingle + $"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id" + [ "@id", Sql.string "eighty" ] + jsonFromData + Expect.equal doc "{}" "There should not have been a document returned" + } + ] testList "customNonQuery" [ testTask "succeeds when operating on data" { use db = PostgresDb.BuildDb() @@ -106,7 +259,7 @@ let integrationTests = let keyExists () = conn.customScalar "SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_key') AS it" [] toExists - + let! exists = tableExists () let! alsoExists = keyExists () Expect.isFalse exists "The table should not exist already" @@ -124,7 +277,7 @@ let integrationTests = let indexExists () = conn.customScalar "SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_document') AS it" [] toExists - + let! exists = indexExists () Expect.isFalse exists "The index should not exist already" @@ -139,7 +292,7 @@ let integrationTests = let indexExists () = conn.customScalar "SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_test') AS it" [] toExists - + let! exists = indexExists () Expect.isFalse exists "The index should not exist already" @@ -213,7 +366,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + let! theCount = conn.countByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] Expect.equal theCount 2 "There should have been 2 matching documents" } @@ -332,7 +485,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + let! results = conn.findAllOrdered PostgresDb.TableName [ Field.Named "n:NumValue" ] Expect.hasLength results 5 "There should have been 5 documents returned" Expect.equal @@ -344,7 +497,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + let! results = conn.findAllOrdered PostgresDb.TableName [ Field.Named "n:NumValue DESC" ] Expect.hasLength results 5 "There should have been 5 documents returned" Expect.equal @@ -356,7 +509,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + let! results = conn.findAllOrdered PostgresDb.TableName [ Field.Named "Id DESC" ] Expect.hasLength results 5 "There should have been 5 documents returned" Expect.equal @@ -677,6 +830,769 @@ let integrationTests = Expect.equal "four" doc.Value.Id "An incorrect document was returned" } ] + testList "jsonAll" [ + testTask "succeeds when there is data" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonAll PostgresDb.TableName + verifyAllData json + } + testTask "succeeds when there is no data" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + let! json = conn.jsonAll PostgresDb.TableName + verifyEmpty json + } + ] + testList "jsonAllOrdered" [ + testTask "succeeds when ordering numerically" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonAllOrdered PostgresDb.TableName [ Field.Named "n:NumValue" ] + verifyExpectedOrder json "one" "three" (Some "two") (Some "four") (Some "five") + } + testTask "succeeds when ordering numerically descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonAllOrdered PostgresDb.TableName [ Field.Named "n:NumValue DESC" ] + verifyExpectedOrder json "five" "four" (Some "two") (Some "three") (Some "one") + } + testTask "succeeds when ordering alphabetically" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonAllOrdered PostgresDb.TableName [ Field.Named "Id DESC" ] + verifyExpectedOrder json "two" "three" (Some "one") (Some "four") (Some "five") + } + ] + testList "jsonById" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! json = conn.jsonById PostgresDb.TableName "two" + Expect.stringStarts json """{"Id": "two",""" "An incorrect document was returned" + Expect.stringEnds json "}" "JSON should have ended with this document" + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonById PostgresDb.TableName "three hundred eighty-seven" + verifyNoDoc json + } + ] + testList "jsonByFields" [ + testTask "succeeds when documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByFields + PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ] + verifySingleById json "four" + } + testTask "succeeds when documents are found using IN with numeric field" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonByFields PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ] + verifySingleById json "three" + } + testTask "succeeds when documents are not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByFields + PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ] + verifyEmpty json + } + testTask "succeeds for InArray when matching documents exist" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! conn.ensureTable PostgresDb.TableName + for doc in ArrayDocument.TestDocuments do do! conn.insert PostgresDb.TableName doc + + let! json = + conn.jsonByFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ] + verifyBeginEnd json + verifyDocById json "first" + verifyDocById json "second" + } + testTask "succeeds for InArray when no matching documents exist" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! conn.ensureTable PostgresDb.TableName + for doc in ArrayDocument.TestDocuments do do! conn.insert PostgresDb.TableName doc + let! json = + conn.jsonByFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ] + verifyEmpty json + } + ] + testList "jsoByFieldsOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByFieldsOrdered + PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] + verifyExpectedOrder json "five" "four" None None None + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByFieldsOrdered + PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] + verifyExpectedOrder json "four" "five" None None None + } + ] + testList "jsonByContains" [ + testTask "succeeds when documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! json = conn.jsonByContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |} + verifyBeginEnd json + verifyDocById json "two" + verifyDocById json "four" + } + testTask "succeeds when documents are not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonByContains PostgresDb.TableName {| Value = "mauve" |} + verifyEmpty json + } + ] + testList "jsonByContainsOrdered" [ + // Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByContainsOrdered + PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ] + verifyExpectedOrder json "two" "four" None None None + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByContainsOrdered + PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ] + verifyExpectedOrder json "four" "two" None None None + } + ] + testList "jsonByJsonPath" [ + testTask "succeeds when documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + let! json = conn.jsonByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 15)" + verifyBeginEnd json + verifyDocById json "one" + verifyDocById json "two" + verifyDocById json "three" + } + testTask "succeeds when documents are not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" + verifyEmpty json + } + ] + testList "jsonByJsonPathOrdered" [ + // Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4 + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ] + verifyExpectedOrder json "one" "three" (Some "two") None None + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonByJsonPathOrdered + PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ] + verifyExpectedOrder json "two" "three" (Some "one") None None + } + ] + testList "jsonFirstByFields" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ] + verifyDocById json "two" + } + testTask "succeeds when multiple documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] + verifyAnyById json [ "five"; "four" ] + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByFields PostgresDb.TableName Any [ Field.Equal "Value" "absent" ] + verifyNoDoc json + } + ] + testList "jsonFirstByFieldsOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonFirstByFieldsOrdered + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] + verifyDocById json "five" + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonFirstByFieldsOrdered + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] + verifyDocById json "four" + } + ] + testList "jsonFirstByContains" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByContains PostgresDb.TableName {| Value = "another" |} + verifyDocById json "two" + } + testTask "succeeds when multiple documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |} + verifyAnyById json [ "two"; "four" ] + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByContains PostgresDb.TableName {| Value = "absent" |} + verifyNoDoc json + } + ] + testList "jsonFirstByContainsOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonFirstByContainsOrdered + PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ] + verifyDocById json "two" + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonFirstByContainsOrdered + PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ] + verifyDocById json "four" + } + ] + testList "jsonFirstByJsonPath" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByJsonPath PostgresDb.TableName """$.Value ? (@ == "FIRST!")""" + verifyDocById json "one" + } + testTask "succeeds when multiple documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByJsonPath PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" + verifyAnyById json [ "two"; "four" ] + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = conn.jsonFirstByJsonPath PostgresDb.TableName """$.Id ? (@ == "nope")""" + verifyNoDoc json + } + ] + testList "jsonFirstByJsonPathOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonFirstByJsonPathOrdered + PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ] + verifyDocById json "two" + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + let! json = + conn.jsonFirstByJsonPathOrdered + PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ] + verifyDocById json "four" + } + ] + testList "writeJsonAll" [ + testTask "succeeds when there is data" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonAll PostgresDb.TableName writer + verifyAllData (streamText stream) + } + testTask "succeeds when there is no data" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonAll PostgresDb.TableName writer + verifyEmpty (streamText stream) + } + ] + testList "writeJsonAllOrdered" [ + testTask "succeeds when ordering numerically" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonAllOrdered PostgresDb.TableName writer [ Field.Named "n:NumValue" ] + verifyExpectedOrder (streamText stream) "one" "three" (Some "two") (Some "four") (Some "five") + } + testTask "succeeds when ordering numerically descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonAllOrdered PostgresDb.TableName writer [ Field.Named "n:NumValue DESC" ] + verifyExpectedOrder (streamText stream) "five" "four" (Some "two") (Some "three") (Some "one") + } + testTask "succeeds when ordering alphabetically" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonAllOrdered PostgresDb.TableName writer [ Field.Named "Id DESC" ] + verifyExpectedOrder (streamText stream) "two" "three" (Some "one") (Some "four") (Some "five") + } + ] + testList "writeJsonById" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonById PostgresDb.TableName writer "two" + let json = streamText stream + Expect.stringStarts json """{"Id": "two",""" "An incorrect document was returned" + Expect.stringEnds json "}" "JSON should have ended with this document" + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonById PostgresDb.TableName writer "three hundred eighty-seven" + verifyNoDoc (streamText stream) + } + ] + testList "writeJsonByFields" [ + testTask "succeeds when documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFields + PostgresDb.TableName writer All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ] + verifySingleById (streamText stream) "four" + } + testTask "succeeds when documents are found using IN with numeric field" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFields PostgresDb.TableName writer All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ] + verifySingleById (streamText stream) "three" + } + testTask "succeeds when documents are not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFields + PostgresDb.TableName writer All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ] + verifyEmpty (streamText stream) + } + testTask "succeeds for InArray when matching documents exist" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! conn.ensureTable PostgresDb.TableName + for doc in ArrayDocument.TestDocuments do do! conn.insert PostgresDb.TableName doc + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFields + PostgresDb.TableName writer All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ] + let json = streamText stream + verifyBeginEnd json + verifyDocById json "first" + verifyDocById json "second" + } + testTask "succeeds for InArray when no matching documents exist" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! conn.ensureTable PostgresDb.TableName + for doc in ArrayDocument.TestDocuments do do! conn.insert PostgresDb.TableName doc + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFields + PostgresDb.TableName writer All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ] + verifyEmpty (streamText stream) + } + ] + testList "writeJsonByFieldsOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFieldsOrdered + PostgresDb.TableName writer All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] + verifyExpectedOrder (streamText stream) "five" "four" None None None + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByFieldsOrdered + PostgresDb.TableName writer All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] + verifyExpectedOrder (streamText stream) "four" "five" None None None + } + ] + testList "writeJsonByContains" [ + testTask "succeeds when documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByContains PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} + let json = streamText stream + verifyBeginEnd json + verifyDocById json "two" + verifyDocById json "four" + } + testTask "succeeds when documents are not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByContains PostgresDb.TableName writer {| Value = "mauve" |} + verifyEmpty (streamText stream) + } + ] + testList "writeJsonByContainsOrdered" [ + // Id = two, Sub.Bar = blue; Id = four, Sub.Bar = red + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByContainsOrdered + PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ] + verifyExpectedOrder (streamText stream) "two" "four" None None None + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByContainsOrdered + PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ] + verifyExpectedOrder (streamText stream) "four" "two" None None None + } + ] + testList "writeJsonByJsonPath" [ + testTask "succeeds when documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByJsonPath PostgresDb.TableName writer "$.NumValue ? (@ < 15)" + let json = streamText stream + verifyBeginEnd json + verifyDocById json "one" + verifyDocById json "two" + verifyDocById json "three" + } + testTask "succeeds when documents are not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByJsonPath PostgresDb.TableName writer "$.NumValue ? (@ < 0)" + verifyEmpty (streamText stream) + } + ] + testList "writeJsonByJsonPathOrdered" [ + // Id = one, NumValue = 0; Id = two, NumValue = 10; Id = three, NumValue = 4 + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByJsonPathOrdered + PostgresDb.TableName writer "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ] + verifyExpectedOrder (streamText stream) "one" "three" (Some "two") None None + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonByJsonPathOrdered + PostgresDb.TableName writer "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ] + verifyExpectedOrder (streamText stream) "two" "three" (Some "one") None None + } + ] + testList "writeJsonFirstByFields" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByFields PostgresDb.TableName writer Any [ Field.Equal "Value" "another" ] + verifyDocById (streamText stream) "two" + } + testTask "succeeds when multiple documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByFields PostgresDb.TableName writer Any [ Field.Equal "Value" "purple" ] + verifyAnyById (streamText stream) [ "five"; "four" ] + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByFields PostgresDb.TableName writer Any [ Field.Equal "Value" "absent" ] + verifyNoDoc (streamText stream) + } + ] + testList "writeJsonFirstByFieldsOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByFieldsOrdered + PostgresDb.TableName writer Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] + verifyDocById (streamText stream) "five" + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByFieldsOrdered + PostgresDb.TableName writer Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] + verifyDocById (streamText stream) "four" + } + ] + testList "writeJsonFirstByContains" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByContains PostgresDb.TableName writer {| Value = "another" |} + verifyDocById (streamText stream) "two" + } + testTask "succeeds when multiple documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByContains PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} + verifyAnyById (streamText stream) [ "two"; "four" ] + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByContains PostgresDb.TableName writer {| Value = "absent" |} + verifyNoDoc (streamText stream) + } + ] + testList "writeJsonFirstByContainsOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByContainsOrdered + PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ] + verifyDocById (streamText stream) "two" + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByContainsOrdered + PostgresDb.TableName writer {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ] + verifyDocById (streamText stream) "four" + } + ] + testList "writeJsonFirstByJsonPath" [ + testTask "succeeds when a document is found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByJsonPath PostgresDb.TableName writer """$.Value ? (@ == "FIRST!")""" + verifyDocById (streamText stream) "one" + } + testTask "succeeds when multiple documents are found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByJsonPath PostgresDb.TableName writer """$.Sub.Foo ? (@ == "green")""" + verifyAnyById (streamText stream) [ "two"; "four" ] + } + testTask "succeeds when a document is not found" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByJsonPath PostgresDb.TableName writer """$.Id ? (@ == "nope")""" + verifyNoDoc (streamText stream) + } + ] + testList "writeJsonFirstByJsonPathOrdered" [ + testTask "succeeds when sorting ascending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByJsonPathOrdered + PostgresDb.TableName writer """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ] + verifyDocById (streamText stream) "two" + } + testTask "succeeds when sorting descending" { + use db = PostgresDb.BuildDb() + use conn = mkConn db + do! loadDocs conn + + use stream = new MemoryStream() + use writer = writeStream stream + do! conn.writeJsonFirstByJsonPathOrdered + PostgresDb.TableName writer """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ] + verifyDocById (streamText stream) "four" + } + ] testList "updateById" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() @@ -694,7 +1610,7 @@ let integrationTests = use conn = mkConn db let! before = conn.countAll PostgresDb.TableName Expect.equal before 0 "There should have been no documents returned" - + // This not raising an exception is the test do! conn.updateById PostgresDb.TableName "test" { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } } @@ -707,7 +1623,7 @@ let integrationTests = do! loadDocs conn do! conn.updateByFunc - PostgresDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } + PostgresDb.TableName _.Id { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } let! after = conn.findById PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" Expect.equal @@ -720,10 +1636,10 @@ let integrationTests = use conn = mkConn db let! before = conn.countAll PostgresDb.TableName Expect.equal before 0 "There should have been no documents returned" - + // This not raising an exception is the test do! conn.updateByFunc - PostgresDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } + PostgresDb.TableName _.Id { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } } ] testList "patchById" [ @@ -731,7 +1647,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + do! conn.patchById PostgresDb.TableName "one" {| NumValue = 44 |} let! after = conn.findById PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" @@ -742,7 +1658,7 @@ let integrationTests = use conn = mkConn db let! before = conn.countAll PostgresDb.TableName Expect.equal before 0 "There should have been no documents returned" - + // This not raising an exception is the test do! conn.patchById PostgresDb.TableName "test" {| Foo = "green" |} } @@ -752,7 +1668,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + do! conn.patchByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |} let! after = conn.countByFields PostgresDb.TableName Any [ Field.Equal "NumValue" "77" ] Expect.equal after 2 "There should have been 2 documents returned" @@ -762,7 +1678,7 @@ let integrationTests = use conn = mkConn db let! before = conn.countAll PostgresDb.TableName Expect.equal before 0 "There should have been no documents returned" - + // This not raising an exception is the test do! conn.patchByFields PostgresDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |} } @@ -772,7 +1688,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + do! conn.patchByContains PostgresDb.TableName {| Value = "purple" |} {| NumValue = 77 |} let! after = conn.countByContains PostgresDb.TableName {| NumValue = 77 |} Expect.equal after 2 "There should have been 2 documents returned" @@ -782,7 +1698,7 @@ let integrationTests = use conn = mkConn db let! before = conn.countAll PostgresDb.TableName Expect.equal before 0 "There should have been no documents returned" - + // This not raising an exception is the test do! conn.patchByContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |} } @@ -792,7 +1708,7 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + do! conn.patchByJsonPath PostgresDb.TableName "$.NumValue ? (@ > 10)" {| NumValue = 1000 |} let! after = conn.countByJsonPath PostgresDb.TableName "$.NumValue ? (@ > 999)" Expect.equal after 2 "There should have been 2 documents returned" @@ -802,7 +1718,7 @@ let integrationTests = use conn = mkConn db let! before = conn.countAll PostgresDb.TableName Expect.equal before 0 "There should have been no documents returned" - + // This not raising an exception is the test do! conn.patchByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |} } @@ -834,14 +1750,14 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + // This not raising an exception is the test do! conn.removeFieldsById PostgresDb.TableName "two" [ "AFieldThatIsNotThere" ] } testTask "succeeds when no document is matched" { use db = PostgresDb.BuildDb() use conn = mkConn db - + // This not raising an exception is the test do! conn.removeFieldsById PostgresDb.TableName "two" [ "Value" ] } @@ -874,14 +1790,14 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + // This not raising an exception is the test do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.Equal "NumValue" "17" ] [ "Nothing" ] } testTask "succeeds when no document is matched" { use db = PostgresDb.BuildDb() use conn = mkConn db - + // This not raising an exception is the test do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ] @@ -914,14 +1830,14 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + // This not raising an exception is the test do! conn.removeFieldsByContains PostgresDb.TableName {| NumValue = 17 |} [ "Nothing" ] } testTask "succeeds when no document is matched" { use db = PostgresDb.BuildDb() use conn = mkConn db - + // This not raising an exception is the test do! conn.removeFieldsByContains PostgresDb.TableName {| Abracadabra = "apple" |} [ "Value" ] } @@ -953,14 +1869,14 @@ let integrationTests = use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - + // This not raising an exception is the test do! conn.removeFieldsByJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Nothing" ] } testTask "succeeds when no document is matched" { use db = PostgresDb.BuildDb() use conn = mkConn db - + // This not raising an exception is the test do! conn.removeFieldsByJsonPath PostgresDb.TableName "$.Abracadabra ? (@ == \"apple\")" [ "Value" ] }