Initial Development #1
| @ -145,12 +145,8 @@ object Json { | |||||||
|      */ |      */ | ||||||
|     @Throws(DocumentException::class) |     @Throws(DocumentException::class) | ||||||
|     @JvmStatic |     @JvmStatic | ||||||
|     fun byFields( |     fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) = | ||||||
|         tableName: String, |         byFields(tableName, fields, howMatched, null, conn) | ||||||
|         fields: Collection<Field<*>>, |  | ||||||
|         howMatched: FieldMatch? = null, |  | ||||||
|         conn: Connection |  | ||||||
|     ) = byFields(tableName, fields, howMatched, null, conn) |  | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only) |      * Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only) | ||||||
|  | |||||||
							
								
								
									
										348
									
								
								src/kotlinx/src/main/kotlin/Json.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								src/kotlinx/src/main/kotlin/Json.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,348 @@ | |||||||
|  | package solutions.bitbadger.documents.kotlinx | ||||||
|  | 
 | ||||||
|  | import solutions.bitbadger.documents.* | ||||||
|  | import solutions.bitbadger.documents.query.FindQuery | ||||||
|  | import solutions.bitbadger.documents.query.orderBy | ||||||
|  | import solutions.bitbadger.documents.java.Json as CoreJson | ||||||
|  | import java.sql.Connection | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Functions to find and retrieve documents, returning them as JSON strings | ||||||
|  |  */ | ||||||
|  | object Json { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve all documents in the given table, ordering results by the optional given fields | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents from the given table | ||||||
|  |      * @throws DocumentException If query execution fails | ||||||
|  |      */ | ||||||
|  |     fun all(tableName: String, orderBy: Collection<Field<*>>? = null, conn: Connection) = | ||||||
|  |         CoreJson.all(tableName, orderBy, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve all documents in the given table (creates connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return A JSON array of documents from the given table | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if query execution fails | ||||||
|  |      */ | ||||||
|  |     fun all(tableName: String, orderBy: Collection<Field<*>>? = null) = | ||||||
|  |         CoreJson.all(tableName, orderBy) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve all documents in the given table | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents from the given table | ||||||
|  |      * @throws DocumentException If query execution fails | ||||||
|  |      */ | ||||||
|  |     fun all(tableName: String, conn: Connection) = | ||||||
|  |         CoreJson.all(tableName, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve a document by its ID | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which the document should be retrieved | ||||||
|  |      * @param docId The ID of the document to retrieve | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON document if found, an empty JSON object if not found | ||||||
|  |      * @throws DocumentException If no dialect has been configured | ||||||
|  |      */ | ||||||
|  |     fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) = | ||||||
|  |         CoreJson.byId(tableName, docId, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve a document by its ID (creates connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which the document should be retrieved | ||||||
|  |      * @param docId The ID of the document to retrieve | ||||||
|  |      * @return A JSON document if found, an empty JSON object if not found | ||||||
|  |      * @throws DocumentException If no connection string has been set | ||||||
|  |      */ | ||||||
|  |     fun <TKey> byId(tableName: String, docId: TKey) = | ||||||
|  |         CoreJson.byId(tableName, docId) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a field comparison, ordering results by the given fields | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param fields The fields which should be compared | ||||||
|  |      * @param howMatched How the fields should be matched | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents matching the field comparison | ||||||
|  |      * @throws DocumentException If no dialect has been configured, or if parameters are invalid | ||||||
|  |      */ | ||||||
|  |     fun byFields( | ||||||
|  |         tableName: String, | ||||||
|  |         fields: Collection<Field<*>>, | ||||||
|  |         howMatched: FieldMatch? = null, | ||||||
|  |         orderBy: Collection<Field<*>>? = null, | ||||||
|  |         conn: Connection | ||||||
|  |     ) = CoreJson.byFields(tableName, fields, howMatched, orderBy, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a field comparison, ordering results by the given fields (creates connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param fields The fields which should be compared | ||||||
|  |      * @param howMatched How the fields should be matched | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return A JSON array of documents matching the field comparison | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if parameters are invalid | ||||||
|  |      */ | ||||||
|  |     fun byFields( | ||||||
|  |         tableName: String, | ||||||
|  |         fields: Collection<Field<*>>, | ||||||
|  |         howMatched: FieldMatch? = null, | ||||||
|  |         orderBy: Collection<Field<*>>? = null | ||||||
|  |     ) = CoreJson.byFields(tableName, fields, howMatched, orderBy) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a field comparison | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param fields The fields which should be compared | ||||||
|  |      * @param howMatched How the fields should be matched | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents matching the field comparison | ||||||
|  |      * @throws DocumentException If no dialect has been configured, or if parameters are invalid | ||||||
|  |      */ | ||||||
|  |     fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) = | ||||||
|  |         CoreJson.byFields(tableName, fields, howMatched, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param criteria The object for which JSON containment should be checked | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents matching the JSON containment query | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     inline fun <reified TContains> byContains( | ||||||
|  |         tableName: String, | ||||||
|  |         criteria: TContains, | ||||||
|  |         orderBy: Collection<Field<*>>? = null, | ||||||
|  |         conn: Connection | ||||||
|  |     ) = Custom.jsonArray( | ||||||
|  |         FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""), | ||||||
|  |         listOf(Parameters.json(":criteria", criteria)), | ||||||
|  |         conn, | ||||||
|  |         Results::jsonFromData | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only; creates | ||||||
|  |      * connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param criteria The object for which JSON containment should be checked | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return A JSON array of documents matching the JSON containment query | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     inline fun <reified TContains> byContains( | ||||||
|  |         tableName: String, | ||||||
|  |         criteria: TContains, | ||||||
|  |         orderBy: Collection<Field<*>>? = null | ||||||
|  |     ) = Configuration.dbConn().use { byContains(tableName, criteria, orderBy, it) } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a JSON containment query (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param criteria The object for which JSON containment should be checked | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents matching the JSON containment query | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) = | ||||||
|  |         byContains(tableName, criteria, null, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param path The JSON path comparison to match | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents matching the JSON Path match query | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     fun byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null, conn: Connection) = | ||||||
|  |         CoreJson.byJsonPath(tableName, path, orderBy, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only; creates | ||||||
|  |      * connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param path The JSON path comparison to match | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return A JSON array of documents matching the JSON Path match query | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     fun byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) = | ||||||
|  |         CoreJson.byJsonPath(tableName, path, orderBy) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve documents using a JSON Path match query (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param path The JSON path comparison to match | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return A JSON array of documents matching the JSON Path match query | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     fun byJsonPath(tableName: String, path: String, conn: Connection) = | ||||||
|  |         CoreJson.byJsonPath(tableName, path, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a field comparison and optional ordering fields | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param fields The fields which should be compared | ||||||
|  |      * @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return The first JSON document matching the field comparison if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If no dialect has been configured, or if parameters are invalid | ||||||
|  |      */ | ||||||
|  |     fun firstByFields( | ||||||
|  |         tableName: String, | ||||||
|  |         fields: Collection<Field<*>>, | ||||||
|  |         howMatched: FieldMatch? = null, | ||||||
|  |         orderBy: Collection<Field<*>>? = null, | ||||||
|  |         conn: Connection | ||||||
|  |     ) = CoreJson.firstByFields(tableName, fields, howMatched, orderBy, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a field comparison and optional ordering fields (creates connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param fields The fields which should be compared | ||||||
|  |      * @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return The first JSON document matching the field comparison if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if parameters are invalid | ||||||
|  |      */ | ||||||
|  |     fun firstByFields( | ||||||
|  |         tableName: String, | ||||||
|  |         fields: Collection<Field<*>>, | ||||||
|  |         howMatched: FieldMatch? = null, | ||||||
|  |         orderBy: Collection<Field<*>>? = null | ||||||
|  |     ) = CoreJson.firstByFields(tableName, fields, howMatched, orderBy) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a field comparison | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param fields The fields which should be compared | ||||||
|  |      * @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return The first JSON document matching the field comparison if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If no dialect has been configured, or if parameters are invalid | ||||||
|  |      */ | ||||||
|  |     fun firstByFields( | ||||||
|  |         tableName: String, | ||||||
|  |         fields: Collection<Field<*>>, | ||||||
|  |         howMatched: FieldMatch? = null, | ||||||
|  |         conn: Connection | ||||||
|  |     ) = CoreJson.firstByFields(tableName, fields, howMatched, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param criteria The object for which JSON containment should be checked | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     inline fun <reified TContains> firstByContains( | ||||||
|  |         tableName: String, | ||||||
|  |         criteria: TContains, | ||||||
|  |         orderBy: Collection<Field<*>>? = null, | ||||||
|  |         conn: Connection | ||||||
|  |     ) = Custom.jsonSingle( | ||||||
|  |         FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""), | ||||||
|  |         listOf(Parameters.json(":criteria", criteria)), | ||||||
|  |         conn, | ||||||
|  |         Results::jsonFromData | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a JSON containment query (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param criteria The object for which JSON containment should be checked | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     inline fun <reified TContains> firstByContains(tableName: String, criteria: TContains, conn: Connection) = | ||||||
|  |         firstByContains(tableName, criteria, null, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only; creates | ||||||
|  |      * connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param criteria The object for which JSON containment should be checked | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     inline fun <reified TContains> firstByContains( | ||||||
|  |         tableName: String, | ||||||
|  |         criteria: TContains, | ||||||
|  |         orderBy: Collection<Field<*>>? = null | ||||||
|  |     ) = Configuration.dbConn().use { firstByContains(tableName, criteria, orderBy, it) } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param path The JSON path comparison to match | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     fun firstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null, conn: Connection) = | ||||||
|  |         CoreJson.firstByJsonPath(tableName, path, orderBy, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a JSON Path match query (PostgreSQL only) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param path The JSON path comparison to match | ||||||
|  |      * @param conn The connection over which documents should be retrieved | ||||||
|  |      * @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     fun firstByJsonPath(tableName: String, path: String, conn: Connection) = | ||||||
|  |         CoreJson.firstByJsonPath(tableName, path, conn) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only; creates | ||||||
|  |      * connection) | ||||||
|  |      * | ||||||
|  |      * @param tableName The table from which documents should be retrieved | ||||||
|  |      * @param path The JSON path comparison to match | ||||||
|  |      * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |      * @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise | ||||||
|  |      * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |      */ | ||||||
|  |     fun firstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) = | ||||||
|  |         CoreJson.firstByJsonPath(tableName, path, orderBy) | ||||||
|  | } | ||||||
| @ -233,7 +233,7 @@ inline fun <reified TContains> Connection.existsByContains(tableName: String, cr | |||||||
| fun Connection.existsByJsonPath(tableName: String, path: String) = | fun Connection.existsByJsonPath(tableName: String, path: String) = | ||||||
|     Exists.byJsonPath(tableName, path, this) |     Exists.byJsonPath(tableName, path, this) | ||||||
| 
 | 
 | ||||||
| // ~~~ DOCUMENT RETRIEVAL QUERIES ~~~ | // ~~~ DOCUMENT RETRIEVAL QUERIES (Domain Objects) ~~~ | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Retrieve all documents in the given table, ordering results by the optional given fields |  * Retrieve all documents in the given table, ordering results by the optional given fields | ||||||
| @ -347,6 +347,119 @@ inline fun <reified TDoc : Any> Connection.findFirstByJsonPath( | |||||||
|     orderBy: Collection<Field<*>>? = null |     orderBy: Collection<Field<*>>? = null | ||||||
| ) = Find.firstByJsonPath<TDoc>(tableName, path, orderBy, this) | ) = Find.firstByJsonPath<TDoc>(tableName, path, orderBy, this) | ||||||
| 
 | 
 | ||||||
|  | // ~~~ DOCUMENT RETRIEVAL QUERIES (Raw JSON) ~~~ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve all documents in the given table | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return A JSON array of documents from the given table | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if query execution fails | ||||||
|  |  */ | ||||||
|  | fun Connection.jsonAll(tableName: String, orderBy: Collection<Field<*>>? = null) = | ||||||
|  |     Json.all(tableName, orderBy, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve a document by its ID | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which the document should be retrieved | ||||||
|  |  * @param docId The ID of the document to retrieve | ||||||
|  |  * @return A JSON document if found, an empty JSON object if not found | ||||||
|  |  * @throws DocumentException If no connection string has been set | ||||||
|  |  */ | ||||||
|  | fun <TKey> Connection.jsonById(tableName: String, docId: TKey) = | ||||||
|  |     Json.byId(tableName, docId, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve documents using a field comparison, ordering results by the given fields | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param fields The fields which should be compared | ||||||
|  |  * @param howMatched How the fields should be matched | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return A JSON array of documents matching the field comparison | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if parameters are invalid | ||||||
|  |  */ | ||||||
|  | fun Connection.jsonByFields( | ||||||
|  |     tableName: String, | ||||||
|  |     fields: Collection<Field<*>>, | ||||||
|  |     howMatched: FieldMatch? = null, | ||||||
|  |     orderBy: Collection<Field<*>>? = null | ||||||
|  | ) = Json.byFields(tableName, fields, howMatched, orderBy, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only) | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param criteria The object for which JSON containment should be checked | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return A JSON array of documents matching the JSON containment query | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |  */ | ||||||
|  | inline fun <reified TContains> Connection.jsonByContains( | ||||||
|  |     tableName: String, | ||||||
|  |     criteria: TContains, | ||||||
|  |     orderBy: Collection<Field<*>>? = null | ||||||
|  | ) = Json.byContains(tableName, criteria, orderBy, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only) | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param path The JSON path comparison to match | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return A JSON array of documents matching the JSON Path match query | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |  */ | ||||||
|  | fun Connection.jsonByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) = | ||||||
|  |     Json.byJsonPath(tableName, path, orderBy, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve the first document using a field comparison and optional ordering fields | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param fields The fields which should be compared | ||||||
|  |  * @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return The first JSON document matching the field comparison if found, an empty JSON object otherwise | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if parameters are invalid | ||||||
|  |  */ | ||||||
|  | fun Connection.jsonFirstByFields( | ||||||
|  |     tableName: String, | ||||||
|  |     fields: Collection<Field<*>>, | ||||||
|  |     howMatched: FieldMatch? = null, | ||||||
|  |     orderBy: Collection<Field<*>>? = null | ||||||
|  | ) = Json.firstByFields(tableName, fields, howMatched, orderBy, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only) | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param criteria The object for which JSON containment should be checked | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |  */ | ||||||
|  | inline fun <reified TContains> Connection.jsonFirstByContains( | ||||||
|  |     tableName: String, | ||||||
|  |     criteria: TContains, | ||||||
|  |     orderBy: Collection<Field<*>>? = null | ||||||
|  | ) = Json.firstByContains(tableName, criteria, orderBy, this) | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only; creates | ||||||
|  |  * connection) | ||||||
|  |  * | ||||||
|  |  * @param tableName The table from which documents should be retrieved | ||||||
|  |  * @param path The JSON path comparison to match | ||||||
|  |  * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) | ||||||
|  |  * @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise | ||||||
|  |  * @throws DocumentException If no connection string has been set, or if called on a SQLite connection | ||||||
|  |  */ | ||||||
|  | fun Connection.jsonFirstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) = | ||||||
|  |     Json.firstByJsonPath(tableName, path, orderBy, this) | ||||||
|  | 
 | ||||||
| // ~~~ DOCUMENT PATCH (PARTIAL UPDATE) QUERIES ~~~ | // ~~~ DOCUMENT PATCH (PARTIAL UPDATE) QUERIES ~~~ | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -49,5 +49,20 @@ data class JsonDocument(val id: String, val value: String = "", val numValue: In | |||||||
| 
 | 
 | ||||||
|         fun load(db: ThrowawayDatabase, tableName: String = TEST_TABLE) = |         fun load(db: ThrowawayDatabase, tableName: String = TEST_TABLE) = | ||||||
|             testDocuments.forEach { db.conn.insert(tableName, it) } |             testDocuments.forEach { db.conn.insert(tableName, it) } | ||||||
|  | 
 | ||||||
|  |         /** Document ID `one` as a JSON string */ | ||||||
|  |         val one = """{"id":"one","value":"FIRST!","numValue":0}""" | ||||||
|  | 
 | ||||||
|  |         /** Document ID `two` as a JSON string */ | ||||||
|  |         val two = """{"id":"two","value":"another","numValue":10,"sub":{"foo":"green","bar":"blue"}}""" | ||||||
|  | 
 | ||||||
|  |         /** Document ID `three` as a JSON string */ | ||||||
|  |         val three = """{"id":"three","value":"","numValue":4}""" | ||||||
|  | 
 | ||||||
|  |         /** Document ID `four` as a JSON string */ | ||||||
|  |         val four = """{"id":"four","value":"purple","numValue":17,"sub":{"foo":"green","bar":"red"}}""" | ||||||
|  | 
 | ||||||
|  |         /** Document ID `five` as a JSON string */ | ||||||
|  |         val five = """{"id":"five","value":"purple","numValue":18}""" | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,7 +2,22 @@ package solutions.bitbadger.documents.kotlinx.tests.integration | |||||||
| 
 | 
 | ||||||
| import solutions.bitbadger.documents.Configuration | import solutions.bitbadger.documents.Configuration | ||||||
| import solutions.bitbadger.documents.Dialect | import solutions.bitbadger.documents.Dialect | ||||||
|  | import solutions.bitbadger.documents.Field | ||||||
|  | import solutions.bitbadger.documents.FieldMatch | ||||||
|  | import solutions.bitbadger.documents.kotlinx.extensions.* | ||||||
|  | import solutions.bitbadger.documents.kotlinx.tests.* | ||||||
|  | import kotlin.test.assertEquals | ||||||
|  | import kotlin.test.assertTrue | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Tests for the JSON-returning functions | ||||||
|  |  * | ||||||
|  |  * NOTE: PostgreSQL JSONB columns do not preserve the original JSON with which a document was stored. These tests are | ||||||
|  |  * the most complex within the library, as they have split testing based on the backing data store. The PostgreSQL tests | ||||||
|  |  * check IDs (and, in the case of ordered queries, which ones occur before which others) vs. the entire JSON string. | ||||||
|  |  * Meanwhile, SQLite stores JSON as text, and will return exactly the JSON it was given when it was originally written. | ||||||
|  |  * These tests can ensure the expected round-trip of the entire JSON string. | ||||||
|  |  */ | ||||||
| object JsonFunctions { | object JsonFunctions { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -15,6 +30,368 @@ object JsonFunctions { | |||||||
|     fun maybeJsonB(json: String) = |     fun maybeJsonB(json: String) = | ||||||
|         when (Configuration.dialect()) { |         when (Configuration.dialect()) { | ||||||
|             Dialect.SQLITE -> json |             Dialect.SQLITE -> json | ||||||
|             Dialect.POSTGRESQL -> json.replace("\":\"", "\": \"").replace("\",\"", "\", \"").replace("\":[", "\": [") |             Dialect.POSTGRESQL -> json.replace("\":", "\": ").replace(",\"", ", \"") | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Create a snippet of JSON to find a document ID | ||||||
|  |      * | ||||||
|  |      * @param id The ID of the document | ||||||
|  |      * @return A connection-aware ID to check for presence and positioning | ||||||
|  |      */ | ||||||
|  |     private fun docId(id: String) = | ||||||
|  |         maybeJsonB("{\"id\":\"$id\"") | ||||||
|  | 
 | ||||||
|  |     fun allDefault(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonAll(TEST_TABLE) | ||||||
|  |         assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> { | ||||||
|  |                 assertTrue(json.contains(JsonDocument.one), "Document 'one' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(JsonDocument.two), "Document 'two' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(JsonDocument.three), "Document 'three' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(JsonDocument.four), "Document 'four' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(JsonDocument.five), "Document 'five' not found in JSON ($json)") | ||||||
|  |             } | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 assertTrue(json.contains(docId("one")), "Document 'one' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("two")), "Document 'two' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("three")), "Document 'three' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("four")), "Document 'four' not found in JSON ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("five")), "Document 'five' not found in JSON ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun allEmpty(db: ThrowawayDatabase) = | ||||||
|  |         assertEquals("[]", db.conn.jsonAll(TEST_TABLE), "There should have been no documents returned") | ||||||
|  | 
 | ||||||
|  |     fun byIdString(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonById(TEST_TABLE, "two") | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.two, json, "An incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("two")), "An incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byIdNumber(db: ThrowawayDatabase) { | ||||||
|  |         Configuration.idField = "key" | ||||||
|  |         try { | ||||||
|  |             db.conn.insert(TEST_TABLE, NumIdDocument(18, "howdy")) | ||||||
|  |             assertEquals( | ||||||
|  |                 maybeJsonB("{\"key\":18,\"text\":\"howdy\"}"), db.conn.jsonById(TEST_TABLE, 18), | ||||||
|  |                 "The document should have been found by numeric ID" | ||||||
|  |             ) | ||||||
|  |         } finally { | ||||||
|  |             Configuration.idField = "id" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byIdNotFound(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals("{}", db.conn.jsonById(TEST_TABLE, "x"), "There should have been no document returned") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byFieldsMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByFields( | ||||||
|  |             TEST_TABLE, listOf(Field.any("value", listOf("blue", "purple")), Field.exists("sub")), FieldMatch.ALL | ||||||
|  |         ) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals("[${JsonDocument.four}]", json, "The incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("four")),"The incorrect document was returned ($json)") | ||||||
|  |                 assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byFieldsMatchOrdered(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByFields( | ||||||
|  |             TEST_TABLE, listOf(Field.equal("value", "purple")), orderBy = listOf(Field.named("id")) | ||||||
|  |         ) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals( | ||||||
|  |                 "[${JsonDocument.five},${JsonDocument.four}]", json, "The documents were not ordered correctly" | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 val fiveIdx = json.indexOf(docId("five")) | ||||||
|  |                 val fourIdx = json.indexOf(docId("four")) | ||||||
|  |                 assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |                 assertTrue(fiveIdx >= 0, "Document 'five' not found ($json)") | ||||||
|  |                 assertTrue(fourIdx >= 0, "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(fiveIdx < fourIdx, "Document 'five' should have been before 'four' ($json)") | ||||||
|  |                 assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byFieldsMatchNumIn(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByFields(TEST_TABLE, listOf(Field.any("numValue", listOf(2, 4, 6, 8)))) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals("[${JsonDocument.three}]", json, "The incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("three")), "The incorrect document was returned ($json)") | ||||||
|  |                 assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byFieldsNoMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals( | ||||||
|  |             "[]", db.conn.jsonByFields(TEST_TABLE, listOf(Field.greater("numValue", 100))), | ||||||
|  |             "There should have been no documents returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byFieldsMatchInArray(db: ThrowawayDatabase) { | ||||||
|  |         ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) } | ||||||
|  |         val json = db.conn.jsonByFields(TEST_TABLE, listOf(Field.inArray("values", TEST_TABLE, listOf("c")))) | ||||||
|  |         assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |         assertTrue(json.contains(docId("first")), "The 'first' document was not found ($json)") | ||||||
|  |         assertTrue(json.contains(docId("second")), "The 'second' document was not found ($json)") | ||||||
|  |         assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byFieldsNoMatchInArray(db: ThrowawayDatabase) { | ||||||
|  |         ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) } | ||||||
|  |         assertEquals( | ||||||
|  |             "[]", db.conn.jsonByFields( | ||||||
|  |                 TEST_TABLE, listOf(Field.inArray("values", TEST_TABLE, listOf("j"))) | ||||||
|  |             ), "There should have been no documents returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byContainsMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "purple")) | ||||||
|  |         assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> { | ||||||
|  |                 assertTrue(json.contains(JsonDocument.four), "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(json.contains(JsonDocument.five), "Document 'five' not found ($json)") | ||||||
|  |             } | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 assertTrue(json.contains(docId("four")), "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("five")), "Document 'five' not found ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byContainsMatchOrdered(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByContains<Map<String, Map<String, String>>>( | ||||||
|  |             TEST_TABLE, mapOf("sub" to mapOf("foo" to "green")), listOf(Field.named("value")) | ||||||
|  |         ) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals( | ||||||
|  |                 "[${JsonDocument.two},${JsonDocument.four}]", json, "The documents were not ordered correctly" | ||||||
|  |             ) | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 val twoIdx = json.indexOf(docId("two")) | ||||||
|  |                 val fourIdx = json.indexOf(docId("four")) | ||||||
|  |                 assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |                 assertTrue(twoIdx >= 0, "Document 'two' not found ($json)") | ||||||
|  |                 assertTrue(fourIdx >= 0, "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(twoIdx < fourIdx, "Document 'two' should have been before 'four' ($json)") | ||||||
|  |                 assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byContainsNoMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals( | ||||||
|  |             "[]", | ||||||
|  |             db.conn.jsonByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "indigo")), | ||||||
|  |             "There should have been no documents returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byJsonPathMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)") | ||||||
|  |         assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> { | ||||||
|  |                 assertTrue(json.contains(JsonDocument.four), "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(json.contains(JsonDocument.five), "Document 'five' not found ($json)") | ||||||
|  |             } | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 assertTrue(json.contains(docId("four")), "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(json.contains(docId("five")), "Document 'five' not found ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byJsonPathMatchOrdered(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)", listOf(Field.named("id"))) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals( | ||||||
|  |                 "[${JsonDocument.five},${JsonDocument.four}]", json, "The documents were not ordered correctly" | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |             Dialect.POSTGRESQL -> { | ||||||
|  |                 val fiveIdx = json.indexOf(docId("five")) | ||||||
|  |                 val fourIdx = json.indexOf(docId("four")) | ||||||
|  |                 assertTrue(json.startsWith("["), "JSON should start with '[' ($json)") | ||||||
|  |                 assertTrue(fiveIdx >= 0, "Document 'five' not found ($json)") | ||||||
|  |                 assertTrue(fourIdx >= 0, "Document 'four' not found ($json)") | ||||||
|  |                 assertTrue(fiveIdx < fourIdx, "Document 'five' should have been before 'four' ($json)") | ||||||
|  |                 assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun byJsonPathNoMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals( | ||||||
|  |             "[]", | ||||||
|  |             db.conn.jsonByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)"), | ||||||
|  |             "There should have been no documents returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByFieldsMatchOne(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByFields(TEST_TABLE, listOf(Field.equal("value", "another"))) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.two, json, "The incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("two")), "The incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByFieldsMatchMany(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByFields(TEST_TABLE, listOf(Field.equal("sub.foo", "green"))) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertTrue( | ||||||
|  |                 json.contains(JsonDocument.two) || json.contains(JsonDocument.four), | ||||||
|  |                 "Expected document 'two' or 'four' ($json)" | ||||||
|  |             ) | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue( | ||||||
|  |                 json.contains(docId("two")) || json.contains(docId("four")), | ||||||
|  |                 "Expected document 'two' or 'four' ($json)" | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByFieldsMatchOrdered(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByFields( | ||||||
|  |             TEST_TABLE, listOf(Field.equal("sub.foo", "green")), orderBy = listOf(Field.named("n:numValue DESC")) | ||||||
|  |         ) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.four, json, "An incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("four")), "An incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByFieldsNoMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals( | ||||||
|  |             "{}", | ||||||
|  |             db.conn.jsonFirstByFields(TEST_TABLE, listOf(Field.equal("value", "absent"))), | ||||||
|  |             "There should have been no document returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByContainsMatchOne(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "FIRST!")) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.one, json, "An incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("one")), "An incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByContainsMatchMany(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "purple")) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertTrue( | ||||||
|  |                 json.contains(JsonDocument.four) || json.contains(JsonDocument.five), | ||||||
|  |                 "Expected document 'four' or 'five' ($json)" | ||||||
|  |             ) | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue( | ||||||
|  |                 json.contains(docId("four")) || json.contains(docId("five")), | ||||||
|  |                 "Expected document 'four' or 'five' ($json)" | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByContainsMatchOrdered(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByContains<Map<String, String>>( | ||||||
|  |             TEST_TABLE, mapOf("value" to "purple"), listOf(Field.named("sub.bar NULLS FIRST")) | ||||||
|  |         ) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.five, json, "An incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("five")), "An incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByContainsNoMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals( | ||||||
|  |             "{}", | ||||||
|  |             db.conn.jsonFirstByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "indigo")), | ||||||
|  |             "There should have been no document returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByJsonPathMatchOne(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10)") | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.two, json, "An incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("two")), "An incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByJsonPathMatchMany(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)") | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertTrue( | ||||||
|  |                 json.contains(JsonDocument.four) || json.contains(JsonDocument.five), | ||||||
|  |                 "Expected document 'four' or 'five' ($json)" | ||||||
|  |             ) | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue( | ||||||
|  |                 json.contains(docId("four")) || json.contains(docId("five")), | ||||||
|  |                 "Expected document 'four' or 'five' ($json)" | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByJsonPathMatchOrdered(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         val json = db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)", listOf(Field.named("id DESC"))) | ||||||
|  |         when (Configuration.dialect()) { | ||||||
|  |             Dialect.SQLITE -> assertEquals(JsonDocument.four, json, "An incorrect document was returned") | ||||||
|  |             Dialect.POSTGRESQL -> assertTrue(json.contains(docId("four")), "An incorrect document was returned ($json)") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fun firstByJsonPathNoMatch(db: ThrowawayDatabase) { | ||||||
|  |         JsonDocument.load(db) | ||||||
|  |         assertEquals( | ||||||
|  |             "{}", | ||||||
|  |             db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)"), | ||||||
|  |             "There should have been no document returned" | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
							
								
								
									
										156
									
								
								src/kotlinx/src/test/kotlin/integration/PostgreSQLJsonIT.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/kotlinx/src/test/kotlin/integration/PostgreSQLJsonIT.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,156 @@ | |||||||
|  | package solutions.bitbadger.documents.kotlinx.tests.integration | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.DisplayName | ||||||
|  | import kotlin.test.Test | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * PostgreSQL integration tests for the `Json` object / `json*` connection extension functions | ||||||
|  |  */ | ||||||
|  | @DisplayName("KotlinX | PostgreSQL: Json") | ||||||
|  | class PostgreSQLJsonIT { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("all retrieves all documents") | ||||||
|  |     fun allDefault() = | ||||||
|  |         PgDB().use(JsonFunctions::allDefault) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("all succeeds with an empty table") | ||||||
|  |     fun allEmpty() = | ||||||
|  |         PgDB().use(JsonFunctions::allEmpty) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byId retrieves a document via a string ID") | ||||||
|  |     fun byIdString() = | ||||||
|  |         PgDB().use(JsonFunctions::byIdString) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byId retrieves a document via a numeric ID") | ||||||
|  |     fun byIdNumber() = | ||||||
|  |         PgDB().use(JsonFunctions::byIdNumber) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byId returns null when a matching ID is not found") | ||||||
|  |     fun byIdNotFound() = | ||||||
|  |         PgDB().use(JsonFunctions::byIdNotFound) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves matching documents") | ||||||
|  |     fun byFieldsMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::byFieldsMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves ordered matching documents") | ||||||
|  |     fun byFieldsMatchOrdered() = | ||||||
|  |         PgDB().use(JsonFunctions::byFieldsMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves matching documents with a numeric IN clause") | ||||||
|  |     fun byFieldsMatchNumIn() = | ||||||
|  |         PgDB().use(JsonFunctions::byFieldsMatchNumIn) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields succeeds when no documents match") | ||||||
|  |     fun byFieldsNoMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::byFieldsNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves matching documents with an IN_ARRAY comparison") | ||||||
|  |     fun byFieldsMatchInArray() = | ||||||
|  |         PgDB().use(JsonFunctions::byFieldsMatchInArray) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields succeeds when no documents match an IN_ARRAY comparison") | ||||||
|  |     fun byFieldsNoMatchInArray() = | ||||||
|  |         PgDB().use(JsonFunctions::byFieldsNoMatchInArray) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byContains retrieves matching documents") | ||||||
|  |     fun byContainsMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::byContainsMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byContains retrieves ordered matching documents") | ||||||
|  |     fun byContainsMatchOrdered() = | ||||||
|  |         PgDB().use(JsonFunctions::byContainsMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byContains succeeds when no documents match") | ||||||
|  |     fun byContainsNoMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::byContainsNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byJsonPath retrieves matching documents") | ||||||
|  |     fun byJsonPathMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::byJsonPathMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byJsonPath retrieves ordered matching documents") | ||||||
|  |     fun byJsonPathMatchOrdered() = | ||||||
|  |         PgDB().use(JsonFunctions::byJsonPathMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byJsonPath succeeds when no documents match") | ||||||
|  |     fun byJsonPathNoMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::byJsonPathNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields retrieves a matching document") | ||||||
|  |     fun firstByFieldsMatchOne() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByFieldsMatchOne) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields retrieves a matching document among many") | ||||||
|  |     fun firstByFieldsMatchMany() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByFieldsMatchMany) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields retrieves a matching document among many (ordered)") | ||||||
|  |     fun firstByFieldsMatchOrdered() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByFieldsMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields returns null when no document matches") | ||||||
|  |     fun firstByFieldsNoMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByFieldsNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByContains retrieves a matching document") | ||||||
|  |     fun firstByContainsMatchOne() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByContainsMatchOne) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByContains retrieves a matching document among many") | ||||||
|  |     fun firstByContainsMatchMany() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByContainsMatchMany) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByContains retrieves a matching document among many (ordered)") | ||||||
|  |     fun firstByContainsMatchOrdered() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByContainsMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByContains returns null when no document matches") | ||||||
|  |     fun firstByContainsNoMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByContainsNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByJsonPath retrieves a matching document") | ||||||
|  |     fun firstByJsonPathMatchOne() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByJsonPathMatchOne) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByJsonPath retrieves a matching document among many") | ||||||
|  |     fun firstByJsonPathMatchMany() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByJsonPathMatchMany) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByJsonPath retrieves a matching document among many (ordered)") | ||||||
|  |     fun firstByJsonPathMatchOrdered() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByJsonPathMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByJsonPath returns null when no document matches") | ||||||
|  |     fun firstByJsonPathNoMatch() = | ||||||
|  |         PgDB().use(JsonFunctions::firstByJsonPathNoMatch) | ||||||
|  | } | ||||||
							
								
								
									
										112
									
								
								src/kotlinx/src/test/kotlin/integration/SQLiteJsonIT.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/kotlinx/src/test/kotlin/integration/SQLiteJsonIT.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,112 @@ | |||||||
|  | package solutions.bitbadger.documents.kotlinx.tests.integration | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.DisplayName | ||||||
|  | import org.junit.jupiter.api.assertThrows | ||||||
|  | import solutions.bitbadger.documents.DocumentException | ||||||
|  | import kotlin.test.Test | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * SQLite integration tests for the `Json` object / `json*` connection extension functions | ||||||
|  |  */ | ||||||
|  | @DisplayName("KotlinX | SQLite: Json") | ||||||
|  | class SQLiteJsonIT { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("all retrieves all documents") | ||||||
|  |     fun allDefault() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::allDefault) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("all succeeds with an empty table") | ||||||
|  |     fun allEmpty() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::allEmpty) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byId retrieves a document via a string ID") | ||||||
|  |     fun byIdString() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byIdString) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byId retrieves a document via a numeric ID") | ||||||
|  |     fun byIdNumber() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byIdNumber) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byId returns null when a matching ID is not found") | ||||||
|  |     fun byIdNotFound() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byIdNotFound) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves matching documents") | ||||||
|  |     fun byFieldsMatch() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byFieldsMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves ordered matching documents") | ||||||
|  |     fun byFieldsMatchOrdered() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byFieldsMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves matching documents with a numeric IN clause") | ||||||
|  |     fun byFieldsMatchNumIn() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byFieldsMatchNumIn) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields succeeds when no documents match") | ||||||
|  |     fun byFieldsNoMatch() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byFieldsNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields retrieves matching documents with an IN_ARRAY comparison") | ||||||
|  |     fun byFieldsMatchInArray() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byFieldsMatchInArray) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byFields succeeds when no documents match an IN_ARRAY comparison") | ||||||
|  |     fun byFieldsNoMatchInArray() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::byFieldsNoMatchInArray) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byContains fails") | ||||||
|  |     fun byContainsFails() { | ||||||
|  |         assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::byContainsMatch) } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("byJsonPath fails") | ||||||
|  |     fun byJsonPathFails() { | ||||||
|  |         assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::byJsonPathMatch) } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields retrieves a matching document") | ||||||
|  |     fun firstByFieldsMatchOne() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::firstByFieldsMatchOne) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields retrieves a matching document among many") | ||||||
|  |     fun firstByFieldsMatchMany() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::firstByFieldsMatchMany) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields retrieves a matching document among many (ordered)") | ||||||
|  |     fun firstByFieldsMatchOrdered() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::firstByFieldsMatchOrdered) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByFields returns null when no document matches") | ||||||
|  |     fun firstByFieldsNoMatch() = | ||||||
|  |         SQLiteDB().use(JsonFunctions::firstByFieldsNoMatch) | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByContains fails") | ||||||
|  |     fun firstByContainsFails() { | ||||||
|  |         assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::firstByContainsMatchOne) } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DisplayName("firstByJsonPath fails") | ||||||
|  |     fun firstByJsonPathFails() { | ||||||
|  |         assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::firstByJsonPathMatchOne) } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user