Initial Development #1

Merged
danieljsummers merged 88 commits from v1-rc into main 2025-04-16 01:29:20 +00:00
37 changed files with 487 additions and 372 deletions
Showing only changes of commit 5bcbc5cffc - Show all commits

View File

@ -2,7 +2,6 @@ package solutions.bitbadger.documents.common
import java.sql.Connection import java.sql.Connection
import java.sql.DriverManager import java.sql.DriverManager
import kotlin.jvm.Throws
/** /**
* Configuration for the document library * Configuration for the document library

View File

@ -71,18 +71,6 @@
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
<configuration>
<compilerPlugins>
<plugin>kotlinx-serialization</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-serialization</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>

View File

@ -1,11 +1,8 @@
@file:JvmName("ConnExt")
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.Custom import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.DocumentIndex
import solutions.bitbadger.documents.common.Field
import solutions.bitbadger.documents.common.FieldMatch
import solutions.bitbadger.documents.common.Parameter
import solutions.bitbadger.documents.java.*
import java.sql.Connection import java.sql.Connection
import java.sql.ResultSet import java.sql.ResultSet
@ -16,24 +13,32 @@ import java.sql.ResultSet
* *
* @param query The query to retrieve the results * @param query The query to retrieve the results
* @param parameters Parameters to use for the query * @param parameters Parameters to use for the query
* @param clazz The class of the document to be returned
* @param mapFunc The mapping function between the document and the domain item * @param mapFunc The mapping function between the document and the domain item
* @return A list of results for the given query * @return A list of results for the given query
*/ */
inline fun <reified TDoc> Connection.customList( fun <TDoc> Connection.customList(
query: String, parameters: Collection<Parameter<*>> = listOf(), noinline mapFunc: (ResultSet, Class<TDoc>) -> TDoc query: String,
) = Custom.list(query, parameters, this, mapFunc) parameters: Collection<Parameter<*>> = listOf(),
clazz: Class<TDoc>,
mapFunc: (ResultSet, Class<TDoc>) -> TDoc
) = Custom.list(query, parameters, clazz, this, mapFunc)
/** /**
* Execute a query that returns one or no results * Execute a query that returns one or no results
* *
* @param query The query to retrieve the results * @param query The query to retrieve the results
* @param parameters Parameters to use for the query * @param parameters Parameters to use for the query
* @param clazz The class of the document to be returned
* @param mapFunc The mapping function between the document and the domain item * @param mapFunc The mapping function between the document and the domain item
* @return The document if one matches the query, `null` otherwise * @return The document if one matches the query, `null` otherwise
*/ */
inline fun <reified TDoc> Connection.customSingle( fun <TDoc> Connection.customSingle(
query: String, parameters: Collection<Parameter<*>> = listOf(), noinline mapFunc: (ResultSet, Class<TDoc>) -> TDoc query: String,
) = Custom.single(query, parameters, this, mapFunc) parameters: Collection<Parameter<*>> = listOf(),
clazz: Class<TDoc>,
mapFunc: (ResultSet, Class<TDoc>) -> TDoc
) = Custom.single(query, parameters, clazz, this, mapFunc)
/** /**
* Execute a query that returns no results * Execute a query that returns no results
@ -49,14 +54,16 @@ fun Connection.customNonQuery(query: String, parameters: Collection<Parameter<*>
* *
* @param query The query to retrieve the result * @param query The query to retrieve the result
* @param parameters Parameters to use for the query * @param parameters Parameters to use for the query
* @param clazz The class of the document to be returned
* @param mapFunc The mapping function between the document and the domain item * @param mapFunc The mapping function between the document and the domain item
* @return The scalar value from the query * @return The scalar value from the query
*/ */
inline fun <reified T : Any> Connection.customScalar( fun <T : Any> Connection.customScalar(
query: String, query: String,
parameters: Collection<Parameter<*>> = listOf(), parameters: Collection<Parameter<*>> = listOf(),
noinline mapFunc: (ResultSet, Class<T>) -> T clazz: Class<T>,
) = Custom.scalar(query, parameters, this, mapFunc) mapFunc: (ResultSet, Class<T>) -> T
) = Custom.scalar(query, parameters, clazz, this, mapFunc)
// ~~~ DEFINITION QUERIES ~~~ // ~~~ DEFINITION QUERIES ~~~
@ -66,7 +73,7 @@ inline fun <reified T : Any> Connection.customScalar(
* @param tableName The table whose existence should be ensured (may include schema) * @param tableName The table whose existence should be ensured (may include schema)
*/ */
fun Connection.ensureTable(tableName: String) = fun Connection.ensureTable(tableName: String) =
solutions.bitbadger.documents.java.Definition.ensureTable(tableName, this) Definition.ensureTable(tableName, this)
/** /**
* Create an index on field(s) within documents in the specified table if necessary * Create an index on field(s) within documents in the specified table if necessary
@ -76,7 +83,7 @@ fun Connection.ensureTable(tableName: String) =
* @param fields One or more fields to be indexed< * @param fields One or more fields to be indexed<
*/ */
fun Connection.ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) = fun Connection.ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) =
solutions.bitbadger.documents.java.Definition.ensureFieldIndex(tableName, indexName, fields, this) Definition.ensureFieldIndex(tableName, indexName, fields, this)
/** /**
* Create a document index on a table (PostgreSQL only) * Create a document index on a table (PostgreSQL only)
@ -85,8 +92,9 @@ fun Connection.ensureFieldIndex(tableName: String, indexName: String, fields: Co
* @param indexType The type of index to ensure * @param indexType The type of index to ensure
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
fun Connection.ensureDocumentIndex(tableName: String, indexType: DocumentIndex) = fun Connection.ensureDocumentIndex(tableName: String, indexType: DocumentIndex) =
solutions.bitbadger.documents.java.Definition.ensureDocumentIndex(tableName, indexType, this) Definition.ensureDocumentIndex(tableName, indexType, this)
// ~~~ DOCUMENT MANIPULATION QUERIES ~~~ // ~~~ DOCUMENT MANIPULATION QUERIES ~~~
@ -96,7 +104,7 @@ fun Connection.ensureDocumentIndex(tableName: String, indexType: DocumentIndex)
* @param tableName The table into which the document should be inserted (may include schema) * @param tableName The table into which the document should be inserted (may include schema)
* @param document The document to be inserted * @param document The document to be inserted
*/ */
inline fun <reified TDoc> Connection.insert(tableName: String, document: TDoc) = fun <TDoc> Connection.insert(tableName: String, document: TDoc) =
Document.insert(tableName, document, this) Document.insert(tableName, document, this)
/** /**
@ -105,7 +113,7 @@ inline fun <reified TDoc> Connection.insert(tableName: String, document: TDoc) =
* @param tableName The table in which the document should be saved (may include schema) * @param tableName The table in which the document should be saved (may include schema)
* @param document The document to be saved * @param document The document to be saved
*/ */
inline fun <reified TDoc> Connection.save(tableName: String, document: TDoc) = fun <TDoc> Connection.save(tableName: String, document: TDoc) =
Document.save(tableName, document, this) Document.save(tableName, document, this)
/** /**
@ -115,7 +123,7 @@ inline fun <reified TDoc> Connection.save(tableName: String, document: TDoc) =
* @param docId The ID of the document to be replaced * @param docId The ID of the document to be replaced
* @param document The document to be replaced * @param document The document to be replaced
*/ */
inline fun <TKey, reified TDoc> Connection.update(tableName: String, docId: TKey, document: TDoc) = fun <TKey, TDoc> Connection.update(tableName: String, docId: TKey, document: TDoc) =
Document.update(tableName, docId, document, this) Document.update(tableName, docId, document, this)
// ~~~ DOCUMENT COUNT QUERIES ~~~ // ~~~ DOCUMENT COUNT QUERIES ~~~
@ -148,7 +156,8 @@ fun Connection.countByFields(tableName: String, fields: Collection<Field<*>>, ho
* @return A count of the matching documents in the table * @return A count of the matching documents in the table
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> Connection.countByContains(tableName: String, criteria: TContains) = @Throws(DocumentException::class)
fun <TContains> Connection.countByContains(tableName: String, criteria: TContains) =
Count.byContains(tableName, criteria, this) Count.byContains(tableName, criteria, this)
/** /**
@ -159,6 +168,7 @@ inline fun <reified TContains> Connection.countByContains(tableName: String, cri
* @return A count of the matching documents in the table * @return A count of the matching documents in the table
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
fun Connection.countByJsonPath(tableName: String, path: String) = fun Connection.countByJsonPath(tableName: String, path: String) =
Count.byJsonPath(tableName, path, this) Count.byJsonPath(tableName, path, this)
@ -193,7 +203,8 @@ fun Connection.existsByFields(tableName: String, fields: Collection<Field<*>>, h
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> Connection.existsByContains(tableName: String, criteria: TContains) = @Throws(DocumentException::class)
fun <TContains> Connection.existsByContains(tableName: String, criteria: TContains) =
Exists.byContains(tableName, criteria, this) Exists.byContains(tableName, criteria, this)
/** /**
@ -204,6 +215,7 @@ inline fun <reified TContains> Connection.existsByContains(tableName: String, cr
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
fun Connection.existsByJsonPath(tableName: String, path: String) = fun Connection.existsByJsonPath(tableName: String, path: String) =
Exists.byJsonPath(tableName, path, this) Exists.byJsonPath(tableName, path, this)
@ -213,119 +225,145 @@ fun Connection.existsByJsonPath(tableName: String, path: String) =
* 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
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents from the given table * @return A list of documents from the given table
*/ */
inline fun <reified TDoc> Connection.findAll(tableName: String, orderBy: Collection<Field<*>>? = null) = @JvmOverloads
solutions.bitbadger.documents.java.Find.all<TDoc>(tableName, orderBy, this) fun <TDoc> Connection.findAll(tableName: String, clazz: Class<TDoc>, orderBy: Collection<Field<*>>? = null) =
Find.all(tableName, clazz, orderBy, this)
/** /**
* Retrieve a document by its ID * Retrieve a document by its ID
* *
* @param tableName The table from which the document should be retrieved * @param tableName The table from which the document should be retrieved
* @param docId The ID of the document to retrieve * @param docId The ID of the document to retrieve
* @param clazz The class of the document to be returned
* @return The document if it is found, `null` otherwise * @return The document if it is found, `null` otherwise
*/ */
inline fun <TKey, reified TDoc> Connection.findById(tableName: String, docId: TKey) = fun <TKey, TDoc> Connection.findById(tableName: String, docId: TKey, clazz: Class<TDoc>) =
solutions.bitbadger.documents.java.Find.byId<TKey, TDoc>(tableName, docId, this) Find.byId(tableName, docId, clazz, this)
/** /**
* Retrieve documents using a field comparison, ordering results by the optional given fields * Retrieve documents using a field comparison, ordering results by the optional given fields
* *
* @param tableName The table from which the document should be retrieved * @param tableName The table from which the document should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents matching the field comparison * @return A list of documents matching the field comparison
*/ */
inline fun <reified TDoc> Connection.findByFields( @JvmOverloads
fun <TDoc> Connection.findByFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
solutions.bitbadger.documents.java.Find.byFields<TDoc>(tableName, fields, howMatched, orderBy, this) Find.byFields(tableName, fields, clazz, howMatched, orderBy, this)
/** /**
* Retrieve documents using a JSON containment query, ordering results by the optional given fields (PostgreSQL only) * Retrieve documents using a JSON containment query, ordering results by the optional given fields (PostgreSQL only)
* *
* @param tableName The name of the table in which document existence should be checked * @param tableName The name of the table in which document existence should be checked
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents matching the JSON containment query * @return A list of documents matching the JSON containment query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> Connection.findByContains( @Throws(DocumentException::class)
@JvmOverloads
fun <TDoc, TContains> Connection.findByContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
solutions.bitbadger.documents.java.Find.byContains<TDoc, TContains>(tableName, criteria, orderBy, this) Find.byContains(tableName, criteria, clazz, orderBy, this)
/** /**
* Retrieve documents using a JSON Path match query, ordering results by the optional given fields (PostgreSQL only) * Retrieve documents using a JSON Path match query, ordering results by the optional given fields (PostgreSQL only)
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents matching the JSON Path match query * @return A list of documents matching the JSON Path match query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> Connection.findByJsonPath( @Throws(DocumentException::class)
@JvmOverloads
fun <TDoc> Connection.findByJsonPath(
tableName: String, tableName: String,
path: String, path: String,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
solutions.bitbadger.documents.java.Find.byJsonPath<TDoc>(tableName, path, orderBy, this) Find.byJsonPath(tableName, path, clazz, orderBy, this)
/** /**
* Retrieve the first document using a field comparison and optional ordering fields * Retrieve the first document using a field comparison and optional ordering fields
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) * @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 orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return The first document matching the field comparison, or `null` if no matches are found * @return The first document matching the field comparison, or `null` if no matches are found
*/ */
inline fun <reified TDoc> Connection.findFirstByFields( @Throws(DocumentException::class)
@JvmOverloads
fun <TDoc> Connection.findFirstByFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
solutions.bitbadger.documents.java.Find.firstByFields<TDoc>(tableName, fields, howMatched, orderBy, this) Find.firstByFields(tableName, fields, clazz, howMatched, orderBy, this)
/** /**
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only) * 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 tableName The table from which documents should be retrieved
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return The first document matching the JSON containment query, or `null` if no matches are found * @return The first document matching the JSON containment query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> Connection.findFirstByContains( @Throws(DocumentException::class)
@JvmOverloads
fun <TDoc, TContains> Connection.findFirstByContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
solutions.bitbadger.documents.java.Find.firstByContains<TDoc, TContains>(tableName, criteria, orderBy, this) Find.firstByContains(tableName, criteria, clazz, orderBy, this)
/** /**
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only) * 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 tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return The first document matching the JSON Path match query, or `null` if no matches are found * @return The first document matching the JSON Path match query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> Connection.findFirstByJsonPath( @Throws(DocumentException::class)
@JvmOverloads
fun <TDoc> Connection.findFirstByJsonPath(
tableName: String, tableName: String,
path: String, path: String,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
solutions.bitbadger.documents.java.Find.firstByJsonPath<TDoc>(tableName, path, orderBy, this) Find.firstByJsonPath(tableName, path, clazz, orderBy, this)
// ~~~ DOCUMENT PATCH (PARTIAL UPDATE) QUERIES ~~~ // ~~~ DOCUMENT PATCH (PARTIAL UPDATE) QUERIES ~~~
@ -336,7 +374,7 @@ inline fun <reified TDoc> Connection.findFirstByJsonPath(
* @param docId The ID of the document to be patched * @param docId The ID of the document to be patched
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
*/ */
inline fun <TKey, reified TPatch> Connection.patchById(tableName: String, docId: TKey, patch: TPatch) = fun <TKey, TPatch> Connection.patchById(tableName: String, docId: TKey, patch: TPatch) =
Patch.byId(tableName, docId, patch, this) Patch.byId(tableName, docId, patch, this)
/** /**
@ -347,7 +385,7 @@ inline fun <TKey, reified TPatch> Connection.patchById(tableName: String, docId:
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
*/ */
inline fun <reified TPatch> Connection.patchByFields( fun <TPatch> Connection.patchByFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
patch: TPatch, patch: TPatch,
@ -363,7 +401,8 @@ inline fun <reified TPatch> Connection.patchByFields(
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains, reified TPatch> Connection.patchByContains( @Throws(DocumentException::class)
fun <TContains, TPatch> Connection.patchByContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
patch: TPatch patch: TPatch
@ -378,7 +417,8 @@ inline fun <reified TContains, reified TPatch> Connection.patchByContains(
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TPatch> Connection.patchByJsonPath(tableName: String, path: String, patch: TPatch) = @Throws(DocumentException::class)
fun <TPatch> Connection.patchByJsonPath(tableName: String, path: String, patch: TPatch) =
Patch.byJsonPath(tableName, path, patch, this) Patch.byJsonPath(tableName, path, patch, this)
// ~~~ DOCUMENT FIELD REMOVAL QUERIES ~~~ // ~~~ DOCUMENT FIELD REMOVAL QUERIES ~~~
@ -417,7 +457,8 @@ fun Connection.removeFieldsByFields(
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> Connection.removeFieldsByContains( @Throws(DocumentException::class)
fun <TContains> Connection.removeFieldsByContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
toRemove: Collection<String> toRemove: Collection<String>
@ -432,6 +473,7 @@ inline fun <reified TContains> Connection.removeFieldsByContains(
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
fun Connection.removeFieldsByJsonPath(tableName: String, path: String, toRemove: Collection<String>) = fun Connection.removeFieldsByJsonPath(tableName: String, path: String, toRemove: Collection<String>) =
RemoveFields.byJsonPath(tableName, path, toRemove, this) RemoveFields.byJsonPath(tableName, path, toRemove, this)
@ -463,7 +505,8 @@ fun Connection.deleteByFields(tableName: String, fields: Collection<Field<*>>, h
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> Connection.deleteByContains(tableName: String, criteria: TContains) = @Throws(DocumentException::class)
fun <TContains> Connection.deleteByContains(tableName: String, criteria: TContains) =
Delete.byContains(tableName, criteria, this) Delete.byContains(tableName, criteria, this)
/** /**

View File

@ -1,10 +1,7 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.Results import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.query.Count
import solutions.bitbadger.documents.common.FieldMatch
import solutions.bitbadger.documents.common.Parameter
import solutions.bitbadger.documents.common.ParameterType
import java.sql.Connection import java.sql.Connection
/** /**
@ -21,7 +18,7 @@ object Count {
*/ */
@JvmStatic @JvmStatic
fun all(tableName: String, conn: Connection) = fun all(tableName: String, conn: Connection) =
conn.customScalar(all(tableName), mapFunc = Results::toCount) conn.customScalar(Count.all(tableName), listOf(), Long::class.java, Results::toCount)
/** /**
* Count all documents in the table * Count all documents in the table
@ -52,8 +49,9 @@ object Count {
): Long { ): Long {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
return conn.customScalar( return conn.customScalar(
byFields(tableName, named, howMatched), Count.byFields(tableName, named, howMatched),
Parameters.addFields(named), Parameters.addFields(named),
Long::class.java,
Results::toCount Results::toCount
) )
} }
@ -81,8 +79,13 @@ object Count {
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@JvmStatic @JvmStatic
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) = fun <TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
conn.customScalar(Count.byContains(tableName), listOf(Parameters.json(":criteria", criteria)), Results::toCount) conn.customScalar(
Count.byContains(tableName),
listOf(Parameters.json(":criteria", criteria)),
Long::class.java,
Results::toCount
)
/** /**
* Count documents using a JSON containment query (PostgreSQL only) * Count documents using a JSON containment query (PostgreSQL only)
@ -93,7 +96,7 @@ object Count {
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@JvmStatic @JvmStatic
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) = fun <TContains> byContains(tableName: String, criteria: TContains) =
Configuration.dbConn().use { byContains(tableName, criteria, it) } Configuration.dbConn().use { byContains(tableName, criteria, it) }
/** /**
@ -110,6 +113,7 @@ object Count {
conn.customScalar( conn.customScalar(
Count.byJsonPath(tableName), Count.byJsonPath(tableName),
listOf(Parameter(":path", ParameterType.STRING, path)), listOf(Parameter(":path", ParameterType.STRING, path)),
Long::class.java,
Results::toCount Results::toCount
) )

View File

@ -1,6 +1,9 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.common.Configuration
import solutions.bitbadger.documents.common.DocumentException
import solutions.bitbadger.documents.common.DocumentIndex import solutions.bitbadger.documents.common.DocumentIndex
import solutions.bitbadger.documents.common.query.Definition
import java.sql.Connection import java.sql.Connection
/** /**
@ -14,6 +17,7 @@ object Definition {
* @param tableName The table whose existence should be ensured (may include schema) * @param tableName The table whose existence should be ensured (may include schema)
* @param conn The connection on which the query should be executed * @param conn The connection on which the query should be executed
*/ */
@JvmStatic
fun ensureTable(tableName: String, conn: Connection) = fun ensureTable(tableName: String, conn: Connection) =
Configuration.dialect("ensure $tableName exists").let { Configuration.dialect("ensure $tableName exists").let {
conn.customNonQuery(Definition.ensureTable(tableName, it)) conn.customNonQuery(Definition.ensureTable(tableName, it))
@ -25,6 +29,7 @@ object Definition {
* *
* @param tableName The table whose existence should be ensured (may include schema) * @param tableName The table whose existence should be ensured (may include schema)
*/ */
@JvmStatic
fun ensureTable(tableName: String) = fun ensureTable(tableName: String) =
Configuration.dbConn().use { ensureTable(tableName, it) } Configuration.dbConn().use { ensureTable(tableName, it) }
@ -33,9 +38,10 @@ object Definition {
* *
* @param tableName The table to be indexed (may include schema) * @param tableName The table to be indexed (may include schema)
* @param indexName The name of the index to create * @param indexName The name of the index to create
* @param fields One or more fields to be indexed< * @param fields One or more fields to be indexed
* @param conn The connection on which the query should be executed * @param conn The connection on which the query should be executed
*/ */
@JvmStatic
fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>, conn: Connection) = fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>, conn: Connection) =
conn.customNonQuery(Definition.ensureIndexOn(tableName, indexName, fields)) conn.customNonQuery(Definition.ensureIndexOn(tableName, indexName, fields))
@ -44,8 +50,9 @@ object Definition {
* *
* @param tableName The table to be indexed (may include schema) * @param tableName The table to be indexed (may include schema)
* @param indexName The name of the index to create * @param indexName The name of the index to create
* @param fields One or more fields to be indexed< * @param fields One or more fields to be indexed
*/ */
@JvmStatic
fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) = fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) =
Configuration.dbConn().use { ensureFieldIndex(tableName, indexName, fields, it) } Configuration.dbConn().use { ensureFieldIndex(tableName, indexName, fields, it) }
@ -57,6 +64,8 @@ object Definition {
* @param conn The connection on which the query should be executed * @param conn The connection on which the query should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex, conn: Connection) = fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex, conn: Connection) =
conn.customNonQuery(Definition.ensureDocumentIndexOn(tableName, indexType)) conn.customNonQuery(Definition.ensureDocumentIndexOn(tableName, indexType))
@ -67,6 +76,8 @@ object Definition {
* @param indexType The type of index to ensure * @param indexType The type of index to ensure
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex) = fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex) =
Configuration.dbConn().use { ensureDocumentIndex(tableName, indexType, it) } Configuration.dbConn().use { ensureDocumentIndex(tableName, indexType, it) }
} }

View File

@ -1,9 +1,7 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.FieldMatch import solutions.bitbadger.documents.common.query.Delete
import solutions.bitbadger.documents.common.Parameter
import solutions.bitbadger.documents.common.ParameterType
import java.sql.Connection import java.sql.Connection
/** /**
@ -18,9 +16,10 @@ object Delete {
* @param docId The ID of the document to be deleted * @param docId The ID of the document to be deleted
* @param conn The connection on which the deletion should be executed * @param conn The connection on which the deletion should be executed
*/ */
@JvmStatic
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) = fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
conn.customNonQuery( conn.customNonQuery(
byId(tableName, docId), Delete.byId(tableName, docId),
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))) Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id")))
) )
@ -30,6 +29,7 @@ object Delete {
* @param tableName The name of the table from which documents should be deleted * @param tableName The name of the table from which documents should be deleted
* @param docId The ID of the document to be deleted * @param docId The ID of the document to be deleted
*/ */
@JvmStatic
fun <TKey> byId(tableName: String, docId: TKey) = fun <TKey> byId(tableName: String, docId: TKey) =
Configuration.dbConn().use { byId(tableName, docId, it) } Configuration.dbConn().use { byId(tableName, docId, it) }
@ -41,9 +41,11 @@ object Delete {
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param conn The connection on which the deletion should be executed * @param conn The connection on which the deletion should be executed
*/ */
@JvmStatic
@JvmOverloads
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) { fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
conn.customNonQuery(byFields(tableName, named, howMatched), Parameters.addFields(named)) conn.customNonQuery(Delete.byFields(tableName, named, howMatched), Parameters.addFields(named))
} }
/** /**
@ -53,6 +55,8 @@ object Delete {
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
*/ */
@JvmStatic
@JvmOverloads
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) = fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) } Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
@ -64,7 +68,9 @@ object Delete {
* @param conn The connection on which the deletion should be executed * @param conn The connection on which the deletion should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) = @Throws(DocumentException::class)
@JvmStatic
fun <TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
conn.customNonQuery(Delete.byContains(tableName), listOf(Parameters.json(":criteria", criteria))) conn.customNonQuery(Delete.byContains(tableName), listOf(Parameters.json(":criteria", criteria)))
/** /**
@ -74,7 +80,9 @@ object Delete {
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) = @Throws(DocumentException::class)
@JvmStatic
fun <TContains> byContains(tableName: String, criteria: TContains) =
Configuration.dbConn().use { byContains(tableName, criteria, it) } Configuration.dbConn().use { byContains(tableName, criteria, it) }
/** /**
@ -85,6 +93,8 @@ object Delete {
* @param conn The connection on which the deletion should be executed * @param conn The connection on which the deletion should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun byJsonPath(tableName: String, path: String, conn: Connection) = fun byJsonPath(tableName: String, path: String, conn: Connection) =
conn.customNonQuery(Delete.byJsonPath(tableName), listOf(Parameter(":path", ParameterType.STRING, path))) conn.customNonQuery(Delete.byJsonPath(tableName), listOf(Parameter(":path", ParameterType.STRING, path)))
@ -95,6 +105,8 @@ object Delete {
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun byJsonPath(tableName: String, path: String) = fun byJsonPath(tableName: String, path: String) =
Configuration.dbConn().use { byJsonPath(tableName, path, it) } Configuration.dbConn().use { byJsonPath(tableName, path, it) }
} }

View File

@ -1,10 +1,7 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.Results import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.query.Exists
import solutions.bitbadger.documents.common.FieldMatch
import solutions.bitbadger.documents.common.Parameter
import solutions.bitbadger.documents.common.ParameterType
import java.sql.Connection import java.sql.Connection
/** /**
@ -20,10 +17,12 @@ object Exists {
* @param conn The connection on which the existence check should be executed * @param conn The connection on which the existence check should be executed
* @return True if the document exists, false if not * @return True if the document exists, false if not
*/ */
@JvmStatic
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) = fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
conn.customScalar( conn.customScalar(
byId(tableName, docId), Exists.byId(tableName, docId),
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))), Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))),
Boolean::class.java,
Results::toExists Results::toExists
) )
@ -34,6 +33,7 @@ object Exists {
* @param docId The ID of the document to be checked * @param docId The ID of the document to be checked
* @return True if the document exists, false if not * @return True if the document exists, false if not
*/ */
@JvmStatic
fun <TKey> byId(tableName: String, docId: TKey) = fun <TKey> byId(tableName: String, docId: TKey) =
Configuration.dbConn().use { byId(tableName, docId, it) } Configuration.dbConn().use { byId(tableName, docId, it) }
@ -46,6 +46,8 @@ object Exists {
* @param conn The connection on which the existence check should be executed * @param conn The connection on which the existence check should be executed
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
*/ */
@JvmStatic
@JvmOverloads
fun byFields( fun byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
@ -54,8 +56,9 @@ object Exists {
): Boolean { ): Boolean {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
return conn.customScalar( return conn.customScalar(
byFields(tableName, named, howMatched), Exists.byFields(tableName, named, howMatched),
Parameters.addFields(named), Parameters.addFields(named),
Boolean::class.java,
Results::toExists Results::toExists
) )
} }
@ -68,6 +71,8 @@ object Exists {
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
*/ */
@JvmStatic
@JvmOverloads
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) = fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) } Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
@ -80,10 +85,13 @@ object Exists {
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) = @Throws(DocumentException::class)
@JvmStatic
fun <TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
conn.customScalar( conn.customScalar(
Exists.byContains(tableName), Exists.byContains(tableName),
listOf(Parameters.json(":criteria", criteria)), listOf(Parameters.json(":criteria", criteria)),
Boolean::class.java,
Results::toExists Results::toExists
) )
@ -95,7 +103,9 @@ object Exists {
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) = @Throws(DocumentException::class)
@JvmStatic
fun <TContains> byContains(tableName: String, criteria: TContains) =
Configuration.dbConn().use { byContains(tableName, criteria, it) } Configuration.dbConn().use { byContains(tableName, criteria, it) }
/** /**
@ -107,10 +117,13 @@ object Exists {
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun byJsonPath(tableName: String, path: String, conn: Connection) = fun byJsonPath(tableName: String, path: String, conn: Connection) =
conn.customScalar( conn.customScalar(
Exists.byJsonPath(tableName), Exists.byJsonPath(tableName),
listOf(Parameter(":path", ParameterType.STRING, path)), listOf(Parameter(":path", ParameterType.STRING, path)),
Boolean::class.java,
Results::toExists Results::toExists
) )
@ -122,6 +135,8 @@ object Exists {
* @return True if any matching documents exist, false if not * @return True if any matching documents exist, false if not
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun byJsonPath(tableName: String, path: String) = fun byJsonPath(tableName: String, path: String) =
Configuration.dbConn().use { byJsonPath(tableName, path, it) } Configuration.dbConn().use { byJsonPath(tableName, path, it) }
} }

View File

@ -1,12 +1,9 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.Results import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.query.Find
import solutions.bitbadger.documents.common.FieldMatch
import solutions.bitbadger.documents.common.Parameter
import solutions.bitbadger.documents.common.ParameterType
import java.sql.Connection
import solutions.bitbadger.documents.common.query.orderBy import solutions.bitbadger.documents.common.query.orderBy
import java.sql.Connection
/** /**
* Functions to find and retrieve documents * Functions to find and retrieve documents
@ -17,45 +14,55 @@ object Find {
* 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
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @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 * @param conn The connection over which documents should be retrieved
* @return A list of documents from the given table * @return A list of documents from the given table
*/ */
inline fun <reified TDoc> all(tableName: String, orderBy: Collection<Field<*>>? = null, conn: Connection) = @JvmStatic
conn.customList<TDoc>(all(tableName) + (orderBy?.let(::orderBy) ?: ""), mapFunc = Results::fromData) fun <TDoc> all(tableName: String, clazz: Class<TDoc>, orderBy: Collection<Field<*>>? = null, conn: Connection) =
conn.customList(Find.all(tableName) + (orderBy?.let(::orderBy) ?: ""), listOf(), clazz, Results::fromData)
/** /**
* Retrieve all documents in the given table * Retrieve all documents in the given table
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents from the given table * @return A list of documents from the given table
*/ */
inline fun <reified TDoc> all(tableName: String, orderBy: Collection<Field<*>>? = null) = @JvmStatic
Configuration.dbConn().use { all<TDoc>(tableName, orderBy, it) } @JvmOverloads
fun <TDoc> all(tableName: String, clazz: Class<TDoc>, orderBy: Collection<Field<*>>? = null) =
Configuration.dbConn().use { all(tableName, clazz, orderBy, it) }
/** /**
* Retrieve all documents in the given table * Retrieve all documents in the given table
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param clazz The class of the document to be returned
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return A list of documents from the given table * @return A list of documents from the given table
*/ */
inline fun <reified TDoc> all(tableName: String, conn: Connection) = @JvmStatic
all<TDoc>(tableName, null, conn) fun <TDoc> all(tableName: String, clazz: Class<TDoc>, conn: Connection) =
all(tableName, clazz, null, conn)
/** /**
* Retrieve a document by its ID * Retrieve a document by its ID
* *
* @param tableName The table from which the document should be retrieved * @param tableName The table from which the document should be retrieved
* @param docId The ID of the document to retrieve * @param docId The ID of the document to retrieve
* @param clazz The class of the document to be returned
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return The document if it is found, `null` otherwise * @return The document if it is found, `null` otherwise
*/ */
inline fun <TKey, reified TDoc> byId(tableName: String, docId: TKey, conn: Connection) = @JvmStatic
conn.customSingle<TDoc>( fun <TKey, TDoc> byId(tableName: String, docId: TKey, clazz: Class<TDoc>, conn: Connection) =
byId(tableName, docId), conn.customSingle(
Find.byId(tableName, docId),
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))), Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))),
clazz,
Results::fromData Results::fromData
) )
@ -64,32 +71,38 @@ object Find {
* *
* @param tableName The table from which the document should be retrieved * @param tableName The table from which the document should be retrieved
* @param docId The ID of the document to retrieve * @param docId The ID of the document to retrieve
* @param clazz The class of the document to be returned
* @return The document if it is found, `null` otherwise * @return The document if it is found, `null` otherwise
*/ */
inline fun <TKey, reified TDoc> byId(tableName: String, docId: TKey) = @JvmStatic
Configuration.dbConn().use { byId<TKey, TDoc>(tableName, docId, it) } fun <TKey, TDoc> byId(tableName: String, docId: TKey, clazz: Class<TDoc>) =
Configuration.dbConn().use { byId(tableName, docId, clazz, it) }
/** /**
* Retrieve documents using a field comparison, ordering results by the given fields * Retrieve documents using a field comparison, ordering results by the given fields
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @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 * @param conn The connection over which documents should be retrieved
* @return A list of documents matching the field comparison * @return A list of documents matching the field comparison
*/ */
inline fun <reified TDoc> byFields( @JvmStatic
fun <TDoc> byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
orderBy: Collection<Field<*>>? = null, orderBy: Collection<Field<*>>? = null,
conn: Connection conn: Connection
): List<TDoc> { ): List<TDoc> {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
return conn.customList<TDoc>( return conn.customList(
byFields(tableName, named, howMatched) + (orderBy?.let(::orderBy) ?: ""), Find.byFields(tableName, named, howMatched) + (orderBy?.let(::orderBy) ?: ""),
Parameters.addFields(named), Parameters.addFields(named),
clazz,
Results::fromData Results::fromData
) )
} }
@ -99,69 +112,66 @@ object Find {
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents matching the field comparison * @return A list of documents matching the field comparison
*/ */
inline fun <reified TDoc> byFields( @JvmStatic
@JvmOverloads
fun <TDoc> byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
Configuration.dbConn().use { byFields<TDoc>(tableName, fields, howMatched, orderBy, it) } Configuration.dbConn().use { byFields(tableName, fields, clazz, howMatched, orderBy, it) }
/** /**
* Retrieve documents using a field comparison * Retrieve documents using a field comparison
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return A list of documents matching the field comparison * @return A list of documents matching the field comparison
*/ */
inline fun <reified TDoc> byFields( @JvmStatic
fun <TDoc> byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
conn: Connection conn: Connection
) = ) =
byFields<TDoc>(tableName, fields, howMatched, null, conn) byFields(tableName, fields, clazz, howMatched, null, conn)
/**
* 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
* @return A list of documents matching the field comparison
*/
inline fun <reified TDoc> byFields(
tableName: String,
fields: Collection<Field<*>>,
howMatched: FieldMatch? = null
) =
Configuration.dbConn().use { byFields<TDoc>(tableName, fields, howMatched, null, it) }
/** /**
* 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)
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @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 * @param conn The connection over which documents should be retrieved
* @return A list of documents matching the JSON containment query * @return A list of documents matching the JSON containment query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> byContains( @Throws(DocumentException::class)
@JvmStatic
fun <TDoc, TContains> byContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null, orderBy: Collection<Field<*>>? = null,
conn: Connection conn: Connection
) = ) =
conn.customList<TDoc>( conn.customList(
Find.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""), Find.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
listOf(Parameters.json(":criteria", criteria)), listOf(Parameters.json(":criteria", criteria)),
clazz,
Results::fromData Results::fromData
) )
@ -170,59 +180,61 @@ object Find {
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents matching the JSON containment query * @return A list of documents matching the JSON containment query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> byContains( @Throws(DocumentException::class)
@JvmStatic
@JvmOverloads
fun <TDoc, TContains> byContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
Configuration.dbConn().use { byContains<TDoc, TContains>(tableName, criteria, orderBy, it) } Configuration.dbConn().use { byContains(tableName, criteria, clazz, orderBy, it) }
/** /**
* Retrieve documents using a JSON containment query (PostgreSQL only) * Retrieve documents using a JSON containment query (PostgreSQL only)
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return A list of documents matching the JSON containment query * @return A list of documents matching the JSON containment query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) = @Throws(DocumentException::class)
byContains<TDoc, TContains>(tableName, criteria, null, conn) @JvmStatic
fun <TDoc, TContains> byContains(tableName: String, criteria: TContains, clazz: Class<TDoc>, conn: Connection) =
/** byContains(tableName, criteria, clazz, null, conn)
* 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
* @return A list of documents matching the JSON containment query
* @throws DocumentException If called on a SQLite connection
*/
inline fun <reified TDoc, reified TContains> byContains(tableName: String, criteria: TContains) =
Configuration.dbConn().use { byContains<TDoc, TContains>(tableName, criteria, it) }
/** /**
* Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only) * 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 tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @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 * @param conn The connection over which documents should be retrieved
* @return A list of documents matching the JSON Path match query * @return A list of documents matching the JSON Path match query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> byJsonPath( @Throws(DocumentException::class)
@JvmStatic
fun <TDoc> byJsonPath(
tableName: String, tableName: String,
path: String, path: String,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null, orderBy: Collection<Field<*>>? = null,
conn: Connection conn: Connection
) = ) =
conn.customList<TDoc>( conn.customList(
byJsonPath(tableName) + (orderBy?.let(::orderBy) ?: ""), Find.byJsonPath(tableName) + (orderBy?.let(::orderBy) ?: ""),
listOf(Parameter(":path", ParameterType.STRING, path)), listOf(Parameter(":path", ParameterType.STRING, path)),
clazz,
Results::fromData Results::fromData
) )
@ -231,46 +243,57 @@ object Find {
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return A list of documents matching the JSON Path match query * @return A list of documents matching the JSON Path match query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) = @Throws(DocumentException::class)
Configuration.dbConn().use { byJsonPath<TDoc>(tableName, path, orderBy, it) } @JvmStatic
@JvmOverloads
fun <TDoc> byJsonPath(tableName: String, path: String, clazz: Class<TDoc>, orderBy: Collection<Field<*>>? = null) =
Configuration.dbConn().use { byJsonPath(tableName, path, clazz, orderBy, it) }
/** /**
* Retrieve documents using a JSON Path match query (PostgreSQL only) * Retrieve documents using a JSON Path match query (PostgreSQL only)
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return A list of documents matching the JSON Path match query * @return A list of documents matching the JSON Path match query
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> byJsonPath(tableName: String, path: String, conn: Connection) = @Throws(DocumentException::class)
byJsonPath<TDoc>(tableName, path, null, conn) @JvmStatic
fun <TDoc> byJsonPath(tableName: String, path: String, clazz: Class<TDoc>, conn: Connection) =
byJsonPath(tableName, path, clazz, null, conn)
/** /**
* Retrieve the first document using a field comparison and optional ordering fields * Retrieve the first document using a field comparison and optional ordering fields
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) * @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 orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return The first document matching the field comparison, or `null` if no matches are found * @return The first document matching the field comparison, or `null` if no matches are found
*/ */
inline fun <reified TDoc> firstByFields( @JvmStatic
fun <TDoc> firstByFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
orderBy: Collection<Field<*>>? = null, orderBy: Collection<Field<*>>? = null,
conn: Connection conn: Connection
): TDoc? { ): TDoc? {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
return conn.customSingle<TDoc>( return conn.customSingle(
byFields(tableName, named, howMatched) + (orderBy?.let(::orderBy) ?: ""), Find.byFields(tableName, named, howMatched) + (orderBy?.let(::orderBy) ?: ""),
Parameters.addFields(named), Parameters.addFields(named),
clazz,
Results::fromData Results::fromData
) )
} }
@ -280,34 +303,41 @@ object Find {
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) * @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 orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return The first document matching the field comparison, or `null` if no matches are found * @return The first document matching the field comparison, or `null` if no matches are found
*/ */
inline fun <reified TDoc> firstByFields( @JvmStatic
@JvmOverloads
fun <TDoc> firstByFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
orderBy: Collection<Field<*>>? = null orderBy: Collection<Field<*>>? = null
) = ) =
Configuration.dbConn().use { firstByFields<TDoc>(tableName, fields, howMatched, orderBy, it) } Configuration.dbConn().use { firstByFields(tableName, fields, clazz, howMatched, orderBy, it) }
/** /**
* Retrieve the first document using a field comparison * Retrieve the first document using a field comparison
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param fields The fields which should be compared * @param fields The fields which should be compared
* @param clazz The class of the document to be returned
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`) * @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return The first document matching the field comparison, or `null` if no matches are found * @return The first document matching the field comparison, or `null` if no matches are found
*/ */
inline fun <reified TDoc> firstByFields( @JvmStatic
fun <TDoc> firstByFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
clazz: Class<TDoc>,
howMatched: FieldMatch? = null, howMatched: FieldMatch? = null,
conn: Connection conn: Connection
) = ) =
firstByFields<TDoc>(tableName, fields, howMatched, null, conn) firstByFields(tableName, fields, clazz, howMatched, null, conn)
/** /**
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only) * Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only)
@ -319,15 +349,19 @@ object Find {
* @return The first document matching the JSON containment query, or `null` if no matches are found * @return The first document matching the JSON containment query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> firstByContains( @Throws(DocumentException::class)
@JvmStatic
fun <TDoc, TContains> firstByContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null, orderBy: Collection<Field<*>>? = null,
conn: Connection conn: Connection
) = ) =
conn.customSingle<TDoc>( conn.customSingle(
Find.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""), Find.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
listOf(Parameters.json(":criteria", criteria)), listOf(Parameters.json(":criteria", criteria)),
clazz,
Results::fromData Results::fromData
) )
@ -336,44 +370,66 @@ object Find {
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return The first document matching the JSON containment query, or `null` if no matches are found * @return The first document matching the JSON containment query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> firstByContains(tableName: String, criteria: TContains, conn: Connection) = @Throws(DocumentException::class)
firstByContains<TDoc, TContains>(tableName, criteria, null, conn) @JvmStatic
fun <TDoc, TContains> firstByContains(
tableName: String,
criteria: TContains,
clazz: Class<TDoc>,
conn: Connection
) =
firstByContains(tableName, criteria, clazz, null, conn)
/** /**
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only) * 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 tableName The table from which documents should be retrieved
* @param criteria The object for which JSON containment should be checked * @param criteria The object for which JSON containment should be checked
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return The first document matching the JSON containment query, or `null` if no matches are found * @return The first document matching the JSON containment query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc, reified TContains> firstByContains(tableName: String, criteria: TContains, orderBy: Collection<Field<*>>? = null) = @Throws(DocumentException::class)
Configuration.dbConn().use { firstByContains<TDoc, TContains>(tableName, criteria, orderBy, it) } @JvmStatic
@JvmOverloads
fun <TDoc, TContains> firstByContains(
tableName: String,
criteria: TContains,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null
) =
Configuration.dbConn().use { firstByContains(tableName, criteria, clazz, orderBy, it) }
/** /**
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only) * 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 tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @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 * @param conn The connection over which documents should be retrieved
* @return The first document matching the JSON Path match query, or `null` if no matches are found * @return The first document matching the JSON Path match query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> firstByJsonPath( @Throws(DocumentException::class)
@JvmStatic
fun <TDoc> firstByJsonPath(
tableName: String, tableName: String,
path: String, path: String,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null, orderBy: Collection<Field<*>>? = null,
conn: Connection conn: Connection
) = ) =
conn.customSingle<TDoc>( conn.customSingle(
byJsonPath(tableName) + (orderBy?.let(::orderBy) ?: ""), Find.byJsonPath(tableName) + (orderBy?.let(::orderBy) ?: ""),
listOf(Parameter(":path", ParameterType.STRING, path)), listOf(Parameter(":path", ParameterType.STRING, path)),
clazz,
Results::fromData Results::fromData
) )
@ -382,22 +438,34 @@ object Find {
* *
* @param tableName The table from which documents should be retrieved * @param tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param conn The connection over which documents should be retrieved * @param conn The connection over which documents should be retrieved
* @return The first document matching the JSON Path match query, or `null` if no matches are found * @return The first document matching the JSON Path match query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> firstByJsonPath(tableName: String, path: String, conn: Connection) = @Throws(DocumentException::class)
firstByJsonPath<TDoc>(tableName, path, null, conn) @JvmStatic
fun <TDoc> firstByJsonPath(tableName: String, path: String, clazz: Class<TDoc>, conn: Connection) =
firstByJsonPath(tableName, path, clazz, null, conn)
/** /**
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only) * 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 tableName The table from which documents should be retrieved
* @param path The JSON path comparison to match * @param path The JSON path comparison to match
* @param clazz The class of the document to be returned
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering) * @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
* @return The first document matching the JSON Path match query, or `null` if no matches are found * @return The first document matching the JSON Path match query, or `null` if no matches are found
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TDoc> firstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) = @Throws(DocumentException::class)
Configuration.dbConn().use { firstByJsonPath<TDoc>(tableName, path, orderBy, it) } @JvmStatic
@JvmOverloads
fun <TDoc> firstByJsonPath(
tableName: String,
path: String,
clazz: Class<TDoc>,
orderBy: Collection<Field<*>>? = null
) =
Configuration.dbConn().use { firstByJsonPath(tableName, path, clazz, orderBy, it) }
} }

View File

@ -1,9 +1,7 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.FieldMatch import solutions.bitbadger.documents.common.query.Patch
import solutions.bitbadger.documents.common.Parameter
import solutions.bitbadger.documents.common.ParameterType
import java.sql.Connection import java.sql.Connection
/** /**
@ -19,7 +17,8 @@ object Patch {
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
*/ */
inline fun <TKey, reified TPatch> byId(tableName: String, docId: TKey, patch: TPatch, conn: Connection) = @JvmStatic
fun <TKey, TPatch> byId(tableName: String, docId: TKey, patch: TPatch, conn: Connection) =
conn.customNonQuery( conn.customNonQuery(
Patch.byId(tableName, docId), Patch.byId(tableName, docId),
Parameters.addFields( Parameters.addFields(
@ -35,7 +34,8 @@ object Patch {
* @param docId The ID of the document to be patched * @param docId The ID of the document to be patched
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
*/ */
inline fun <TKey, reified TPatch> byId(tableName: String, docId: TKey, patch: TPatch) = @JvmStatic
fun <TKey, TPatch> byId(tableName: String, docId: TKey, patch: TPatch) =
Configuration.dbConn().use { byId(tableName, docId, patch, it) } Configuration.dbConn().use { byId(tableName, docId, patch, it) }
/** /**
@ -47,7 +47,8 @@ object Patch {
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
*/ */
inline fun <reified TPatch> byFields( @JvmStatic
fun <TPatch> byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
patch: TPatch, patch: TPatch,
@ -56,7 +57,7 @@ object Patch {
) { ) {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
conn.customNonQuery( conn.customNonQuery(
byFields(tableName, named, howMatched), Parameters.addFields( Patch.byFields(tableName, named, howMatched), Parameters.addFields(
named, named,
mutableListOf(Parameters.json(":data", patch)) mutableListOf(Parameters.json(":data", patch))
) )
@ -71,7 +72,9 @@ object Patch {
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
*/ */
inline fun <reified TPatch> byFields( @JvmStatic
@JvmOverloads
fun <TPatch> byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
patch: TPatch, patch: TPatch,
@ -88,12 +91,9 @@ object Patch {
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains, reified TPatch> byContains( @Throws(DocumentException::class)
tableName: String, @JvmStatic
criteria: TContains, fun <TContains, TPatch> byContains(tableName: String, criteria: TContains, patch: TPatch, conn: Connection) =
patch: TPatch,
conn: Connection
) =
conn.customNonQuery( conn.customNonQuery(
Patch.byContains(tableName), Patch.byContains(tableName),
listOf(Parameters.json(":criteria", criteria), Parameters.json(":data", patch)) listOf(Parameters.json(":criteria", criteria), Parameters.json(":data", patch))
@ -107,7 +107,9 @@ object Patch {
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains, reified TPatch> byContains(tableName: String, criteria: TContains, patch: TPatch) = @Throws(DocumentException::class)
@JvmStatic
fun <TContains, TPatch> byContains(tableName: String, criteria: TContains, patch: TPatch) =
Configuration.dbConn().use { byContains(tableName, criteria, patch, it) } Configuration.dbConn().use { byContains(tableName, criteria, patch, it) }
/** /**
@ -119,7 +121,9 @@ object Patch {
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TPatch> byJsonPath(tableName: String, path: String, patch: TPatch, conn: Connection) = @Throws(DocumentException::class)
@JvmStatic
fun <TPatch> byJsonPath(tableName: String, path: String, patch: TPatch, conn: Connection) =
conn.customNonQuery( conn.customNonQuery(
Patch.byJsonPath(tableName), Patch.byJsonPath(tableName),
listOf(Parameter(":path", ParameterType.STRING, path), Parameters.json(":data", patch)) listOf(Parameter(":path", ParameterType.STRING, path), Parameters.json(":data", patch))
@ -133,6 +137,8 @@ object Patch {
* @param patch The object whose properties should be replaced in the document * @param patch The object whose properties should be replaced in the document
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TPatch> byJsonPath(tableName: String, path: String, patch: TPatch) = @Throws(DocumentException::class)
@JvmStatic
fun <TPatch> byJsonPath(tableName: String, path: String, patch: TPatch) =
Configuration.dbConn().use { byJsonPath(tableName, path, patch, it) } Configuration.dbConn().use { byJsonPath(tableName, path, patch, it) }
} }

View File

@ -1,6 +1,7 @@
package solutions.bitbadger.documents.java package solutions.bitbadger.documents.java
import solutions.bitbadger.documents.common.* import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.query.RemoveFields
import java.sql.Connection import java.sql.Connection
/** /**
@ -30,10 +31,11 @@ object RemoveFields {
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
*/ */
@JvmStatic
fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>, conn: Connection) { fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>, conn: Connection) {
val nameParams = Parameters.fieldNames(toRemove) val nameParams = Parameters.fieldNames(toRemove)
conn.customNonQuery( conn.customNonQuery(
byId(tableName, nameParams, docId), RemoveFields.byId(tableName, nameParams, docId),
Parameters.addFields( Parameters.addFields(
listOf(Field.equal(Configuration.idField, docId, ":id")), listOf(Field.equal(Configuration.idField, docId, ":id")),
translatePath(nameParams) translatePath(nameParams)
@ -48,6 +50,7 @@ object RemoveFields {
* @param docId The ID of the document to have fields removed * @param docId The ID of the document to have fields removed
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
*/ */
@JvmStatic
fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>) = fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>) =
Configuration.dbConn().use { byId(tableName, docId, toRemove, it) } Configuration.dbConn().use { byId(tableName, docId, toRemove, it) }
@ -60,6 +63,7 @@ object RemoveFields {
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
*/ */
@JvmStatic
fun byFields( fun byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
@ -70,7 +74,7 @@ object RemoveFields {
val named = Parameters.nameFields(fields) val named = Parameters.nameFields(fields)
val nameParams = Parameters.fieldNames(toRemove) val nameParams = Parameters.fieldNames(toRemove)
conn.customNonQuery( conn.customNonQuery(
byFields(tableName, nameParams, named, howMatched), RemoveFields.byFields(tableName, nameParams, named, howMatched),
Parameters.addFields(named, translatePath(nameParams)) Parameters.addFields(named, translatePath(nameParams))
) )
} }
@ -83,6 +87,8 @@ object RemoveFields {
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
* @param howMatched How the fields should be matched * @param howMatched How the fields should be matched
*/ */
@JvmStatic
@JvmOverloads
fun byFields( fun byFields(
tableName: String, tableName: String,
fields: Collection<Field<*>>, fields: Collection<Field<*>>,
@ -100,7 +106,9 @@ object RemoveFields {
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> byContains( @Throws(DocumentException::class)
@JvmStatic
fun <TContains> byContains(
tableName: String, tableName: String,
criteria: TContains, criteria: TContains,
toRemove: Collection<String>, toRemove: Collection<String>,
@ -121,7 +129,9 @@ object RemoveFields {
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, toRemove: Collection<String>) = @Throws(DocumentException::class)
@JvmStatic
fun <TContains> byContains(tableName: String, criteria: TContains, toRemove: Collection<String>) =
Configuration.dbConn().use { byContains(tableName, criteria, toRemove, it) } Configuration.dbConn().use { byContains(tableName, criteria, toRemove, it) }
/** /**
@ -133,6 +143,8 @@ object RemoveFields {
* @param conn The connection on which the update should be executed * @param conn The connection on which the update should be executed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>, conn: Connection) { fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>, conn: Connection) {
val nameParams = Parameters.fieldNames(toRemove) val nameParams = Parameters.fieldNames(toRemove)
conn.customNonQuery( conn.customNonQuery(
@ -149,6 +161,8 @@ object RemoveFields {
* @param toRemove The names of the fields to be removed * @param toRemove The names of the fields to be removed
* @throws DocumentException If called on a SQLite connection * @throws DocumentException If called on a SQLite connection
*/ */
@Throws(DocumentException::class)
@JvmStatic
fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>) = fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>) =
Configuration.dbConn().use { byJsonPath(tableName, path, toRemove, it) } Configuration.dbConn().use { byJsonPath(tableName, path, toRemove, it) }
} }

View File

@ -63,12 +63,13 @@ object Results {
* Extract a count from the first column * Extract a count from the first column
* *
* @param rs A `ResultSet` set to the row with the count to retrieve * @param rs A `ResultSet` set to the row with the count to retrieve
* @param clazz The type parameter (ignored; this always returns `Long`)
* @return The count from the row * @return The count from the row
* @throws DocumentException If the dialect has not been set * @throws DocumentException If the dialect has not been set
*/ */
@Throws(DocumentException::class) @Throws(DocumentException::class)
@JvmStatic @JvmStatic
fun toCount(rs: ResultSet) = fun toCount(rs: ResultSet, clazz: Class<*>) =
when (Configuration.dialect()) { when (Configuration.dialect()) {
Dialect.POSTGRESQL -> rs.getInt("it").toLong() Dialect.POSTGRESQL -> rs.getInt("it").toLong()
Dialect.SQLITE -> rs.getLong("it") Dialect.SQLITE -> rs.getLong("it")
@ -78,14 +79,15 @@ object Results {
* Extract a true/false value from the first column * Extract a true/false value from the first column
* *
* @param rs A `ResultSet` set to the row with the true/false value to retrieve * @param rs A `ResultSet` set to the row with the true/false value to retrieve
* @param clazz The type parameter (ignored; this always returns `Boolean`)
* @return The true/false value from the row * @return The true/false value from the row
* @throws DocumentException If the dialect has not been set * @throws DocumentException If the dialect has not been set
*/ */
@Throws(DocumentException::class) @Throws(DocumentException::class)
@JvmStatic @JvmStatic
fun toExists(rs: ResultSet) = fun toExists(rs: ResultSet, clazz: Class<*>) =
when (Configuration.dialect()) { when (Configuration.dialect()) {
Dialect.POSTGRESQL -> rs.getBoolean("it") Dialect.POSTGRESQL -> rs.getBoolean("it")
Dialect.SQLITE -> toCount(rs) > 0L Dialect.SQLITE -> toCount(rs, Long::class.java) > 0L
} }
} }

View File

@ -1,9 +1,12 @@
package solutions.bitbadger.documents.java.integration.common package solutions.bitbadger.documents.java.integration.common
import solutions.bitbadger.documents.common.* import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.query.Count
import solutions.bitbadger.documents.common.query.Delete
import solutions.bitbadger.documents.common.query.Find
import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.java.integration.JsonDocument import solutions.bitbadger.documents.java.integration.JsonDocument
import solutions.bitbadger.documents.java.integration.TEST_TABLE import solutions.bitbadger.documents.java.integration.TEST_TABLE
import solutions.bitbadger.documents.java.Results
import solutions.bitbadger.documents.java.integration.ThrowawayDatabase import solutions.bitbadger.documents.java.integration.ThrowawayDatabase
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
@ -17,26 +20,26 @@ object Custom {
fun listEmpty(db: ThrowawayDatabase) { fun listEmpty(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
db.conn.deleteByFields(TEST_TABLE, listOf(Field.exists(Configuration.idField))) db.conn.deleteByFields(TEST_TABLE, listOf(Field.exists(Configuration.idField)))
val result = db.conn.customList<JsonDocument>(Find.all(TEST_TABLE), mapFunc = Results::fromData) val result = db.conn.customList(Find.all(TEST_TABLE), listOf(), JsonDocument::class.java, Results::fromData)
assertEquals(0, result.size, "There should have been no results") assertEquals(0, result.size, "There should have been no results")
} }
fun listAll(db: ThrowawayDatabase) { fun listAll(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val result = db.conn.customList<JsonDocument>(Find.all(TEST_TABLE), mapFunc = Results::fromData) val result = db.conn.customList(Find.all(TEST_TABLE), listOf(), JsonDocument::class.java, Results::fromData)
assertEquals(5, result.size, "There should have been 5 results") assertEquals(5, result.size, "There should have been 5 results")
} }
fun singleNone(db: ThrowawayDatabase) = fun singleNone(db: ThrowawayDatabase) =
assertNull( assertNull(
db.conn.customSingle(Find.all(TEST_TABLE), mapFunc = Results::fromData), db.conn.customSingle(Find.all(TEST_TABLE), listOf(), JsonDocument::class.java, Results::fromData),
"There should not have been a document returned" "There should not have been a document returned"
) )
fun singleOne(db: ThrowawayDatabase) { fun singleOne(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertNotNull( assertNotNull(
db.conn.customSingle<JsonDocument>(Find.all(TEST_TABLE), mapFunc = Results::fromData), db.conn.customSingle(Find.all(TEST_TABLE), listOf(), JsonDocument::class.java, Results::fromData),
"There should not have been a document returned" "There should not have been a document returned"
) )
} }
@ -44,12 +47,12 @@ object Custom {
fun nonQueryChanges(db: ThrowawayDatabase) { fun nonQueryChanges(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals( assertEquals(
5L, db.conn.customScalar(Count.all(TEST_TABLE), mapFunc = Results::toCount), 5L, db.conn.customScalar(Count.all(TEST_TABLE), listOf(), Long::class.java, Results::toCount),
"There should have been 5 documents in the table" "There should have been 5 documents in the table"
) )
db.conn.customNonQuery("DELETE FROM $TEST_TABLE") db.conn.customNonQuery("DELETE FROM $TEST_TABLE")
assertEquals( assertEquals(
0L, db.conn.customScalar(Count.all(TEST_TABLE), mapFunc = Results::toCount), 0L, db.conn.customScalar(Count.all(TEST_TABLE), listOf(), Long::class.java, Results::toCount),
"There should have been no documents in the table" "There should have been no documents in the table"
) )
} }
@ -57,7 +60,7 @@ object Custom {
fun nonQueryNoChanges(db: ThrowawayDatabase) { fun nonQueryNoChanges(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals( assertEquals(
5L, db.conn.customScalar(Count.all(TEST_TABLE), mapFunc = Results::toCount), 5L, db.conn.customScalar(Count.all(TEST_TABLE), listOf(), Long::class.java, Results::toCount),
"There should have been 5 documents in the table" "There should have been 5 documents in the table"
) )
db.conn.customNonQuery( db.conn.customNonQuery(
@ -65,7 +68,7 @@ object Custom {
listOf(Parameter(":id", ParameterType.STRING, "eighty-two")) listOf(Parameter(":id", ParameterType.STRING, "eighty-two"))
) )
assertEquals( assertEquals(
5L, db.conn.customScalar(Count.all(TEST_TABLE), mapFunc = Results::toCount), 5L, db.conn.customScalar(Count.all(TEST_TABLE), listOf(), Long::class.java, Results::toCount),
"There should still have been 5 documents in the table" "There should still have been 5 documents in the table"
) )
} }
@ -74,7 +77,12 @@ object Custom {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals( assertEquals(
3L, 3L,
db.conn.customScalar("SELECT 3 AS it FROM $TEST_TABLE LIMIT 1", mapFunc = Results::toCount), db.conn.customScalar(
"SELECT 3 AS it FROM $TEST_TABLE LIMIT 1",
listOf(),
Long::class.java,
Results::toCount
),
"The number 3 should have been returned" "The number 3 should have been returned"
) )
} }

View File

@ -1,8 +1,6 @@
package solutions.bitbadger.documents.java.integration.common package solutions.bitbadger.documents.java.integration.common
import solutions.bitbadger.documents.* import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Field
import solutions.bitbadger.documents.integration.*
import solutions.bitbadger.documents.java.* import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.java.integration.* import solutions.bitbadger.documents.java.integration.*
import kotlin.test.* import kotlin.test.*
@ -16,7 +14,7 @@ object Document {
assertEquals(0L, db.conn.countAll(TEST_TABLE), "There should be no documents in the table") assertEquals(0L, db.conn.countAll(TEST_TABLE), "There should be no documents in the table")
val doc = JsonDocument("turkey", "", 0, SubDocument("gobble", "gobble")) val doc = JsonDocument("turkey", "", 0, SubDocument("gobble", "gobble"))
db.conn.insert(TEST_TABLE, doc) db.conn.insert(TEST_TABLE, doc)
val after = db.conn.findAll<JsonDocument>(TEST_TABLE) val after = db.conn.findAll(TEST_TABLE, JsonDocument::class.java)
assertEquals(1, after.size, "There should be one document in the table") assertEquals(1, after.size, "There should be one document in the table")
assertEquals(doc, after[0], "The document should be what was inserted") assertEquals(doc, after[0], "The document should be what was inserted")
} }
@ -42,7 +40,7 @@ object Document {
db.conn.insert(TEST_TABLE, NumIdDocument(77, "three")) db.conn.insert(TEST_TABLE, NumIdDocument(77, "three"))
db.conn.insert(TEST_TABLE, NumIdDocument(0, "four")) db.conn.insert(TEST_TABLE, NumIdDocument(0, "four"))
val after = db.conn.findAll<NumIdDocument>(TEST_TABLE, listOf(Field.named("key"))) val after = db.conn.findAll(TEST_TABLE, NumIdDocument::class.java, listOf(Field.named("key")))
assertEquals(4, after.size, "There should have been 4 documents returned") assertEquals(4, after.size, "There should have been 4 documents returned")
assertEquals( assertEquals(
"1|2|77|78", after.joinToString("|") { it.key.toString() }, "1|2|77|78", after.joinToString("|") { it.key.toString() },
@ -61,7 +59,7 @@ object Document {
db.conn.insert(TEST_TABLE, JsonDocument("")) db.conn.insert(TEST_TABLE, JsonDocument(""))
val after = db.conn.findAll<JsonDocument>(TEST_TABLE) val after = db.conn.findAll(TEST_TABLE, JsonDocument::class.java)
assertEquals(1, after.size, "There should have been 1 document returned") assertEquals(1, after.size, "There should have been 1 document returned")
assertEquals(32, after[0].id.length, "The ID was not generated correctly") assertEquals(32, after[0].id.length, "The ID was not generated correctly")
} finally { } finally {
@ -79,7 +77,7 @@ object Document {
Configuration.idStringLength = 21 Configuration.idStringLength = 21
db.conn.insert(TEST_TABLE, JsonDocument("")) db.conn.insert(TEST_TABLE, JsonDocument(""))
val after = db.conn.findAll<JsonDocument>(TEST_TABLE) val after = db.conn.findAll(TEST_TABLE, JsonDocument::class.java)
assertEquals(2, after.size, "There should have been 2 documents returned") assertEquals(2, after.size, "There should have been 2 documents returned")
assertEquals(16, after[0].id.length, "The first document's ID was not generated correctly") assertEquals(16, after[0].id.length, "The first document's ID was not generated correctly")
assertEquals(21, after[1].id.length, "The second document's ID was not generated correctly") assertEquals(21, after[1].id.length, "The second document's ID was not generated correctly")
@ -92,7 +90,7 @@ object Document {
fun saveMatch(db: ThrowawayDatabase) { fun saveMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
db.conn.save(TEST_TABLE, JsonDocument("two", numValue = 44)) db.conn.save(TEST_TABLE, JsonDocument("two", numValue = 44))
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "two") val doc = db.conn.findById(TEST_TABLE, "two", JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("two", doc.id, "An incorrect document was returned") assertEquals("two", doc.id, "An incorrect document was returned")
assertEquals("", doc.value, "The \"value\" field was not updated") assertEquals("", doc.value, "The \"value\" field was not updated")
@ -104,7 +102,7 @@ object Document {
JsonDocument.load(db) JsonDocument.load(db)
db.conn.save(TEST_TABLE, JsonDocument("test", sub = SubDocument("a", "b"))) db.conn.save(TEST_TABLE, JsonDocument("test", sub = SubDocument("a", "b")))
assertNotNull( assertNotNull(
db.conn.findById<String, JsonDocument>(TEST_TABLE, "test"), db.conn.findById(TEST_TABLE, "test", JsonDocument::class.java),
"The test document should have been saved" "The test document should have been saved"
) )
} }
@ -112,7 +110,7 @@ object Document {
fun updateMatch(db: ThrowawayDatabase) { fun updateMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
db.conn.update(TEST_TABLE, "one", JsonDocument("one", "howdy", 8, SubDocument("y", "z"))) db.conn.update(TEST_TABLE, "one", JsonDocument("one", "howdy", 8, SubDocument("y", "z")))
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "one") val doc = db.conn.findById(TEST_TABLE, "one", JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("one", doc.id, "An incorrect document was returned") assertEquals("one", doc.id, "An incorrect document was returned")
assertEquals("howdy", doc.value, "The \"value\" field was not updated") assertEquals("howdy", doc.value, "The \"value\" field was not updated")

View File

@ -1,9 +1,6 @@
package solutions.bitbadger.documents.java.integration.common package solutions.bitbadger.documents.java.integration.common
import solutions.bitbadger.documents.* import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Field
import solutions.bitbadger.documents.common.FieldMatch
import solutions.bitbadger.documents.integration.*
import solutions.bitbadger.documents.java.* import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.java.integration.* import solutions.bitbadger.documents.java.integration.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -18,12 +15,16 @@ object Find {
fun allDefault(db: ThrowawayDatabase) { fun allDefault(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals(5, db.conn.findAll<JsonDocument>(TEST_TABLE).size, "There should have been 5 documents returned") assertEquals(
5,
db.conn.findAll(TEST_TABLE, JsonDocument::class.java).size,
"There should have been 5 documents returned"
)
} }
fun allAscending(db: ThrowawayDatabase) { fun allAscending(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findAll<JsonDocument>(TEST_TABLE, listOf(Field.named("id"))) val docs = db.conn.findAll(TEST_TABLE, JsonDocument::class.java, listOf(Field.named("id")))
assertEquals(5, docs.size, "There should have been 5 documents returned") assertEquals(5, docs.size, "There should have been 5 documents returned")
assertEquals( assertEquals(
"five|four|one|three|two", "five|four|one|three|two",
@ -34,7 +35,7 @@ object Find {
fun allDescending(db: ThrowawayDatabase) { fun allDescending(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findAll<JsonDocument>(TEST_TABLE, listOf(Field.named("id DESC"))) val docs = db.conn.findAll(TEST_TABLE, JsonDocument::class.java, listOf(Field.named("id DESC")))
assertEquals(5, docs.size, "There should have been 5 documents returned") assertEquals(5, docs.size, "There should have been 5 documents returned")
assertEquals( assertEquals(
"two|three|one|four|five", "two|three|one|four|five",
@ -45,8 +46,9 @@ object Find {
fun allNumOrder(db: ThrowawayDatabase) { fun allNumOrder(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findAll<JsonDocument>( val docs = db.conn.findAll(
TEST_TABLE, TEST_TABLE,
JsonDocument::class.java,
listOf(Field.named("sub.foo NULLS LAST"), Field.named("n:numValue")) listOf(Field.named("sub.foo NULLS LAST"), Field.named("n:numValue"))
) )
assertEquals(5, docs.size, "There should have been 5 documents returned") assertEquals(5, docs.size, "There should have been 5 documents returned")
@ -58,11 +60,15 @@ object Find {
} }
fun allEmpty(db: ThrowawayDatabase) = fun allEmpty(db: ThrowawayDatabase) =
assertEquals(0, db.conn.findAll<JsonDocument>(TEST_TABLE).size, "There should have been no documents returned") assertEquals(
0,
db.conn.findAll(TEST_TABLE, JsonDocument::class.java).size,
"There should have been no documents returned"
)
fun byIdString(db: ThrowawayDatabase) { fun byIdString(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "two") val doc = db.conn.findById(TEST_TABLE, "two", JsonDocument::class.java)
assertNotNull(doc, "The document should have been returned") assertNotNull(doc, "The document should have been returned")
assertEquals("two", doc.id, "An incorrect document was returned") assertEquals("two", doc.id, "An incorrect document was returned")
} }
@ -71,7 +77,7 @@ object Find {
Configuration.idField = "key" Configuration.idField = "key"
try { try {
db.conn.insert(TEST_TABLE, NumIdDocument(18, "howdy")) db.conn.insert(TEST_TABLE, NumIdDocument(18, "howdy"))
val doc = db.conn.findById<Int, NumIdDocument>(TEST_TABLE, 18) val doc = db.conn.findById(TEST_TABLE, 18, NumIdDocument::class.java)
assertNotNull(doc, "The document should have been returned") assertNotNull(doc, "The document should have been returned")
} finally { } finally {
Configuration.idField = "id" Configuration.idField = "id"
@ -81,16 +87,17 @@ object Find {
fun byIdNotFound(db: ThrowawayDatabase) { fun byIdNotFound(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertNull( assertNull(
db.conn.findById<String, JsonDocument>(TEST_TABLE, "x"), db.conn.findById(TEST_TABLE, "x", JsonDocument::class.java),
"There should have been no document returned" "There should have been no document returned"
) )
} }
fun byFieldsMatch(db: ThrowawayDatabase) { fun byFieldsMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByFields<JsonDocument>( val docs = db.conn.findByFields(
TEST_TABLE, TEST_TABLE,
listOf(Field.any("value", listOf("blue", "purple")), Field.exists("sub")), listOf(Field.any("value", listOf("blue", "purple")), Field.exists("sub")),
JsonDocument::class.java,
FieldMatch.ALL FieldMatch.ALL
) )
assertEquals(1, docs.size, "There should have been a document returned") assertEquals(1, docs.size, "There should have been a document returned")
@ -99,9 +106,10 @@ object Find {
fun byFieldsMatchOrdered(db: ThrowawayDatabase) { fun byFieldsMatchOrdered(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByFields<JsonDocument>( val docs = db.conn.findByFields(
TEST_TABLE, TEST_TABLE,
listOf(Field.equal("value", "purple")), listOf(Field.equal("value", "purple")),
JsonDocument::class.java,
orderBy = listOf(Field.named("id")) orderBy = listOf(Field.named("id"))
) )
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
@ -110,7 +118,11 @@ object Find {
fun byFieldsMatchNumIn(db: ThrowawayDatabase) { fun byFieldsMatchNumIn(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByFields<JsonDocument>(TEST_TABLE, listOf(Field.any("numValue", listOf(2, 4, 6, 8)))) val docs = db.conn.findByFields(
TEST_TABLE,
listOf(Field.any("numValue", listOf(2, 4, 6, 8))),
JsonDocument::class.java
)
assertEquals(1, docs.size, "There should have been a document returned") assertEquals(1, docs.size, "There should have been a document returned")
assertEquals("three", docs[0].id, "The incorrect document was returned") assertEquals("three", docs[0].id, "The incorrect document was returned")
} }
@ -119,7 +131,7 @@ object Find {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals( assertEquals(
0, 0,
db.conn.findByFields<JsonDocument>(TEST_TABLE, listOf(Field.greater("numValue", 100))).size, db.conn.findByFields(TEST_TABLE, listOf(Field.greater("numValue", 100)), JsonDocument::class.java).size,
"There should have been no documents returned" "There should have been no documents returned"
) )
} }
@ -127,7 +139,11 @@ object Find {
fun byFieldsMatchInArray(db: ThrowawayDatabase) { fun byFieldsMatchInArray(db: ThrowawayDatabase) {
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) } ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
val docs = val docs =
db.conn.findByFields<ArrayDocument>(TEST_TABLE, listOf(Field.inArray("values", TEST_TABLE, listOf("c")))) db.conn.findByFields(
TEST_TABLE,
listOf(Field.inArray("values", TEST_TABLE, listOf("c"))),
ArrayDocument::class.java
)
assertEquals(2, docs.size, "There should have been two documents returned") assertEquals(2, docs.size, "There should have been two documents returned")
assertTrue(listOf("first", "second").contains(docs[0].id), "An incorrect document was returned (${docs[0].id}") assertTrue(listOf("first", "second").contains(docs[0].id), "An incorrect document was returned (${docs[0].id}")
assertTrue(listOf("first", "second").contains(docs[1].id), "An incorrect document was returned (${docs[1].id}") assertTrue(listOf("first", "second").contains(docs[1].id), "An incorrect document was returned (${docs[1].id}")
@ -137,9 +153,10 @@ object Find {
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) } ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
assertEquals( assertEquals(
0, 0,
db.conn.findByFields<ArrayDocument>( db.conn.findByFields(
TEST_TABLE, TEST_TABLE,
listOf(Field.inArray("values", TEST_TABLE, listOf("j"))) listOf(Field.inArray("values", TEST_TABLE, listOf("j"))),
ArrayDocument::class.java
).size, ).size,
"There should have been no documents returned" "There should have been no documents returned"
) )
@ -147,7 +164,7 @@ object Find {
fun byContainsMatch(db: ThrowawayDatabase) { fun byContainsMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "purple")) val docs = db.conn.findByContains(TEST_TABLE, mapOf("value" to "purple"), JsonDocument::class.java)
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
assertTrue(listOf("four", "five").contains(docs[0].id), "An incorrect document was returned (${docs[0].id}") assertTrue(listOf("four", "five").contains(docs[0].id), "An incorrect document was returned (${docs[0].id}")
assertTrue(listOf("four", "five").contains(docs[1].id), "An incorrect document was returned (${docs[1].id}") assertTrue(listOf("four", "five").contains(docs[1].id), "An incorrect document was returned (${docs[1].id}")
@ -155,9 +172,10 @@ object Find {
fun byContainsMatchOrdered(db: ThrowawayDatabase) { fun byContainsMatchOrdered(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByContains<JsonDocument, Map<String, Map<String, String>>>( val docs = db.conn.findByContains(
TEST_TABLE, TEST_TABLE,
mapOf("sub" to mapOf("foo" to "green")), mapOf("sub" to mapOf("foo" to "green")),
JsonDocument::class.java,
listOf(Field.named("value")) listOf(Field.named("value"))
) )
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
@ -168,14 +186,14 @@ object Find {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals( assertEquals(
0, 0,
db.conn.findByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "indigo")).size, db.conn.findByContains(TEST_TABLE, mapOf("value" to "indigo"), JsonDocument::class.java).size,
"There should have been no documents returned" "There should have been no documents returned"
) )
} }
fun byJsonPathMatch(db: ThrowawayDatabase) { fun byJsonPathMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 10)") val docs = db.conn.findByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)", JsonDocument::class.java)
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
assertTrue(listOf("four", "five").contains(docs[0].id), "An incorrect document was returned (${docs[0].id}") assertTrue(listOf("four", "five").contains(docs[0].id), "An incorrect document was returned (${docs[0].id}")
assertTrue(listOf("four", "five").contains(docs[1].id), "An incorrect document was returned (${docs[1].id}") assertTrue(listOf("four", "five").contains(docs[1].id), "An incorrect document was returned (${docs[1].id}")
@ -183,7 +201,12 @@ object Find {
fun byJsonPathMatchOrdered(db: ThrowawayDatabase) { fun byJsonPathMatchOrdered(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 10)", listOf(Field.named("id"))) val docs = db.conn.findByJsonPath(
TEST_TABLE,
"$.numValue ? (@ > 10)",
JsonDocument::class.java,
listOf(Field.named("id"))
)
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
assertEquals("five|four", docs.joinToString("|") { it.id }, "The documents were not ordered correctly") assertEquals("five|four", docs.joinToString("|") { it.id }, "The documents were not ordered correctly")
} }
@ -192,30 +215,34 @@ object Find {
JsonDocument.load(db) JsonDocument.load(db)
assertEquals( assertEquals(
0, 0,
db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 100)").size, db.conn.findByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)", JsonDocument::class.java).size,
"There should have been no documents returned" "There should have been no documents returned"
) )
} }
fun firstByFieldsMatchOne(db: ThrowawayDatabase) { fun firstByFieldsMatchOne(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByFields<JsonDocument>(TEST_TABLE, listOf(Field.equal("value", "another"))) val doc =
db.conn.findFirstByFields(TEST_TABLE, listOf(Field.equal("value", "another")), JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("two", doc.id, "The incorrect document was returned") assertEquals("two", doc.id, "The incorrect document was returned")
} }
fun firstByFieldsMatchMany(db: ThrowawayDatabase) { fun firstByFieldsMatchMany(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByFields<JsonDocument>(TEST_TABLE, listOf(Field.equal("sub.foo", "green"))) val doc =
db.conn.findFirstByFields(TEST_TABLE, listOf(Field.equal("sub.foo", "green")), JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertTrue(listOf("two", "four").contains(doc.id), "An incorrect document was returned (${doc.id}") assertTrue(listOf("two", "four").contains(doc.id), "An incorrect document was returned (${doc.id}")
} }
fun firstByFieldsMatchOrdered(db: ThrowawayDatabase) { fun firstByFieldsMatchOrdered(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByFields<JsonDocument>( val doc = db.conn.findFirstByFields(
TEST_TABLE, listOf(Field.equal("sub.foo", "green")), orderBy = listOf( TEST_TABLE, listOf(Field.equal("sub.foo", "green")), JsonDocument::class.java, orderBy = listOf(
Field.named("n:numValue DESC"))) Field.named("n:numValue DESC")
)
)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("four", doc.id, "An incorrect document was returned") assertEquals("four", doc.id, "An incorrect document was returned")
} }
@ -223,30 +250,31 @@ object Find {
fun firstByFieldsNoMatch(db: ThrowawayDatabase) { fun firstByFieldsNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertNull( assertNull(
db.conn.findFirstByFields(TEST_TABLE, listOf(Field.equal("value", "absent"))), db.conn.findFirstByFields(TEST_TABLE, listOf(Field.equal("value", "absent")), JsonDocument::class.java),
"There should have been no document returned" "There should have been no document returned"
) )
} }
fun firstByContainsMatchOne(db: ThrowawayDatabase) { fun firstByContainsMatchOne(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "FIRST!")) val doc = db.conn.findFirstByContains(TEST_TABLE, mapOf("value" to "FIRST!"), JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("one", doc.id, "An incorrect document was returned") assertEquals("one", doc.id, "An incorrect document was returned")
} }
fun firstByContainsMatchMany(db: ThrowawayDatabase) { fun firstByContainsMatchMany(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "purple")) val doc = db.conn.findFirstByContains(TEST_TABLE, mapOf("value" to "purple"), JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertTrue(listOf("four", "five").contains(doc.id), "An incorrect document was returned (${doc.id}") assertTrue(listOf("four", "five").contains(doc.id), "An incorrect document was returned (${doc.id}")
} }
fun firstByContainsMatchOrdered(db: ThrowawayDatabase) { fun firstByContainsMatchOrdered(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>( val doc = db.conn.findFirstByContains(
TEST_TABLE, TEST_TABLE,
mapOf("value" to "purple"), mapOf("value" to "purple"),
JsonDocument::class.java,
listOf(Field.named("sub.bar NULLS FIRST")) listOf(Field.named("sub.bar NULLS FIRST"))
) )
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
@ -256,32 +284,31 @@ object Find {
fun firstByContainsNoMatch(db: ThrowawayDatabase) { fun firstByContainsNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertNull( assertNull(
db.conn.findFirstByContains<JsonDocument, Map<String, String>>( db.conn.findFirstByContains(TEST_TABLE, mapOf("value" to "indigo"), JsonDocument::class.java),
TEST_TABLE, "There should have been no document returned"
mapOf("value" to "indigo")
), "There should have been no document returned"
) )
} }
fun firstByJsonPathMatchOne(db: ThrowawayDatabase) { fun firstByJsonPathMatchOne(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ == 10)") val doc = db.conn.findFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10)", JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("two", doc.id, "An incorrect document was returned") assertEquals("two", doc.id, "An incorrect document was returned")
} }
fun firstByJsonPathMatchMany(db: ThrowawayDatabase) { fun firstByJsonPathMatchMany(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 10)") val doc = db.conn.findFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)", JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertTrue(listOf("four", "five").contains(doc.id), "An incorrect document was returned (${doc.id}") assertTrue(listOf("four", "five").contains(doc.id), "An incorrect document was returned (${doc.id}")
} }
fun firstByJsonPathMatchOrdered(db: ThrowawayDatabase) { fun firstByJsonPathMatchOrdered(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
val doc = db.conn.findFirstByJsonPath<JsonDocument>( val doc = db.conn.findFirstByJsonPath(
TEST_TABLE, TEST_TABLE,
"$.numValue ? (@ > 10)", "$.numValue ? (@ > 10)",
JsonDocument::class.java,
listOf(Field.named("id DESC")) listOf(Field.named("id DESC"))
) )
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
@ -290,6 +317,9 @@ object Find {
fun firstByJsonPathNoMatch(db: ThrowawayDatabase) { fun firstByJsonPathNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
assertNull(db.conn.findFirstByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 100)"), "There should have been no document returned") assertNull(
db.conn.findFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)", JsonDocument::class.java),
"There should have been no document returned"
)
} }
} }

View File

@ -1,6 +1,5 @@
package solutions.bitbadger.documents.java.integration.common package solutions.bitbadger.documents.java.integration.common
import solutions.bitbadger.documents.*
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.Field
import solutions.bitbadger.documents.java.* import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.java.integration.JsonDocument import solutions.bitbadger.documents.java.integration.JsonDocument
@ -19,7 +18,7 @@ object Patch {
fun byIdMatch(db: ThrowawayDatabase) { fun byIdMatch(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
db.conn.patchById(TEST_TABLE, "one", mapOf("numValue" to 44)) db.conn.patchById(TEST_TABLE, "one", mapOf("numValue" to 44))
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "one") val doc = db.conn.findById(TEST_TABLE, "one", JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("one", doc.id, "An incorrect document was returned") assertEquals("one", doc.id, "An incorrect document was returned")
assertEquals(44, doc.numValue, "The document was not patched") assertEquals(44, doc.numValue, "The document was not patched")
@ -56,7 +55,7 @@ object Patch {
JsonDocument.load(db) JsonDocument.load(db)
val contains = mapOf("value" to "another") val contains = mapOf("value" to "another")
db.conn.patchByContains(TEST_TABLE, contains, mapOf("numValue" to 12)) db.conn.patchByContains(TEST_TABLE, contains, mapOf("numValue" to 12))
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(TEST_TABLE, contains) val doc = db.conn.findFirstByContains(TEST_TABLE, contains, JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("two", doc.id, "The incorrect document was returned") assertEquals("two", doc.id, "The incorrect document was returned")
assertEquals(12, doc.numValue, "The document was not updated") assertEquals(12, doc.numValue, "The document was not updated")
@ -73,7 +72,7 @@ object Patch {
JsonDocument.load(db) JsonDocument.load(db)
val path = "$.numValue ? (@ > 10)" val path = "$.numValue ? (@ > 10)"
db.conn.patchByJsonPath(TEST_TABLE, path, mapOf("value" to "blue")) db.conn.patchByJsonPath(TEST_TABLE, path, mapOf("value" to "blue"))
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, path) val docs = db.conn.findByJsonPath(TEST_TABLE, path, JsonDocument::class.java)
assertEquals(2, docs.size, "There should have been two documents returned") assertEquals(2, docs.size, "There should have been two documents returned")
docs.forEach { docs.forEach {
assertTrue(listOf("four", "five").contains(it.id), "An incorrect document was returned (${it.id})") assertTrue(listOf("four", "five").contains(it.id), "An incorrect document was returned (${it.id})")

View File

@ -1,6 +1,5 @@
package solutions.bitbadger.documents.java.integration.common package solutions.bitbadger.documents.java.integration.common
import solutions.bitbadger.documents.*
import solutions.bitbadger.documents.common.Field import solutions.bitbadger.documents.common.Field
import solutions.bitbadger.documents.java.* import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.java.integration.JsonDocument import solutions.bitbadger.documents.java.integration.JsonDocument
@ -17,7 +16,7 @@ object RemoveFields {
fun byIdMatchFields(db: ThrowawayDatabase) { fun byIdMatchFields(db: ThrowawayDatabase) {
JsonDocument.load(db) JsonDocument.load(db)
db.conn.removeFieldsById(TEST_TABLE, "two", listOf("sub", "value")) db.conn.removeFieldsById(TEST_TABLE, "two", listOf("sub", "value"))
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "two") val doc = db.conn.findById(TEST_TABLE, "two", JsonDocument::class.java)
assertNotNull(doc, "There should have been a document returned") assertNotNull(doc, "There should have been a document returned")
assertEquals("", doc.value, "The value should have been empty") assertEquals("", doc.value, "The value should have been empty")
assertNull(doc.sub, "The sub-document should have been removed") assertNull(doc.sub, "The sub-document should have been removed")
@ -39,7 +38,7 @@ object RemoveFields {
JsonDocument.load(db) JsonDocument.load(db)
val fields = listOf(Field.equal("numValue", 17)) val fields = listOf(Field.equal("numValue", 17))
db.conn.removeFieldsByFields(TEST_TABLE, fields, listOf("sub")) db.conn.removeFieldsByFields(TEST_TABLE, fields, listOf("sub"))
val doc = db.conn.findFirstByFields<JsonDocument>(TEST_TABLE, fields) val doc = db.conn.findFirstByFields(TEST_TABLE, fields, JsonDocument::class.java)
assertNotNull(doc, "The document should have been returned") assertNotNull(doc, "The document should have been returned")
assertEquals("four", doc.id, "An incorrect document was returned") assertEquals("four", doc.id, "An incorrect document was returned")
assertNull(doc.sub, "The sub-document should have been removed") assertNull(doc.sub, "The sub-document should have been removed")
@ -62,7 +61,7 @@ object RemoveFields {
JsonDocument.load(db) JsonDocument.load(db)
val criteria = mapOf("sub" to mapOf("foo" to "green")) val criteria = mapOf("sub" to mapOf("foo" to "green"))
db.conn.removeFieldsByContains(TEST_TABLE, criteria, listOf("value")) db.conn.removeFieldsByContains(TEST_TABLE, criteria, listOf("value"))
val docs = db.conn.findByContains<JsonDocument, Map<String, Map<String, String>>>(TEST_TABLE, criteria) val docs = db.conn.findByContains(TEST_TABLE, criteria, JsonDocument::class.java)
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
docs.forEach { docs.forEach {
assertTrue(listOf("two", "four").contains(it.id), "An incorrect document was returned (${it.id})") assertTrue(listOf("two", "four").contains(it.id), "An incorrect document was returned (${it.id})")
@ -88,7 +87,7 @@ object RemoveFields {
JsonDocument.load(db) JsonDocument.load(db)
val path = "$.value ? (@ == \"purple\")" val path = "$.value ? (@ == \"purple\")"
db.conn.removeFieldsByJsonPath(TEST_TABLE, path, listOf("sub")) db.conn.removeFieldsByJsonPath(TEST_TABLE, path, listOf("sub"))
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, path) val docs = db.conn.findByJsonPath(TEST_TABLE, path, JsonDocument::class.java)
assertEquals(2, docs.size, "There should have been 2 documents returned") assertEquals(2, docs.size, "There should have been 2 documents returned")
docs.forEach { docs.forEach {
assertTrue(listOf("four", "five").contains(it.id), "An incorrect document was returned (${it.id})") assertTrue(listOf("four", "five").contains(it.id), "An incorrect document was returned (${it.id})")

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Count` object / `count*` connection extension functions * PostgreSQL integration tests for the `Count` object / `count*` connection extension functions
*/ */
@DisplayName("Kotlin | PostgreSQL: Count") @DisplayName("Java | Kotlin | PostgreSQL: Count")
class CountIT { class CountIT {
@Test @Test

View File

@ -8,7 +8,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions * PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions
*/ */
@DisplayName("PostgreSQL - Custom") @DisplayName("Java | Kotlin | PostgreSQL: Custom")
class CustomIT { class CustomIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Definition` object / `ensure*` connection extension functions * PostgreSQL integration tests for the `Definition` object / `ensure*` connection extension functions
*/ */
@DisplayName("PostgreSQL - Definition") @DisplayName("Java | Kotlin | PostgreSQL: Definition")
class DefinitionIT { class DefinitionIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Delete` object / `deleteBy*` connection extension functions * PostgreSQL integration tests for the `Delete` object / `deleteBy*` connection extension functions
*/ */
@DisplayName("PostgreSQL - Delete") @DisplayName("Java | Kotlin | PostgreSQL: Delete")
class DeleteIT { class DeleteIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions * PostgreSQL integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions
*/ */
@DisplayName("PostgreSQL - Document") @DisplayName("Java | Kotlin | PostgreSQL: Document")
class DocumentIT { class DocumentIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Exists` object / `existsBy*` connection extension functions * PostgreSQL integration tests for the `Exists` object / `existsBy*` connection extension functions
*/ */
@DisplayName("PostgreSQL - Exists") @DisplayName("Java | Kotlin | PostgreSQL: Exists")
class ExistsIT { class ExistsIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Find` object / `find*` connection extension functions * PostgreSQL integration tests for the `Find` object / `find*` connection extension functions
*/ */
@DisplayName("PostgreSQL - Find") @DisplayName("Java | Kotlin | PostgreSQL: Find")
class FindIT { class FindIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `Patch` object / `patchBy*` connection extension functions * PostgreSQL integration tests for the `Patch` object / `patchBy*` connection extension functions
*/ */
@DisplayName("PostgreSQL - Patch") @DisplayName("Java | Kotlin | PostgreSQL: Patch")
class PatchIT { class PatchIT {
@Test @Test

View File

@ -1,8 +1,7 @@
package solutions.bitbadger.documents.java.integration.postgresql package solutions.bitbadger.documents.java.integration.postgresql
import solutions.bitbadger.documents.* import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Parameter import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.common.ParameterType
import solutions.bitbadger.documents.java.integration.TEST_TABLE import solutions.bitbadger.documents.java.integration.TEST_TABLE
import solutions.bitbadger.documents.java.integration.ThrowawayDatabase import solutions.bitbadger.documents.java.integration.ThrowawayDatabase
@ -39,7 +38,7 @@ class PgDB : ThrowawayDatabase {
override fun dbObjectExists(name: String) = override fun dbObjectExists(name: String) =
conn.customScalar("SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = :name) AS it", conn.customScalar("SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = :name) AS it",
listOf(Parameter(":name", ParameterType.STRING, name)), Results::toExists) listOf(Parameter(":name", ParameterType.STRING, name)), Boolean::class.java, Results::toExists)
companion object { companion object {

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* PostgreSQL integration tests for the `RemoveFields` object / `removeFieldsBy*` connection extension functions * PostgreSQL integration tests for the `RemoveFields` object / `removeFieldsBy*` connection extension functions
*/ */
@DisplayName("PostgreSQL - RemoveFields") @DisplayName("Java | Kotlin | PostgreSQL: RemoveFields")
class RemoveFieldsIT { class RemoveFieldsIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Count` object / `count*` connection extension functions * SQLite integration tests for the `Count` object / `count*` connection extension functions
*/ */
@DisplayName("SQLite - Count") @DisplayName("Java | Kotlin | SQLite: Count")
class CountIT { class CountIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Custom` object / `custom*` connection extension functions * SQLite integration tests for the `Custom` object / `custom*` connection extension functions
*/ */
@DisplayName("SQLite - Custom") @DisplayName("Java | Kotlin | SQLite: Custom")
class CustomIT { class CustomIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Definition` object / `ensure*` connection extension functions * SQLite integration tests for the `Definition` object / `ensure*` connection extension functions
*/ */
@DisplayName("SQLite - Definition") @DisplayName("Java | Kotlin | SQLite: Definition")
class DefinitionIT { class DefinitionIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Delete` object / `deleteBy*` connection extension functions * SQLite integration tests for the `Delete` object / `deleteBy*` connection extension functions
*/ */
@DisplayName("SQLite - Delete") @DisplayName("Java | Kotlin | SQLite: Delete")
class DeleteIT { class DeleteIT {
@Test @Test

View File

@ -7,7 +7,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions * SQLite integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions
*/ */
@DisplayName("SQLite - Document") @DisplayName("Java | Kotlin | SQLite: Document")
class DocumentIT { class DocumentIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Exists` object / `existsBy*` connection extension functions * SQLite integration tests for the `Exists` object / `existsBy*` connection extension functions
*/ */
@DisplayName("SQLite - Exists") @DisplayName("Java | Kotlin | SQLite: Exists")
class ExistsIT { class ExistsIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Find` object / `find*` connection extension functions * SQLite integration tests for the `Find` object / `find*` connection extension functions
*/ */
@DisplayName("SQLite - Find") @DisplayName("Java | Kotlin | SQLite: Find")
class FindIT { class FindIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `Patch` object / `patchBy*` connection extension functions * SQLite integration tests for the `Patch` object / `patchBy*` connection extension functions
*/ */
@DisplayName("SQLite - Patch") @DisplayName("Java | Kotlin | SQLite: Patch")
class PatchIT { class PatchIT {
@Test @Test

View File

@ -9,7 +9,7 @@ import kotlin.test.Test
/** /**
* SQLite integration tests for the `RemoveFields` object / `removeFieldsBy*` connection extension functions * SQLite integration tests for the `RemoveFields` object / `removeFieldsBy*` connection extension functions
*/ */
@DisplayName("SQLite - RemoveFields") @DisplayName("Java | Kotlin | SQLite: RemoveFields")
class RemoveFieldsIT { class RemoveFieldsIT {
@Test @Test

View File

@ -1,8 +1,7 @@
package solutions.bitbadger.documents.java.integration.sqlite package solutions.bitbadger.documents.java.integration.sqlite
import solutions.bitbadger.documents.* import solutions.bitbadger.documents.common.*
import solutions.bitbadger.documents.common.Parameter import solutions.bitbadger.documents.java.*
import solutions.bitbadger.documents.common.ParameterType
import solutions.bitbadger.documents.java.integration.TEST_TABLE import solutions.bitbadger.documents.java.integration.TEST_TABLE
import solutions.bitbadger.documents.java.integration.ThrowawayDatabase import solutions.bitbadger.documents.java.integration.ThrowawayDatabase
import java.io.File import java.io.File
@ -32,5 +31,5 @@ class SQLiteDB : ThrowawayDatabase {
override fun dbObjectExists(name: String) = override fun dbObjectExists(name: String) =
conn.customScalar("SELECT EXISTS (SELECT 1 FROM sqlite_master WHERE name = :name) AS it", conn.customScalar("SELECT EXISTS (SELECT 1 FROM sqlite_master WHERE name = :name) AS it",
listOf(Parameter(":name", ParameterType.STRING, name)), Results::toExists) listOf(Parameter(":name", ParameterType.STRING, name)), Boolean::class.java, Results::toExists)
} }

View File

@ -1,79 +0,0 @@
package solutions.bitbadger.documents
import solutions.bitbadger.documents.common.Dialect
import solutions.bitbadger.documents.common.DocumentException
import solutions.bitbadger.documents.java.Results
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
/**
* Helper functions for handling results
*/
object Results {
/**
* Create a domain item from a document, specifying the field in which the document is found
*
* @param field The field name containing the JSON document
* @param rs A `ResultSet` set to the row with the document to be constructed
* @return The constructed domain item
*/
inline fun <reified TDoc> fromDocument(field: String): (ResultSet, Class<TDoc>) -> TDoc =
{ rs, _ -> Results.fromDocument(field, rs, TDoc::class.java) }
/**
* Create a domain item from a document
*
* @param rs A `ResultSet` set to the row with the document to be constructed<
* @param clazz The class of the document to be returned
* @return The constructed domain item
*/
inline fun <reified TDoc> fromData(rs: ResultSet, clazz: Class<TDoc> = TDoc::class.java) =
Results.fromDocument("data", rs, TDoc::class.java)
/**
* Create a list of items for the results of the given command, using the specified mapping function
*
* @param stmt The prepared statement to execute
* @param mapFunc The mapping function from data reader to domain class instance
* @return A list of items from the query's result
* @throws DocumentException If there is a problem executing the query
*/
inline fun <reified TDoc : Any> toCustomList(stmt: PreparedStatement, mapFunc: (ResultSet) -> TDoc) =
try {
stmt.executeQuery().use {
val results = mutableListOf<TDoc>()
while (it.next()) {
results.add(mapFunc(it))
}
results.toList()
}
} catch (ex: SQLException) {
throw DocumentException("Error retrieving documents from query: ${ex.message}", ex)
}
/**
* Extract a count from the first column
*
* @param rs A `ResultSet` set to the row with the count to retrieve
* @return The count from the row
*/
fun toCount(rs: ResultSet, clazz: Class<Long> = Long::class.java) =
when (Configuration.dialect()) {
Dialect.POSTGRESQL -> rs.getInt("it").toLong()
Dialect.SQLITE -> rs.getLong("it")
}
/**
* Extract a true/false value from the first column
*
* @param rs A `ResultSet` set to the row with the true/false value to retrieve
* @return The true/false value from the row
*/
fun toExists(rs: ResultSet, clazz: Class<Boolean> = Boolean::class.java) =
when (Configuration.dialect()) {
Dialect.POSTGRESQL -> rs.getBoolean("it")
Dialect.SQLITE -> toCount(rs) > 0L
}
}