Initial Development (#1)
This project now contains: - A generic JVM document library (with Kotlin extensions on the JDBC `Connection` object) - A Groovy library which adds extension methods to the `Connection` object - A Scala library, which uses native Scala collections and adds Scala-style extension methods to the `Connection` object - A Kotlin library which uses `kotlinx.serialization` (no reflection, reified generic types) along with `Connection` extensions Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
186
src/kotlinx/pom.xml
Normal file
186
src/kotlinx/pom.xml
Normal file
@@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>solutions.bitbadger</groupId>
|
||||
<artifactId>documents</artifactId>
|
||||
<version>1.0.0-RC1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>solutions.bitbadger.documents</groupId>
|
||||
<artifactId>kotlinx</artifactId>
|
||||
|
||||
<name>${project.groupId}:${project.artifactId}</name>
|
||||
<description>Expose a document store interface for PostgreSQL and SQLite (KotlinX Serialization Library)</description>
|
||||
<url>https://relationaldocs.bitbadger.solutions/jvm/</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT License</name>
|
||||
<url>https://www.opensource.org/licenses/mit-license.php</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Daniel J. Summers</name>
|
||||
<email>daniel@bitbadger.solutions</email>
|
||||
<organization>Bit Badger Solutions</organization>
|
||||
<organizationUrl>https://bitbadger.solutions</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://git.bitbadger.solutions/bit-badger/solutions.bitbadger.documents.git</connection>
|
||||
<developerConnection>scm:git:https://git.bitbadger.solutions/bit-badger/solutions.bitbadger.documents.git</developerConnection>
|
||||
<url>https://git.bitbadger.solutions/bit-badger/solutions.bitbadger.documents</url>
|
||||
</scm>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>solutions.bitbadger.documents</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-serialization-json-jvm</artifactId>
|
||||
<version>${serialization.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirs>
|
||||
<sourceDir>${project.basedir}/src/main/java</sourceDir>
|
||||
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
|
||||
</sourceDirs>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>process-test-sources</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirs>
|
||||
<sourceDir>${project.basedir}/src/test/java</sourceDir>
|
||||
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
|
||||
</sourceDirs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</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>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${failsafe.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>${buildHelperPlugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>src/main/kotlin</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>${sourcePlugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.dokka</groupId>
|
||||
<artifactId>dokka-maven-plugin</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<configuration>
|
||||
<reportUndocumented>true</reportUndocumented>
|
||||
<includes>${project.basedir}/src/main/module-info.md</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>javadocJar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.central</groupId>
|
||||
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||
<version>0.7.0</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<deploymentName>Deployment-kotlinx-${project.version}</deploymentName>
|
||||
<publishingServerId>central</publishingServerId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
10
src/kotlinx/src/main/java/module-info.java
Normal file
10
src/kotlinx/src/main/java/module-info.java
Normal file
@@ -0,0 +1,10 @@
|
||||
module solutions.bitbadger.documents.kotlinx {
|
||||
requires solutions.bitbadger.documents.core;
|
||||
requires kotlin.stdlib;
|
||||
requires kotlin.reflect;
|
||||
requires kotlinx.serialization.json;
|
||||
requires java.sql;
|
||||
|
||||
exports solutions.bitbadger.documents.kotlinx;
|
||||
exports solutions.bitbadger.documents.kotlinx.extensions;
|
||||
}
|
||||
120
src/kotlinx/src/main/kotlin/Count.kt
Normal file
120
src/kotlinx/src/main/kotlin/Count.kt
Normal file
@@ -0,0 +1,120 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.query.CountQuery
|
||||
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to count documents
|
||||
*/
|
||||
object Count {
|
||||
|
||||
/**
|
||||
* Count all documents in the table
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param conn The connection over which documents should be counted
|
||||
* @return A count of the documents in the table
|
||||
*/
|
||||
fun all(tableName: String, conn: Connection) =
|
||||
conn.customScalar(CountQuery.all(tableName), mapFunc = Results::toCount)
|
||||
|
||||
/**
|
||||
* Count all documents in the table
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @return A count of the documents in the table
|
||||
*/
|
||||
fun all(tableName: String) =
|
||||
Configuration.dbConn().use { all(tableName, it) }
|
||||
|
||||
/**
|
||||
* Count documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
* @return A count of the matching documents in the table
|
||||
*/
|
||||
fun byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
): Long {
|
||||
val named = Parameters.nameFields(fields)
|
||||
return conn.customScalar(
|
||||
CountQuery.byFields(tableName, named, howMatched),
|
||||
Parameters.addFields(named),
|
||||
Results::toCount
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Count documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @return A count of the matching documents in the table
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
|
||||
|
||||
/**
|
||||
* Count documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection on which the count should be executed
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
conn.customScalar<Long>(
|
||||
CountQuery.byContains(tableName),
|
||||
listOf(Parameters.json<TContains>(":criteria", criteria)),
|
||||
Results::toCount
|
||||
)
|
||||
|
||||
/**
|
||||
* Count documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) =
|
||||
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||
|
||||
/**
|
||||
* Count documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection on which the count should be executed
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
conn.customScalar(
|
||||
CountQuery.byJsonPath(tableName),
|
||||
listOf(Parameter(":path", ParameterType.STRING, path)),
|
||||
Results::toCount
|
||||
)
|
||||
|
||||
/**
|
||||
* Count documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param path The JSON path comparison to match
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String) =
|
||||
Configuration.dbConn().use { byJsonPath(tableName, path, it) }
|
||||
}
|
||||
218
src/kotlinx/src/main/kotlin/Custom.kt
Normal file
218
src/kotlinx/src/main/kotlin/Custom.kt
Normal file
@@ -0,0 +1,218 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import java.io.PrintWriter
|
||||
import solutions.bitbadger.documents.java.Custom as CoreCustom
|
||||
import java.sql.Connection
|
||||
import java.sql.ResultSet
|
||||
|
||||
/**
|
||||
* Custom query execution functions
|
||||
*/
|
||||
object Custom {
|
||||
|
||||
/**
|
||||
* Execute a query that returns a list of results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return A list of results for the given query
|
||||
*/
|
||||
inline fun <reified TDoc : Any> list(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
conn: Connection,
|
||||
mapFunc: (ResultSet) -> TDoc
|
||||
) = Parameters.apply(conn, query, parameters).use { Results.toCustomList(it, mapFunc) }
|
||||
|
||||
/**
|
||||
* Execute a query that returns a list of results (creates connection)
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return A list of results for the given query
|
||||
*/
|
||||
inline fun <reified TDoc : Any> list(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
mapFunc: (ResultSet) -> TDoc
|
||||
) = Configuration.dbConn().use { list(query, parameters, it, mapFunc) }
|
||||
|
||||
/**
|
||||
* Execute a query that returns a JSON array of results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param mapFunc The mapping function to extract the JSON from the query
|
||||
* @return A JSON array of results for the given query
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun jsonArray(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
conn: Connection,
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = CoreCustom.jsonArray(query, parameters, conn, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns a JSON array of results (creates connection)
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function to extract the JSON from the query
|
||||
* @return A JSON array of results for the given query
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun jsonArray(query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> String) =
|
||||
CoreCustom.jsonArray(query, parameters, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query, writing its JSON array of results to the given `PrintWriter`
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param writer The writer to which the results should be written
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param mapFunc The mapping function to extract the JSON from the query
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun writeJsonArray(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
writer: PrintWriter,
|
||||
conn: Connection,
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = CoreCustom.writeJsonArray(query, parameters, writer, conn, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query, writing its JSON array of results to the given `PrintWriter` (creates connection)
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param writer The writer to which the results should be written
|
||||
* @param mapFunc The mapping function to extract the JSON from the query
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun writeJsonArray(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
writer: PrintWriter,
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = CoreCustom.writeJsonArray(query, parameters, writer, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns one or no results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The document if one matches the query, `null` otherwise
|
||||
*/
|
||||
inline fun <reified TDoc : Any> single(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
conn: Connection,
|
||||
mapFunc: (ResultSet) -> TDoc
|
||||
) = list("$query LIMIT 1", parameters, conn, mapFunc).singleOrNull()
|
||||
|
||||
/**
|
||||
* Execute a query that returns one or no results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The document if one matches the query, `null` otherwise
|
||||
*/
|
||||
inline fun <reified TDoc : Any> single(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
noinline mapFunc: (ResultSet) -> TDoc
|
||||
) = Configuration.dbConn().use { single(query, parameters, it, mapFunc) }
|
||||
|
||||
/**
|
||||
* Execute a query that returns JSON for one or no documents
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The JSON for the document if found, an empty object (`{}`) if not
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun jsonSingle(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
conn: Connection,
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = CoreCustom.jsonSingle(query, parameters, conn, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns JSON for one or no documents (creates connection)
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The JSON for the document if found, an empty object (`{}`) if not
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun jsonSingle(query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> String) =
|
||||
CoreCustom.jsonSingle(query, parameters, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns no results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param parameters Parameters to use for the query
|
||||
*/
|
||||
fun nonQuery(query: String, parameters: Collection<Parameter<*>> = listOf(), conn: Connection) =
|
||||
CoreCustom.nonQuery(query, parameters, conn)
|
||||
|
||||
/**
|
||||
* Execute a query that returns no results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
*/
|
||||
fun nonQuery(query: String, parameters: Collection<Parameter<*>> = listOf()) =
|
||||
Configuration.dbConn().use { nonQuery(query, parameters, it) }
|
||||
|
||||
/**
|
||||
* Execute a query that returns a scalar result
|
||||
*
|
||||
* @param query The query to retrieve the result
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param conn The connection over which the query should be executed
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The scalar value from the query
|
||||
*/
|
||||
inline fun <reified T : Any> scalar(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
conn: Connection,
|
||||
mapFunc: (ResultSet) -> T
|
||||
) = Parameters.apply(conn, query, parameters).use { stmt ->
|
||||
stmt.executeQuery().use { rs ->
|
||||
rs.next()
|
||||
mapFunc(rs)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a query that returns a scalar result
|
||||
*
|
||||
* @param query The query to retrieve the result
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The scalar value from the query
|
||||
*/
|
||||
inline fun <reified T : Any> scalar(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> T
|
||||
) = Configuration.dbConn().use { scalar(query, parameters, it, mapFunc) }
|
||||
}
|
||||
71
src/kotlinx/src/main/kotlin/Definition.kt
Normal file
71
src/kotlinx/src/main/kotlin/Definition.kt
Normal file
@@ -0,0 +1,71 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import solutions.bitbadger.documents.DocumentIndex
|
||||
import solutions.bitbadger.documents.java.Definition as JvmDefinition
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to define tables and indexes
|
||||
*/
|
||||
object Definition {
|
||||
|
||||
/**
|
||||
* Create a document table if necessary
|
||||
*
|
||||
* @param tableName The table whose existence should be ensured (may include schema)
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
fun ensureTable(tableName: String, conn: Connection) =
|
||||
JvmDefinition.ensureTable(tableName, conn)
|
||||
|
||||
/**
|
||||
* Create a document table if necessary
|
||||
*
|
||||
* @param tableName The table whose existence should be ensured (may include schema)
|
||||
*/
|
||||
fun ensureTable(tableName: String) =
|
||||
JvmDefinition.ensureTable(tableName)
|
||||
|
||||
/**
|
||||
* Create an index on field(s) within documents in the specified table if necessary
|
||||
*
|
||||
* @param tableName The table to be indexed (may include schema)
|
||||
* @param indexName The name of the index to create
|
||||
* @param fields One or more fields to be indexed<
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>, conn: Connection) =
|
||||
JvmDefinition.ensureFieldIndex(tableName, indexName, fields, conn)
|
||||
|
||||
/**
|
||||
* Create an index on field(s) within documents in the specified table if necessary
|
||||
*
|
||||
* @param tableName The table to be indexed (may include schema)
|
||||
* @param indexName The name of the index to create
|
||||
* @param fields One or more fields to be indexed<
|
||||
*/
|
||||
fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) =
|
||||
JvmDefinition.ensureFieldIndex(tableName, indexName, fields)
|
||||
|
||||
/**
|
||||
* Create a document index on a table (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table to be indexed (may include schema)
|
||||
* @param indexType The type of index to ensure
|
||||
* @param conn The connection on which the query should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex, conn: Connection) =
|
||||
JvmDefinition.ensureDocumentIndex(tableName, indexType, conn)
|
||||
|
||||
/**
|
||||
* Create a document index on a table (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table to be indexed (may include schema)
|
||||
* @param indexType The type of index to ensure
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex) =
|
||||
JvmDefinition.ensureDocumentIndex(tableName, indexType)
|
||||
}
|
||||
95
src/kotlinx/src/main/kotlin/Delete.kt
Normal file
95
src/kotlinx/src/main/kotlin/Delete.kt
Normal file
@@ -0,0 +1,95 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.java.Delete as JvmDelete
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.query.DeleteQuery
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to delete documents
|
||||
*/
|
||||
object Delete {
|
||||
|
||||
/**
|
||||
* Delete a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param docId The ID of the document to be deleted
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
JvmDelete.byId(tableName, docId, conn)
|
||||
|
||||
/**
|
||||
* Delete a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param docId The ID of the document to be deleted
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey) =
|
||||
JvmDelete.byId(tableName, docId)
|
||||
|
||||
/**
|
||||
* Delete documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) =
|
||||
JvmDelete.byFields(tableName, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Delete documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
JvmDelete.byFields(tableName, fields, howMatched)
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
conn.customNonQuery(DeleteQuery.byContains(tableName), listOf(Parameters.json<TContains>(":criteria", criteria)))
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) =
|
||||
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
JvmDelete.byJsonPath(tableName, path, conn)
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param path The JSON path comparison to match
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String) =
|
||||
JvmDelete.byJsonPath(tableName, path)
|
||||
}
|
||||
114
src/kotlinx/src/main/kotlin/Document.kt
Normal file
114
src/kotlinx/src/main/kotlin/Document.kt
Normal file
@@ -0,0 +1,114 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.AutoId
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import solutions.bitbadger.documents.Dialect
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.customNonQuery
|
||||
import solutions.bitbadger.documents.query.DocumentQuery
|
||||
import solutions.bitbadger.documents.query.Where
|
||||
import solutions.bitbadger.documents.query.statementWhere
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions for manipulating documents
|
||||
*/
|
||||
object Document {
|
||||
|
||||
/**
|
||||
* Insert a new document
|
||||
*
|
||||
* @param tableName The table into which the document should be inserted (may include schema)
|
||||
* @param document The document to be inserted
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
inline fun <reified TDoc> insert(tableName: String, document: TDoc, conn: Connection) {
|
||||
val strategy = Configuration.autoIdStrategy
|
||||
val query = if (strategy == AutoId.DISABLED) {
|
||||
DocumentQuery.insert(tableName)
|
||||
} else {
|
||||
val idField = Configuration.idField
|
||||
val dialect = Configuration.dialect("Create auto-ID insert query")
|
||||
val dataParam = if (AutoId.needsAutoId(strategy, document, idField)) {
|
||||
when (dialect) {
|
||||
Dialect.POSTGRESQL ->
|
||||
when (strategy) {
|
||||
AutoId.NUMBER -> "' || (SELECT coalesce(max(data->>'$idField')::numeric, 0) + 1 " +
|
||||
"FROM $tableName) || '"
|
||||
AutoId.UUID -> "\"${AutoId.generateUUID()}\""
|
||||
AutoId.RANDOM_STRING -> "\"${AutoId.generateRandomString()}\""
|
||||
else -> "\"' || (:data)->>'$idField' || '\""
|
||||
}.let { ":data::jsonb || ('{\"$idField\":$it}')::jsonb" }
|
||||
|
||||
Dialect.SQLITE ->
|
||||
when (strategy) {
|
||||
AutoId.NUMBER -> "(SELECT coalesce(max(data->>'$idField'), 0) + 1 FROM $tableName)"
|
||||
AutoId.UUID -> "'${AutoId.generateUUID()}'"
|
||||
AutoId.RANDOM_STRING -> "'${AutoId.generateRandomString()}'"
|
||||
else -> "(:data)->>'$idField'"
|
||||
}.let { "json_set(:data, '$.$idField', $it)" }
|
||||
}
|
||||
} else {
|
||||
":data"
|
||||
}
|
||||
|
||||
DocumentQuery.insert(tableName).replace(":data", dataParam)
|
||||
}
|
||||
conn.customNonQuery(query, listOf(Parameters.json(":data", document)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new document
|
||||
*
|
||||
* @param tableName The table into which the document should be inserted (may include schema)
|
||||
* @param document The document to be inserted
|
||||
*/
|
||||
inline fun <reified TDoc> insert(tableName: String, document: TDoc) =
|
||||
Configuration.dbConn().use { insert(tableName, document, it) }
|
||||
|
||||
/**
|
||||
* Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
*
|
||||
* @param tableName The table in which the document should be saved (may include schema)
|
||||
* @param document The document to be saved
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
inline fun <reified TDoc> save(tableName: String, document: TDoc, conn: Connection) =
|
||||
conn.customNonQuery(DocumentQuery.save(tableName), listOf(Parameters.json(":data", document)))
|
||||
|
||||
/**
|
||||
* Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
*
|
||||
* @param tableName The table in which the document should be saved (may include schema)
|
||||
* @param document The document to be saved
|
||||
*/
|
||||
inline fun <reified TDoc> save(tableName: String, document: TDoc) =
|
||||
Configuration.dbConn().use { save(tableName, document, it) }
|
||||
|
||||
/**
|
||||
* Update (replace) a document by its ID
|
||||
*
|
||||
* @param tableName The table in which the document should be replaced (may include schema)
|
||||
* @param docId The ID of the document to be replaced
|
||||
* @param document The document to be replaced
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
inline fun <TKey, reified TDoc> update(tableName: String, docId: TKey, document: TDoc, conn: Connection) =
|
||||
conn.customNonQuery(
|
||||
statementWhere(DocumentQuery.update(tableName), Where.byId(":id", docId)),
|
||||
Parameters.addFields(
|
||||
listOf(Field.equal(Configuration.idField, docId, ":id")),
|
||||
mutableListOf(Parameters.json(":data", document))
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Update (replace) a document by its ID
|
||||
*
|
||||
* @param tableName The table in which the document should be replaced (may include schema)
|
||||
* @param docId The ID of the document to be replaced
|
||||
* @param document The document to be replaced
|
||||
*/
|
||||
inline fun <TKey, reified TDoc> update(tableName: String, docId: TKey, document: TDoc) =
|
||||
Configuration.dbConn().use { update(tableName, docId, document, it) }
|
||||
}
|
||||
33
src/kotlinx/src/main/kotlin/DocumentConfig.kt
Normal file
33
src/kotlinx/src/main/kotlin/DocumentConfig.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
/**
|
||||
* Configuration for document serialization
|
||||
*/
|
||||
object DocumentConfig {
|
||||
|
||||
val options = Json {
|
||||
coerceInputValues = true
|
||||
encodeDefaults = true
|
||||
explicitNulls = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a document to JSON
|
||||
*
|
||||
* @param document The document to be serialized
|
||||
* @return The JSON string with the serialized document
|
||||
*/
|
||||
inline fun <reified TDoc> serialize(document: TDoc) =
|
||||
options.encodeToString(document)
|
||||
|
||||
/**
|
||||
* Deserialize a document from JSON
|
||||
*
|
||||
* @param json The JSON string with the serialized document
|
||||
* @return The document created from the given JSON
|
||||
*/
|
||||
inline fun <reified TDoc> deserialize(json: String) =
|
||||
options.decodeFromString<TDoc>(json)
|
||||
}
|
||||
107
src/kotlinx/src/main/kotlin/Exists.kt
Normal file
107
src/kotlinx/src/main/kotlin/Exists.kt
Normal file
@@ -0,0 +1,107 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.java.Exists as JvmExists
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.query.ExistsQuery
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to determine whether documents exist
|
||||
*/
|
||||
object Exists {
|
||||
|
||||
/**
|
||||
* Determine a document's existence by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param docId The ID of the document to be checked
|
||||
* @param conn The connection on which the existence check should be executed
|
||||
* @return True if the document exists, false if not
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
JvmExists.byId(tableName, docId, conn)
|
||||
|
||||
/**
|
||||
* Determine a document's existence by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param docId The ID of the document to be checked
|
||||
* @return True if the document exists, false if not
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey) =
|
||||
JvmExists.byId(tableName, docId)
|
||||
|
||||
/**
|
||||
* Determine document existence using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection on which the existence check should be executed
|
||||
* @return True if any matching documents exist, false if not
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) =
|
||||
JvmExists.byFields(tableName, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Determine document existence using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @return True if any matching documents exist, false if not
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
JvmExists.byFields(tableName, fields, howMatched)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @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 conn The connection on which the existence check should be executed
|
||||
* @return True if any matching documents exist, false if not
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
conn.customScalar(
|
||||
ExistsQuery.byContains(tableName),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
Results::toExists
|
||||
)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @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
|
||||
* @return True if any matching documents exist, false if not
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) =
|
||||
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection on which the existence check should be executed
|
||||
* @return True if any matching documents exist, false if not
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
JvmExists.byJsonPath(tableName, path, conn)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param path The JSON path comparison to match
|
||||
* @return True if any matching documents exist, false if not
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String) =
|
||||
JvmExists.byJsonPath(tableName, path)
|
||||
}
|
||||
417
src/kotlinx/src/main/kotlin/Find.kt
Normal file
417
src/kotlinx/src/main/kotlin/Find.kt
Normal file
@@ -0,0 +1,417 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.query.FindQuery
|
||||
import solutions.bitbadger.documents.query.orderBy
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to find and retrieve documents
|
||||
*/
|
||||
object Find {
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table, ordering results by the optional given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents from the given table
|
||||
*/
|
||||
inline fun <reified TDoc : Any> all(tableName: String, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
conn.customList<TDoc>(FindQuery.all(tableName) + (orderBy?.let(::orderBy) ?: ""), mapFunc = Results::fromData)
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents from the given table
|
||||
*/
|
||||
inline fun <reified TDoc : Any> all(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Configuration.dbConn().use { all<TDoc>(tableName, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents from the given table
|
||||
*/
|
||||
inline fun <reified TDoc : Any> all(tableName: String, conn: Connection) =
|
||||
all<TDoc>(tableName, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The document if it is found, `null` otherwise
|
||||
*/
|
||||
inline fun <TKey, reified TDoc : Any> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
conn.customSingle<TDoc>(
|
||||
FindQuery.byId(tableName, docId),
|
||||
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))),
|
||||
Results::fromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @return The document if it is found, `null` otherwise
|
||||
*/
|
||||
inline fun <TKey, reified TDoc : Any> byId(tableName: String, docId: TKey) =
|
||||
Configuration.dbConn().use { byId<TKey, TDoc>(tableName, docId, it) }
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison, ordering results by the given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
): List<TDoc> {
|
||||
val named = Parameters.nameFields(fields)
|
||||
return conn.customList<TDoc>(
|
||||
FindQuery.byFields(tableName, named, howMatched) + (orderBy?.let(::orderBy) ?: ""),
|
||||
Parameters.addFields(named),
|
||||
Results::fromData
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison, ordering results by the given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) =
|
||||
Configuration.dbConn().use { byFields<TDoc>(tableName, fields, howMatched, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
byFields<TDoc>(tableName, fields, 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 : Any> 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)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
conn.customList<TDoc>(
|
||||
FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
Results::fromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) =
|
||||
Configuration.dbConn().use { byContains<TDoc, TContains>(tableName, criteria, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
conn: Connection
|
||||
) =
|
||||
byContains<TDoc, TContains>(tableName, criteria, 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 : Any, 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)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any> byJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
conn.customList<TDoc>(
|
||||
FindQuery.byJsonPath(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameter(":path", ParameterType.STRING, path)),
|
||||
Results::fromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any> byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Configuration.dbConn().use { byJsonPath<TDoc>(tableName, path, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any> byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
byJsonPath<TDoc>(tableName, path, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first document matching the field comparison, or `null` if no matches are found
|
||||
*/
|
||||
inline fun <reified TDoc : Any> firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
): TDoc? {
|
||||
val named = Parameters.nameFields(fields)
|
||||
return conn.customSingle<TDoc>(
|
||||
FindQuery.byFields(tableName, named, howMatched) + (orderBy?.let(::orderBy) ?: ""),
|
||||
Parameters.addFields(named),
|
||||
Results::fromData
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first document matching the field comparison, or `null` if no matches are found
|
||||
*/
|
||||
inline fun <reified TDoc : Any> firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) =
|
||||
Configuration.dbConn().use { firstByFields<TDoc>(tableName, fields, howMatched, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first document matching the field comparison, or `null` if no matches are found
|
||||
*/
|
||||
inline fun <reified TDoc : Any> firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
firstByFields<TDoc>(tableName, fields, howMatched, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first document matching the JSON containment query, or `null` if no matches are found
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
conn.customSingle<TDoc>(
|
||||
FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
Results::fromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first document matching the JSON containment query, or `null` if no matches are found
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
conn: Connection
|
||||
) =
|
||||
firstByContains<TDoc, TContains>(tableName, criteria, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first document matching the JSON containment query, or `null` if no matches are found
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) =
|
||||
Configuration.dbConn().use { firstByContains<TDoc, TContains>(tableName, criteria, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first document matching the JSON Path match query, or `null` if no matches are found
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any> firstByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
conn.customSingle<TDoc>(
|
||||
FindQuery.byJsonPath(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameter(":path", ParameterType.STRING, path)),
|
||||
Results::fromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first document matching the JSON Path match query, or `null` if no matches are found
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any> firstByJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
firstByJsonPath<TDoc>(tableName, path, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @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
|
||||
*/
|
||||
inline fun <reified TDoc : Any> firstByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) =
|
||||
Configuration.dbConn().use { firstByJsonPath<TDoc>(tableName, path, orderBy, it) }
|
||||
}
|
||||
731
src/kotlinx/src/main/kotlin/Json.kt
Normal file
731
src/kotlinx/src/main/kotlin/Json.kt
Normal file
@@ -0,0 +1,731 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.query.FindQuery
|
||||
import solutions.bitbadger.documents.query.orderBy
|
||||
import java.io.PrintWriter
|
||||
import solutions.bitbadger.documents.java.Json as CoreJson
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to find and retrieve documents, returning them as JSON strings
|
||||
*/
|
||||
object Json {
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table, ordering results by the optional given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents from the given table
|
||||
* @throws DocumentException If query execution fails
|
||||
*/
|
||||
fun all(tableName: String, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
CoreJson.all(tableName, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table (creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents from the given table
|
||||
* @throws DocumentException If no connection string has been set, or if query execution fails
|
||||
*/
|
||||
fun all(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
CoreJson.all(tableName, orderBy)
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents from the given table
|
||||
* @throws DocumentException If query execution fails
|
||||
*/
|
||||
fun all(tableName: String, conn: Connection) =
|
||||
CoreJson.all(tableName, conn)
|
||||
|
||||
/**
|
||||
* Write all documents in the given table to the given `PrintWriter`, ordering results by the optional given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @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
|
||||
* @throws DocumentException If query execution fails
|
||||
*/
|
||||
fun writeAll(tableName: String, writer: PrintWriter, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
CoreJson.writeAll(tableName, writer, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Write all documents in the given table to the given `PrintWriter`, ordering results by the optional given fields
|
||||
* (creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If query execution fails
|
||||
*/
|
||||
fun writeAll(tableName: String, writer: PrintWriter, orderBy: Collection<Field<*>>? = null) =
|
||||
CoreJson.writeAll(tableName, writer, orderBy)
|
||||
|
||||
/**
|
||||
* Write all documents in the given table to the given `PrintWriter`
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If query execution fails
|
||||
*/
|
||||
fun writeAll(tableName: String, writer: PrintWriter, conn: Connection) =
|
||||
CoreJson.writeAll(tableName, writer, conn)
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON document if found, an empty JSON object if not found
|
||||
* @throws DocumentException If no dialect has been configured
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
CoreJson.byId(tableName, docId, conn)
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID (creates connection)
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @return A JSON document if found, an empty JSON object if not found
|
||||
* @throws DocumentException If no connection string has been set
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey) =
|
||||
CoreJson.byId(tableName, docId)
|
||||
|
||||
/**
|
||||
* Write a document to the given `PrintWriter` by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If no dialect has been configured
|
||||
*/
|
||||
fun <TKey> writeById(tableName: String, writer: PrintWriter, docId: TKey, conn: Connection) =
|
||||
CoreJson.writeById(tableName, writer, docId, conn)
|
||||
|
||||
/**
|
||||
* Write a document to the given `PrintWriter` by its ID (creates connection)
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @throws DocumentException If no dialect has been configured
|
||||
*/
|
||||
fun <TKey> writeById(tableName: String, writer: PrintWriter, docId: TKey) =
|
||||
CoreJson.writeById(tableName, writer, docId)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison, ordering results by the given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents matching the field comparison
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.byFields(tableName, fields, howMatched, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison, ordering results by the given fields (creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents matching the field comparison
|
||||
* @throws DocumentException If no connection string has been set, or if parameters are invalid
|
||||
*/
|
||||
fun byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = CoreJson.byFields(tableName, fields, howMatched, orderBy)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents matching the field comparison
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) =
|
||||
CoreJson.byFields(tableName, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a field comparison, ordering results by the given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun writeByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.writeByFields(tableName, writer, fields, howMatched, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a field comparison, ordering results by the given fields
|
||||
* (creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun writeByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = CoreJson.writeByFields(tableName, writer, fields, howMatched, orderBy)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a field comparison
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun writeByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.writeByFields(tableName, writer, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = Custom.jsonArray(
|
||||
FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
conn,
|
||||
Results::jsonFromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only; creates
|
||||
* connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents matching the JSON containment query
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Configuration.dbConn().use { byContains(tableName, criteria, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
byContains(tableName, criteria, null, conn)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a JSON containment query, ordering results by the given fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> writeByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = Custom.writeJsonArray(
|
||||
FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
writer,
|
||||
conn,
|
||||
Results::jsonFromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a JSON containment query, ordering results by the given fields
|
||||
* (PostgreSQL only; creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> writeByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Configuration.dbConn().use { writeByContains(tableName, writer, criteria, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a JSON containment query, ordering results by the given fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> writeByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
conn: Connection
|
||||
) = writeByContains(tableName, writer, criteria, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
CoreJson.byJsonPath(tableName, path, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only; creates
|
||||
* connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents matching the JSON Path match query
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
CoreJson.byJsonPath(tableName, path, orderBy)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A JSON array of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
CoreJson.byJsonPath(tableName, path, conn)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` 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 writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun writeByJsonPath(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.writeByJsonPath(tableName, writer, path, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a JSON Path match query, ordering results by the given fields
|
||||
* (PostgreSQL only; creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun writeByJsonPath(tableName: String, writer: PrintWriter, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
CoreJson.writeByJsonPath(tableName, writer, path, orderBy)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun writeByJsonPath(tableName: String, writer: PrintWriter, path: String, conn: Connection) =
|
||||
CoreJson.writeByJsonPath(tableName, writer, path, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first JSON document matching the field comparison if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.firstByFields(tableName, fields, howMatched, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison and optional ordering fields (creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first JSON document matching the field comparison if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no connection string has been set, or if parameters are invalid
|
||||
*/
|
||||
fun firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = CoreJson.firstByFields(tableName, fields, howMatched, orderBy)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first JSON document matching the field comparison if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.firstByFields(tableName, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun writeFirstByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.writeFirstByFields(tableName, writer, fields, howMatched, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a field comparison and optional ordering fields
|
||||
* (creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun writeFirstByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = CoreJson.writeFirstByFields(tableName, writer, fields, howMatched, orderBy)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a field comparison
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If no dialect has been configured, or if parameters are invalid
|
||||
*/
|
||||
fun writeFirstByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.writeFirstByFields(tableName, writer, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = Custom.jsonSingle(
|
||||
FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
conn,
|
||||
Results::jsonFromData
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> firstByContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
firstByContains(tableName, criteria, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only; creates
|
||||
* connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Configuration.dbConn().use { firstByContains(tableName, criteria, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON containment query and optional ordering fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> writeFirstByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = writer.write(
|
||||
Custom.jsonSingle(
|
||||
FindQuery.byContains(tableName) + (orderBy?.let(::orderBy) ?: ""),
|
||||
listOf(Parameters.json(":criteria", criteria)),
|
||||
conn,
|
||||
Results::jsonFromData
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON containment query and optional ordering fields
|
||||
* (PostgreSQL only; creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> writeFirstByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Configuration.dbConn().use { writeFirstByContains<TContains>(tableName, writer, criteria, orderBy, it) }
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> writeFirstByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
conn: Connection
|
||||
) = writeFirstByContains<TContains>(tableName, writer, criteria, null, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun firstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
CoreJson.firstByJsonPath(tableName, path, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun firstByJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
CoreJson.firstByJsonPath(tableName, path, conn)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only; creates
|
||||
* connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
fun firstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
CoreJson.firstByJsonPath(tableName, path, orderBy)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON Path match query and optional ordering fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun writeFirstByJsonPath(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
conn: Connection
|
||||
) = CoreJson.writeFirstByJsonPath(tableName, writer, path, orderBy, conn)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON Path match query and optional ordering fields
|
||||
* (PostgreSQL only; creates connection)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun writeFirstByJsonPath(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = CoreJson.writeFirstByJsonPath(tableName, writer, path, orderBy)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun writeFirstByJsonPath(tableName: String, writer: PrintWriter, path: String, conn: Connection) =
|
||||
CoreJson.writeFirstByJsonPath(tableName, writer, path, conn)
|
||||
}
|
||||
77
src/kotlinx/src/main/kotlin/Parameters.kt
Normal file
77
src/kotlinx/src/main/kotlin/Parameters.kt
Normal file
@@ -0,0 +1,77 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.ParameterType
|
||||
import solutions.bitbadger.documents.java.Parameters as JvmParameters
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to assist with the creation and implementation of parameters for SQL queries
|
||||
*
|
||||
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||
*/
|
||||
object Parameters {
|
||||
|
||||
/**
|
||||
* Assign parameter names to any fields that do not have them assigned
|
||||
*
|
||||
* @param fields The collection of fields to be named
|
||||
* @return The collection of fields with parameter names assigned
|
||||
*/
|
||||
fun nameFields(fields: Collection<Field<*>>): Collection<Field<*>> =
|
||||
JvmParameters.nameFields(fields)
|
||||
|
||||
/**
|
||||
* Create a parameter by encoding a JSON object
|
||||
*
|
||||
* @param name The parameter name
|
||||
* @param value The object to be encoded as JSON
|
||||
* @return A parameter with the value encoded
|
||||
*/
|
||||
inline fun <reified T> json(name: String, value: T) =
|
||||
Parameter(name, ParameterType.JSON, DocumentConfig.serialize<T>(value))
|
||||
|
||||
/**
|
||||
* Add field parameters to the given set of parameters
|
||||
*
|
||||
* @param fields The fields being compared in the query
|
||||
* @param existing Any existing parameters for the query (optional, defaults to empty collection)
|
||||
* @return A collection of parameters for the query
|
||||
*/
|
||||
fun addFields(fields: Collection<Field<*>>, existing: MutableCollection<Parameter<*>> = mutableListOf()) =
|
||||
JvmParameters.addFields(fields, existing)
|
||||
|
||||
/**
|
||||
* Replace the parameter names in the query with question marks
|
||||
*
|
||||
* @param query The query with named placeholders
|
||||
* @param parameters The parameters for the query
|
||||
* @return The query, with name parameters changed to `?`s
|
||||
*/
|
||||
fun replaceNamesInQuery(query: String, parameters: Collection<Parameter<*>>) =
|
||||
JvmParameters.replaceNamesInQuery(query, parameters)
|
||||
|
||||
/**
|
||||
* Apply the given parameters to the given query, returning a prepared statement
|
||||
*
|
||||
* @param conn The active JDBC connection
|
||||
* @param query The query
|
||||
* @param parameters The parameters for the query
|
||||
* @return A `PreparedStatement` with the parameter names replaced with `?` and parameter values bound
|
||||
* @throws DocumentException If parameter names are invalid or number value types are invalid
|
||||
*/
|
||||
fun apply(conn: Connection, query: String, parameters: Collection<Parameter<*>>) =
|
||||
JvmParameters.apply(conn, query, parameters)
|
||||
|
||||
/**
|
||||
* Create parameters for field names to be removed from a document
|
||||
*
|
||||
* @param names The names of the fields to be removed
|
||||
* @param parameterName The parameter name to use for the query
|
||||
* @return A list of parameters to use for building the query
|
||||
* @throws DocumentException If the dialect has not been set
|
||||
*/
|
||||
fun fieldNames(names: Collection<String>, parameterName: String = ":name") =
|
||||
JvmParameters.fieldNames(names, parameterName)
|
||||
}
|
||||
137
src/kotlinx/src/main/kotlin/Patch.kt
Normal file
137
src/kotlinx/src/main/kotlin/Patch.kt
Normal file
@@ -0,0 +1,137 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.query.PatchQuery
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to patch (partially update) documents
|
||||
*/
|
||||
object Patch {
|
||||
|
||||
/**
|
||||
* Patch a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which a document should 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 conn The connection on which the update should be executed
|
||||
*/
|
||||
inline fun <TKey, reified TPatch> byId(tableName: String, docId: TKey, patch: TPatch, conn: Connection) =
|
||||
conn.customNonQuery(
|
||||
PatchQuery.byId(tableName, docId),
|
||||
Parameters.addFields(
|
||||
listOf(Field.equal(Configuration.idField, docId, ":id")),
|
||||
mutableListOf(Parameters.json(":data", patch))
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Patch a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which a document should be patched
|
||||
* @param docId The ID of the document to be patched
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
*/
|
||||
inline fun <TKey, reified TPatch> byId(tableName: String, docId: TKey, patch: TPatch) =
|
||||
Configuration.dbConn().use { byId(tableName, docId, patch, it) }
|
||||
|
||||
/**
|
||||
* Patch documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param fields The fields which should be compared
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection on which the update should be executed
|
||||
*/
|
||||
inline fun <reified TPatch> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
patch: TPatch,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) {
|
||||
val named = Parameters.nameFields(fields)
|
||||
conn.customNonQuery(
|
||||
PatchQuery.byFields(tableName, named, howMatched), Parameters.addFields(
|
||||
named,
|
||||
mutableListOf(Parameters.json(":data", patch))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param fields The fields which should be compared
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
inline fun <reified TPatch> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
patch: TPatch,
|
||||
howMatched: FieldMatch? = null
|
||||
) =
|
||||
Configuration.dbConn().use { byFields(tableName, fields, patch, howMatched, it) }
|
||||
|
||||
/**
|
||||
* Patch documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param criteria The object against which JSON containment should be checked
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @param conn The connection on which the update should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains, reified TPatch> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
patch: TPatch,
|
||||
conn: Connection
|
||||
) =
|
||||
conn.customNonQuery(
|
||||
PatchQuery.byContains(tableName),
|
||||
listOf(Parameters.json(":criteria", criteria), Parameters.json(":data", patch))
|
||||
)
|
||||
|
||||
/**
|
||||
* Patch documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param criteria The object against which JSON containment should be checked
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains, reified TPatch> byContains(tableName: String, criteria: TContains, patch: TPatch) =
|
||||
Configuration.dbConn().use { byContains(tableName, criteria, patch, it) }
|
||||
|
||||
/**
|
||||
* Patch documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param path The JSON path comparison to match
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @param conn The connection on which the update should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TPatch> byJsonPath(tableName: String, path: String, patch: TPatch, conn: Connection) =
|
||||
conn.customNonQuery(
|
||||
PatchQuery.byJsonPath(tableName),
|
||||
listOf(Parameter(":path", ParameterType.STRING, path), Parameters.json(":data", patch))
|
||||
)
|
||||
|
||||
/**
|
||||
* Patch documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param path The JSON path comparison to match
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TPatch> byJsonPath(tableName: String, path: String, patch: TPatch) =
|
||||
Configuration.dbConn().use { byJsonPath(tableName, path, patch, it) }
|
||||
}
|
||||
124
src/kotlinx/src/main/kotlin/RemoveFields.kt
Normal file
124
src/kotlinx/src/main/kotlin/RemoveFields.kt
Normal file
@@ -0,0 +1,124 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.java.RemoveFields as JvmRemoveFields
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.query.RemoveFieldsQuery
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Functions to remove fields from documents
|
||||
*/
|
||||
object RemoveFields {
|
||||
|
||||
/**
|
||||
* Remove fields from a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which the document's fields should be removed
|
||||
* @param docId The ID of the document to have fields removed
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @param conn The connection on which the update should be executed
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>, conn: Connection) =
|
||||
JvmRemoveFields.byId(tableName, docId, toRemove, conn)
|
||||
|
||||
/**
|
||||
* Remove fields from a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which the document's fields should be removed
|
||||
* @param docId The ID of the document to have fields removed
|
||||
* @param toRemove The names of the fields to be removed
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>) =
|
||||
JvmRemoveFields.byId(tableName, docId, toRemove)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param fields The fields which should be compared
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param conn The connection on which the update should be executed
|
||||
*/
|
||||
fun byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
toRemove: Collection<String>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) =
|
||||
JvmRemoveFields.byFields(tableName, fields, toRemove, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param fields The fields which should be compared
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
fun byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
toRemove: Collection<String>,
|
||||
howMatched: FieldMatch? = null
|
||||
) =
|
||||
JvmRemoveFields.byFields(tableName, fields, toRemove, howMatched)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param criteria The object against which JSON containment should be checked
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @param conn The connection on which the update should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
toRemove: Collection<String>,
|
||||
conn: Connection
|
||||
) {
|
||||
val nameParams = Parameters.fieldNames(toRemove)
|
||||
conn.customNonQuery(
|
||||
RemoveFieldsQuery.byContains(tableName, nameParams),
|
||||
listOf(Parameters.json(":criteria", criteria), *nameParams.toTypedArray())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param criteria The object against which JSON containment should be checked
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, toRemove: Collection<String>) =
|
||||
Configuration.dbConn().use { byContains(tableName, criteria, toRemove, it) }
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param path The JSON path comparison to match
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @param conn The connection on which the update should be executed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>, conn: Connection) =
|
||||
JvmRemoveFields.byJsonPath(tableName, path, toRemove, conn)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param path The JSON path comparison to match
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>) =
|
||||
JvmRemoveFields.byJsonPath(tableName, path, toRemove)
|
||||
}
|
||||
107
src/kotlinx/src/main/kotlin/Results.kt
Normal file
107
src/kotlinx/src/main/kotlin/Results.kt
Normal file
@@ -0,0 +1,107 @@
|
||||
package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import solutions.bitbadger.documents.Dialect
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import solutions.bitbadger.documents.java.Results as CoreResults
|
||||
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
|
||||
* @return A function to create the constructed domain item
|
||||
*/
|
||||
inline fun <reified TDoc> fromDocument(field: String): (ResultSet) -> TDoc =
|
||||
{ rs -> DocumentConfig.deserialize<TDoc>(rs.getString(field)) }
|
||||
|
||||
/**
|
||||
* Create a domain item from a document
|
||||
*
|
||||
* @return The constructed domain item
|
||||
*/
|
||||
inline fun <reified TDoc> fromData(rs: ResultSet) =
|
||||
fromDocument<TDoc>("data")(rs)
|
||||
|
||||
/**
|
||||
* 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) =
|
||||
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) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.POSTGRESQL -> rs.getBoolean("it")
|
||||
Dialect.SQLITE -> toCount(rs) > 0L
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the JSON text of 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 JSON text of the document
|
||||
*/
|
||||
fun jsonFromDocument(field: String, rs: ResultSet) =
|
||||
CoreResults.jsonFromDocument(field, rs)
|
||||
|
||||
/**
|
||||
* Retrieve the JSON text of a document, specifying the field in which the document is found
|
||||
*
|
||||
* @param rs A `ResultSet` set to the row with the document to be constructed
|
||||
* @return The JSON text of the document
|
||||
*/
|
||||
fun jsonFromData(rs: ResultSet) =
|
||||
CoreResults.jsonFromData(rs)
|
||||
|
||||
/**
|
||||
* Create a JSON array 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 JSON text
|
||||
* @return A string with a JSON array of documents from the query's result
|
||||
* @throws DocumentException If there is a problem executing the query (unchecked)
|
||||
*/
|
||||
fun toJsonArray(stmt: PreparedStatement, mapFunc: (ResultSet) -> String) =
|
||||
CoreResults.toJsonArray(stmt, mapFunc)
|
||||
}
|
||||
750
src/kotlinx/src/main/kotlin/extensions/Connection.kt
Normal file
750
src/kotlinx/src/main/kotlin/extensions/Connection.kt
Normal file
@@ -0,0 +1,750 @@
|
||||
package solutions.bitbadger.documents.kotlinx.extensions
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.*
|
||||
import java.io.PrintWriter
|
||||
import java.sql.Connection
|
||||
import java.sql.ResultSet
|
||||
|
||||
// ~~~ CUSTOM QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Execute a query that returns a list of results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return A list of results for the given query
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.customList(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> TDoc
|
||||
) = Custom.list(query, parameters, this, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns a JSON array of results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function to extract the JSON from the query
|
||||
* @return A JSON array of results for the given query
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun Connection.customJsonArray(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = Custom.jsonArray(query, parameters, this, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query, writing its JSON array of results to the given `PrintWriter` (creates connection)
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param writer The writer to which the results should be written
|
||||
* @param mapFunc The mapping function to extract the JSON from the query
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun Connection.writeCustomJsonArray(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
writer: PrintWriter,
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = Custom.writeJsonArray(query, parameters, writer, this, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns one or no results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The document if one matches the query, `null` otherwise
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.customSingle(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> TDoc
|
||||
) = Custom.single(query, parameters, this, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns JSON for one or no documents (creates connection)
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The JSON for the document if found, an empty object (`{}`) if not
|
||||
* @throws DocumentException If parameters are invalid
|
||||
*/
|
||||
fun Connection.customJsonSingle(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
mapFunc: (ResultSet) -> String
|
||||
) = Custom.jsonSingle(query, parameters, this, mapFunc)
|
||||
|
||||
/**
|
||||
* Execute a query that returns no results
|
||||
*
|
||||
* @param query The query to retrieve the results
|
||||
* @param parameters Parameters to use for the query
|
||||
*/
|
||||
fun Connection.customNonQuery(query: String, parameters: Collection<Parameter<*>> = listOf()) =
|
||||
Custom.nonQuery(query, parameters, this)
|
||||
|
||||
/**
|
||||
* Execute a query that returns a scalar result
|
||||
*
|
||||
* @param query The query to retrieve the result
|
||||
* @param parameters Parameters to use for the query
|
||||
* @param mapFunc The mapping function between the document and the domain item
|
||||
* @return The scalar value from the query
|
||||
*/
|
||||
inline fun <reified T : Any> Connection.customScalar(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
mapFunc: (ResultSet) -> T
|
||||
) = Custom.scalar(query, parameters, this, mapFunc)
|
||||
|
||||
// ~~~ DEFINITION QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Create a document table if necessary
|
||||
*
|
||||
* @param tableName The table whose existence should be ensured (may include schema)
|
||||
*/
|
||||
fun Connection.ensureTable(tableName: String) =
|
||||
Definition.ensureTable(tableName, this)
|
||||
|
||||
/**
|
||||
* Create an index on field(s) within documents in the specified table if necessary
|
||||
*
|
||||
* @param tableName The table to be indexed (may include schema)
|
||||
* @param indexName The name of the index to create
|
||||
* @param fields One or more fields to be indexed<
|
||||
*/
|
||||
fun Connection.ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) =
|
||||
Definition.ensureFieldIndex(tableName, indexName, fields, this)
|
||||
|
||||
/**
|
||||
* Create a document index on a table (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table to be indexed (may include schema)
|
||||
* @param indexType The type of index to ensure
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun Connection.ensureDocumentIndex(tableName: String, indexType: DocumentIndex) =
|
||||
Definition.ensureDocumentIndex(tableName, indexType, this)
|
||||
|
||||
// ~~~ DOCUMENT MANIPULATION QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Insert a new document
|
||||
*
|
||||
* @param tableName The table into which the document should be inserted (may include schema)
|
||||
* @param document The document to be inserted
|
||||
*/
|
||||
inline fun <reified TDoc> Connection.insert(tableName: String, document: TDoc) =
|
||||
Document.insert(tableName, document, this)
|
||||
|
||||
/**
|
||||
* Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
*
|
||||
* @param tableName The table in which the document should be saved (may include schema)
|
||||
* @param document The document to be saved
|
||||
*/
|
||||
inline fun <reified TDoc> Connection.save(tableName: String, document: TDoc) =
|
||||
Document.save(tableName, document, this)
|
||||
|
||||
/**
|
||||
* Update (replace) a document by its ID
|
||||
*
|
||||
* @param tableName The table in which the document should be replaced (may include schema)
|
||||
* @param docId The ID of 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) =
|
||||
Document.update(tableName, docId, document, this)
|
||||
|
||||
// ~~~ DOCUMENT COUNT QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Count all documents in the table
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @return A count of the documents in the table
|
||||
*/
|
||||
fun Connection.countAll(tableName: String) =
|
||||
Count.all(tableName, this)
|
||||
|
||||
/**
|
||||
* Count documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @return A count of the matching documents in the table
|
||||
*/
|
||||
fun Connection.countByFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Count.byFields(tableName, fields, howMatched, this)
|
||||
|
||||
/**
|
||||
* Count documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.countByContains(tableName: String, criteria: TContains) =
|
||||
Count.byContains(tableName, criteria, this)
|
||||
|
||||
/**
|
||||
* Count documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @param path The JSON path comparison to match
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun Connection.countByJsonPath(tableName: String, path: String) =
|
||||
Count.byJsonPath(tableName, path, this)
|
||||
|
||||
// ~~~ DOCUMENT EXISTENCE QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Determine a document's existence by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param docId The ID of the document to be checked
|
||||
* @return True if the document exists, false if not
|
||||
*/
|
||||
fun <TKey> Connection.existsById(tableName: String, docId: TKey) =
|
||||
Exists.byId(tableName, docId, this)
|
||||
|
||||
/**
|
||||
* Determine document existence using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @return True if any matching documents exist, false if not
|
||||
*/
|
||||
fun Connection.existsByFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Exists.byFields(tableName, fields, howMatched, this)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @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
|
||||
* @return True if any matching documents exist, false if not
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.existsByContains(tableName: String, criteria: TContains) =
|
||||
Exists.byContains(tableName, criteria, this)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document existence should be checked
|
||||
* @param path The JSON path comparison to match
|
||||
* @return True if any matching documents exist, false if not
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun Connection.existsByJsonPath(tableName: String, path: String) =
|
||||
Exists.byJsonPath(tableName, path, this)
|
||||
|
||||
// ~~~ DOCUMENT RETRIEVAL QUERIES (Domain Objects) ~~~
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table, ordering results by the optional given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents from the given table
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.findAll(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Find.all<TDoc>(tableName, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @return The document if it is found, `null` otherwise
|
||||
*/
|
||||
inline fun <TKey, reified TDoc : Any> Connection.findById(tableName: String, docId: TKey) =
|
||||
Find.byId<TKey, TDoc>(tableName, docId, this)
|
||||
|
||||
/**
|
||||
* 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 fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.findByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Find.byFields<TDoc>(tableName, fields, howMatched, orderBy, this)
|
||||
|
||||
/**
|
||||
* 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 criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> Connection.findByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Find.byContains<TDoc, TContains>(tableName, criteria, orderBy, this)
|
||||
|
||||
/**
|
||||
* 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 path The JSON path comparison to match
|
||||
* @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
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.findByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Find.byJsonPath<TDoc>(tableName, path, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first document matching the field comparison, or `null` if no matches are found
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.findFirstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Find.firstByFields<TDoc>(tableName, fields, howMatched, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first document matching the JSON containment query, or `null` if no matches are found
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc : Any, reified TContains> Connection.findFirstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Find.firstByContains<TDoc, TContains>(tableName, criteria, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @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
|
||||
*/
|
||||
inline fun <reified TDoc : Any> Connection.findFirstByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Find.firstByJsonPath<TDoc>(tableName, path, orderBy, this)
|
||||
|
||||
// ~~~ DOCUMENT RETRIEVAL QUERIES (Raw JSON) ~~~
|
||||
|
||||
/**
|
||||
* Retrieve all documents in the given table
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents from the given table
|
||||
* @throws DocumentException If no connection string has been set, or if query execution fails
|
||||
*/
|
||||
fun Connection.jsonAll(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Json.all(tableName, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @return A JSON document if found, an empty JSON object if not found
|
||||
* @throws DocumentException If no connection string has been set
|
||||
*/
|
||||
fun <TKey> Connection.jsonById(tableName: String, docId: TKey) =
|
||||
Json.byId(tableName, docId, this)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a field comparison, ordering results by the given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents matching the field comparison
|
||||
* @throws DocumentException If no connection string has been set, or if parameters are invalid
|
||||
*/
|
||||
fun Connection.jsonByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.byFields(tableName, fields, howMatched, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON containment query, ordering results by the given fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents matching the JSON containment query
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.jsonByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.byContains(tableName, criteria, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve documents using a JSON Path match query, ordering results by the given fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return A JSON array of documents matching the JSON Path match query
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
fun Connection.jsonByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Json.byJsonPath(tableName, path, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first JSON document matching the field comparison if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no connection string has been set, or if parameters are invalid
|
||||
*/
|
||||
fun Connection.jsonFirstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.firstByFields(tableName, fields, howMatched, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON containment query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first JSON document matching the JSON containment query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.jsonFirstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.firstByContains(tableName, criteria, orderBy, this)
|
||||
|
||||
/**
|
||||
* Retrieve the first document using a JSON Path match query and optional ordering fields (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @return The first JSON document matching the JSON Path match query if found, an empty JSON object otherwise
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
fun Connection.jsonFirstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Json.firstByJsonPath(tableName, path, orderBy, this)
|
||||
|
||||
// ~~~ DOCUMENT RETRIEVAL QUERIES (Write raw JSON to PrintWriter) ~~~
|
||||
|
||||
/**
|
||||
* Write all documents in the given table to the given `PrintWriter`, ordering results by the optional given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if query execution fails
|
||||
*/
|
||||
fun Connection.writeJsonAll(tableName: String, writer: PrintWriter, orderBy: Collection<Field<*>>? = null) =
|
||||
Json.writeAll(tableName, writer, orderBy, this)
|
||||
|
||||
/**
|
||||
* Write a document to the given `PrintWriter` by its ID
|
||||
*
|
||||
* @param tableName The table from which the document should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @throws DocumentException If no connection string has been set
|
||||
*/
|
||||
fun <TKey> Connection.writeJsonById(tableName: String, writer: PrintWriter, docId: TKey) =
|
||||
Json.writeById(tableName, writer, docId, this)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a field comparison, ordering results by the given fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if parameters are invalid
|
||||
*/
|
||||
fun Connection.writeJsonByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.writeByFields(tableName, writer, fields, howMatched, orderBy, this)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` using a JSON containment query, ordering results by the given fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.writeJsonByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.writeByContains(tableName, writer, criteria, orderBy, this)
|
||||
|
||||
/**
|
||||
* Write documents to the given `PrintWriter` 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 writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
fun Connection.writeJsonByJsonPath(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.writeByJsonPath(tableName, writer, path, orderBy, this)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a field comparison and optional ordering fields
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched (optional, defaults to `FieldMatch.ALL`)
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if parameters are invalid
|
||||
*/
|
||||
fun Connection.writeJsonFirstByFields(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.writeFirstByFields(tableName, writer, fields, howMatched, orderBy, this)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON containment query and optional ordering fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.writeJsonFirstByContains(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.writeFirstByContains(tableName, writer, criteria, orderBy, this)
|
||||
|
||||
/**
|
||||
* Write the first document to the given `PrintWriter` using a JSON Path match query and optional ordering fields
|
||||
* (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The table from which documents should be retrieved
|
||||
* @param writer The `PrintWriter` to which the results should be written
|
||||
* @param path The JSON path comparison to match
|
||||
* @param orderBy Fields by which the query should be ordered (optional, defaults to no ordering)
|
||||
* @throws DocumentException If no connection string has been set, or if called on a SQLite connection
|
||||
*/
|
||||
fun Connection.writeJsonFirstByJsonPath(
|
||||
tableName: String,
|
||||
writer: PrintWriter,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) = Json.writeFirstByJsonPath(tableName, writer, path, orderBy, this)
|
||||
|
||||
// ~~~ DOCUMENT PATCH (PARTIAL UPDATE) QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Patch a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which a document should be patched
|
||||
* @param docId The ID of the document to be patched
|
||||
* @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) =
|
||||
Patch.byId(tableName, docId, patch, this)
|
||||
|
||||
/**
|
||||
* Patch documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param fields The fields which should be compared
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
inline fun <reified TPatch> Connection.patchByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
patch: TPatch,
|
||||
howMatched: FieldMatch? = null
|
||||
) = Patch.byFields(tableName, fields, patch, howMatched, this)
|
||||
|
||||
/**
|
||||
* Patch documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param criteria The object against which JSON containment should be checked
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains, reified TPatch> Connection.patchByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
patch: TPatch
|
||||
) = Patch.byContains(tableName, criteria, patch, this)
|
||||
|
||||
/**
|
||||
* Patch documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which documents should be patched
|
||||
* @param path The JSON path comparison to match
|
||||
* @param patch The object whose properties should be replaced in the document
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TPatch> Connection.patchByJsonPath(tableName: String, path: String, patch: TPatch) =
|
||||
Patch.byJsonPath(tableName, path, patch, this)
|
||||
|
||||
// ~~~ DOCUMENT FIELD REMOVAL QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Remove fields from a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table in which the document's fields should be removed
|
||||
* @param docId The ID of the document to have fields removed
|
||||
* @param toRemove The names of the fields to be removed
|
||||
*/
|
||||
fun <TKey> Connection.removeFieldsById(tableName: String, docId: TKey, toRemove: Collection<String>) =
|
||||
RemoveFields.byId(tableName, docId, toRemove, this)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param fields The fields which should be compared
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
fun Connection.removeFieldsByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
toRemove: Collection<String>,
|
||||
howMatched: FieldMatch? = null
|
||||
) = RemoveFields.byFields(tableName, fields, toRemove, howMatched, this)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param criteria The object against which JSON containment should be checked
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.removeFieldsByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
toRemove: Collection<String>
|
||||
) = RemoveFields.byContains(tableName, criteria, toRemove, this)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table in which document fields should be removed
|
||||
* @param path The JSON path comparison to match
|
||||
* @param toRemove The names of the fields to be removed
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun Connection.removeFieldsByJsonPath(tableName: String, path: String, toRemove: Collection<String>) =
|
||||
RemoveFields.byJsonPath(tableName, path, toRemove, this)
|
||||
|
||||
// ~~~ DOCUMENT DELETION QUERIES ~~~
|
||||
|
||||
/**
|
||||
* Delete a document by its ID
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param docId The ID of the document to be deleted
|
||||
*/
|
||||
fun <TKey> Connection.deleteById(tableName: String, docId: TKey) =
|
||||
Delete.byId(tableName, docId, this)
|
||||
|
||||
/**
|
||||
* Delete documents using a field comparison
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param fields The fields which should be compared
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
fun Connection.deleteByFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Delete.byFields(tableName, fields, howMatched, this)
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param criteria The object for which JSON containment should be checked
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TContains> Connection.deleteByContains(tableName: String, criteria: TContains) =
|
||||
Delete.byContains(tableName, criteria, this)
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||
*
|
||||
* @param tableName The name of the table from which documents should be deleted
|
||||
* @param path The JSON path comparison to match
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun Connection.deleteByJsonPath(tableName: String, path: String) =
|
||||
Delete.byJsonPath(tableName, path, this)
|
||||
11
src/kotlinx/src/main/module-info.md
Normal file
11
src/kotlinx/src/main/module-info.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Module kotlinx
|
||||
|
||||
This module contains an implementation of the document store API which uses a `kotlinx.serialization`-based serializer (relies on reified generics)
|
||||
|
||||
# Package solutions.bitbadger.documents.kotlinx
|
||||
|
||||
The document store API based on `kotlinx.serialization`
|
||||
|
||||
# Package solutions.bitbadger.documents.kotlinx.extensions
|
||||
|
||||
Extensions on the Java `Connection` object for document manipulation
|
||||
14
src/kotlinx/src/test/java/module-info.java
Normal file
14
src/kotlinx/src/test/java/module-info.java
Normal file
@@ -0,0 +1,14 @@
|
||||
module solutions.bitbadger.documents.kotlinx.tests {
|
||||
requires solutions.bitbadger.documents.core;
|
||||
requires solutions.bitbadger.documents.kotlinx;
|
||||
requires java.sql;
|
||||
requires kotlin.stdlib;
|
||||
requires kotlinx.serialization.json;
|
||||
requires kotlin.test.junit5;
|
||||
|
||||
exports solutions.bitbadger.documents.kotlinx.tests;
|
||||
exports solutions.bitbadger.documents.kotlinx.tests.integration;
|
||||
|
||||
opens solutions.bitbadger.documents.kotlinx.tests;
|
||||
opens solutions.bitbadger.documents.kotlinx.tests.integration;
|
||||
}
|
||||
22
src/kotlinx/src/test/kotlin/DocumentConfigTest.kt
Normal file
22
src/kotlinx/src/test/kotlin/DocumentConfigTest.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import solutions.bitbadger.documents.kotlinx.DocumentConfig
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Unit tests for the `Configuration` object
|
||||
*/
|
||||
@DisplayName("KotlinX | DocumentConfig")
|
||||
class DocumentConfigTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Default JSON options are as expected")
|
||||
fun defaultJsonOptions() {
|
||||
assertTrue(DocumentConfig.options.configuration.encodeDefaults, "Encode Defaults should have been set")
|
||||
assertFalse(DocumentConfig.options.configuration.explicitNulls, "Explicit Nulls should not have been set")
|
||||
assertTrue(DocumentConfig.options.configuration.coerceInputValues, "Coerce Input Values should have been set")
|
||||
}
|
||||
}
|
||||
68
src/kotlinx/src/test/kotlin/Types.kt
Normal file
68
src/kotlinx/src/test/kotlin/Types.kt
Normal file
@@ -0,0 +1,68 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.insert
|
||||
import solutions.bitbadger.documents.kotlinx.tests.integration.ThrowawayDatabase
|
||||
|
||||
/** The test table name to use for integration tests */
|
||||
const val TEST_TABLE = "test_table"
|
||||
|
||||
@Serializable
|
||||
data class NumIdDocument(val key: Int, val text: String) {
|
||||
constructor() : this(0, "")
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class SubDocument(val foo: String, val bar: String) {
|
||||
constructor() : this("", "")
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ArrayDocument(val id: String, val values: List<String>) {
|
||||
|
||||
constructor() : this("", listOf())
|
||||
|
||||
companion object {
|
||||
/** A set of documents used for integration tests */
|
||||
val testDocuments = listOf(
|
||||
ArrayDocument("first", listOf("a", "b", "c")),
|
||||
ArrayDocument("second", listOf("c", "d", "e")),
|
||||
ArrayDocument("third", listOf("x", "y", "z"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class JsonDocument(val id: String, val value: String = "", val numValue: Int = 0, val sub: SubDocument? = null) {
|
||||
|
||||
constructor() : this("")
|
||||
|
||||
companion object {
|
||||
/** Documents to use for testing */
|
||||
private val testDocuments = listOf(
|
||||
JsonDocument("one", "FIRST!", 0, null),
|
||||
JsonDocument("two", "another", 10, SubDocument("green", "blue")),
|
||||
JsonDocument("three", "", 4, null),
|
||||
JsonDocument("four", "purple", 17, SubDocument("green", "red")),
|
||||
JsonDocument("five", "purple", 18, null)
|
||||
)
|
||||
|
||||
fun load(db: ThrowawayDatabase, tableName: String = TEST_TABLE) =
|
||||
testDocuments.forEach { db.conn.insert(tableName, it) }
|
||||
|
||||
/** Document ID `one` as a JSON string */
|
||||
val one = """{"id":"one","value":"FIRST!","numValue":0}"""
|
||||
|
||||
/** Document ID `two` as a JSON string */
|
||||
val two = """{"id":"two","value":"another","numValue":10,"sub":{"foo":"green","bar":"blue"}}"""
|
||||
|
||||
/** Document ID `three` as a JSON string */
|
||||
val three = """{"id":"three","value":"","numValue":4}"""
|
||||
|
||||
/** Document ID `four` as a JSON string */
|
||||
val four = """{"id":"four","value":"purple","numValue":17,"sub":{"foo":"green","bar":"red"}}"""
|
||||
|
||||
/** Document ID `five` as a JSON string */
|
||||
val five = """{"id":"five","value":"purple","numValue":18}"""
|
||||
}
|
||||
}
|
||||
72
src/kotlinx/src/test/kotlin/integration/CountFunctions.kt
Normal file
72
src/kotlinx/src/test/kotlin/integration/CountFunctions.kt
Normal file
@@ -0,0 +1,72 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
/**
|
||||
* Integration tests for the `Count` object
|
||||
*/
|
||||
object CountFunctions {
|
||||
|
||||
fun all(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5L, db.conn.countAll(TEST_TABLE), "There should have been 5 documents in the table")
|
||||
}
|
||||
|
||||
fun byFieldsNumeric(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
3L,
|
||||
db.conn.countByFields(TEST_TABLE, listOf(Field.between("numValue", 10, 20))),
|
||||
"There should have been 3 matching documents"
|
||||
)
|
||||
}
|
||||
|
||||
fun byFieldsAlpha(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
1L,
|
||||
db.conn.countByFields(TEST_TABLE, listOf(Field.between("value", "aardvark", "apple"))),
|
||||
"There should have been 1 matching document"
|
||||
)
|
||||
}
|
||||
|
||||
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
2L,
|
||||
db.conn.countByContains(TEST_TABLE, mapOf("value" to "purple")),
|
||||
"There should have been 2 matching documents"
|
||||
)
|
||||
}
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
0L,
|
||||
db.conn.countByContains(TEST_TABLE, mapOf("value" to "magenta")),
|
||||
"There should have been no matching documents"
|
||||
)
|
||||
}
|
||||
|
||||
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
2L,
|
||||
db.conn.countByJsonPath(TEST_TABLE, "$.numValue ? (@ < 5)"),
|
||||
"There should have been 2 matching documents"
|
||||
)
|
||||
}
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
0L,
|
||||
db.conn.countByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)"),
|
||||
"There should have been no matching documents"
|
||||
)
|
||||
}
|
||||
}
|
||||
162
src/kotlinx/src/test/kotlin/integration/CustomFunctions.kt
Normal file
162
src/kotlinx/src/test/kotlin/integration/CustomFunctions.kt
Normal file
@@ -0,0 +1,162 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.Results
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.ArrayDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import solutions.bitbadger.documents.query.*
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
/**
|
||||
* Integration tests for the `Custom` object
|
||||
*/
|
||||
object CustomFunctions {
|
||||
|
||||
fun listEmpty(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.deleteByFields(TEST_TABLE, listOf(Field.exists(Configuration.idField)))
|
||||
val result = db.conn.customList<JsonDocument>(FindQuery.all(TEST_TABLE), mapFunc = Results::fromData)
|
||||
assertEquals(0, result.size, "There should have been no results")
|
||||
}
|
||||
|
||||
fun listAll(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val result = db.conn.customList<JsonDocument>(FindQuery.all(TEST_TABLE), mapFunc = Results::fromData)
|
||||
assertEquals(5, result.size, "There should have been 5 results")
|
||||
}
|
||||
|
||||
fun jsonArrayEmpty(db: ThrowawayDatabase) {
|
||||
assertEquals(0L, db.conn.countAll(TEST_TABLE), "The test table should be empty")
|
||||
assertEquals(
|
||||
"[]",
|
||||
db.conn.customJsonArray(FindQuery.all(TEST_TABLE), listOf(), Results::jsonFromData),
|
||||
"An empty list was not represented correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun jsonArraySingle(db: ThrowawayDatabase) {
|
||||
db.conn.insert(TEST_TABLE, ArrayDocument("one", listOf("2", "3")))
|
||||
assertEquals(
|
||||
JsonFunctions.maybeJsonB("""[{"id":"one","values":["2","3"]}]"""),
|
||||
db.conn.customJsonArray(FindQuery.all(TEST_TABLE), listOf(), Results::jsonFromData),
|
||||
"A single document list was not represented correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun jsonArrayMany(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
assertEquals(
|
||||
JsonFunctions.maybeJsonB("""[{"id":"first","values":["a","b","c"]},"""
|
||||
+ """{"id":"second","values":["c","d","e"]},{"id":"third","values":["x","y","z"]}]"""),
|
||||
db.conn.customJsonArray(FindQuery.all(TEST_TABLE) + orderBy(listOf(Field.named("id"))), listOf(),
|
||||
Results::jsonFromData),
|
||||
"A multiple document list was not represented correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun writeJsonArrayEmpty(db: ThrowawayDatabase) {
|
||||
assertEquals(0L, db.conn.countAll(TEST_TABLE), "The test table should be empty")
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeCustomJsonArray(FindQuery.all(TEST_TABLE), listOf(), writer, Results::jsonFromData)
|
||||
assertEquals("[]", output.toString(), "An empty list was not represented correctly")
|
||||
}
|
||||
|
||||
fun writeJsonArraySingle(db: ThrowawayDatabase) {
|
||||
db.conn.insert(TEST_TABLE, ArrayDocument("one", listOf("2", "3")))
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeCustomJsonArray(FindQuery.all(TEST_TABLE), listOf(), writer, Results::jsonFromData)
|
||||
assertEquals(
|
||||
JsonFunctions.maybeJsonB("""[{"id":"one","values":["2","3"]}]"""),
|
||||
output.toString(),
|
||||
"A single document list was not represented correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun writeJsonArrayMany(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeCustomJsonArray(FindQuery.all(TEST_TABLE) + orderBy(listOf(Field.named("id"))), listOf(), writer,
|
||||
Results::jsonFromData)
|
||||
assertEquals(
|
||||
JsonFunctions.maybeJsonB("""[{"id":"first","values":["a","b","c"]},"""
|
||||
+ """{"id":"second","values":["c","d","e"]},{"id":"third","values":["x","y","z"]}]"""),
|
||||
output.toString(),
|
||||
"A multiple document list was not represented correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun singleNone(db: ThrowawayDatabase) =
|
||||
assertNull(
|
||||
db.conn.customSingle(FindQuery.all(TEST_TABLE), mapFunc = Results::fromData),
|
||||
"There should not have been a document returned"
|
||||
)
|
||||
|
||||
fun singleOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertNotNull(
|
||||
db.conn.customSingle<JsonDocument>(FindQuery.all(TEST_TABLE), mapFunc = Results::fromData),
|
||||
"There should not have been a document returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun jsonSingleNone(db: ThrowawayDatabase) =
|
||||
assertEquals("{}", db.conn.customJsonSingle(FindQuery.all(TEST_TABLE), listOf(), Results::jsonFromData),
|
||||
"An empty document was not represented correctly")
|
||||
|
||||
fun jsonSingleOne(db: ThrowawayDatabase) {
|
||||
db.conn.insert(TEST_TABLE, ArrayDocument("me", listOf("myself", "i")))
|
||||
assertEquals(
|
||||
JsonFunctions.maybeJsonB("{\"id\":\"me\",\"values\":[\"myself\",\"i\"]}"),
|
||||
db.conn.customJsonSingle(FindQuery.all(TEST_TABLE), listOf(), Results::jsonFromData),
|
||||
"A single document was not represented correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun nonQueryChanges(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
5L, db.conn.customScalar(CountQuery.all(TEST_TABLE), mapFunc = Results::toCount),
|
||||
"There should have been 5 documents in the table"
|
||||
)
|
||||
db.conn.customNonQuery("DELETE FROM $TEST_TABLE")
|
||||
assertEquals(
|
||||
0L, db.conn.customScalar(CountQuery.all(TEST_TABLE), mapFunc = Results::toCount),
|
||||
"There should have been no documents in the table"
|
||||
)
|
||||
}
|
||||
|
||||
fun nonQueryNoChanges(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
5L, db.conn.customScalar(CountQuery.all(TEST_TABLE), mapFunc = Results::toCount),
|
||||
"There should have been 5 documents in the table"
|
||||
)
|
||||
db.conn.customNonQuery(
|
||||
DeleteQuery.byId(TEST_TABLE, "eighty-two"),
|
||||
listOf(Parameter(":id", ParameterType.STRING, "eighty-two"))
|
||||
)
|
||||
assertEquals(
|
||||
5L, db.conn.customScalar(CountQuery.all(TEST_TABLE), mapFunc = Results::toCount),
|
||||
"There should still have been 5 documents in the table"
|
||||
)
|
||||
}
|
||||
|
||||
fun scalar(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
3L,
|
||||
db.conn.customScalar("SELECT 3 AS it FROM $TEST_TABLE LIMIT 1", mapFunc = Results::toCount),
|
||||
"The number 3 should have been returned"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Integration tests for the `Definition` object / `ensure*` connection extension functions
|
||||
*/
|
||||
object DefinitionFunctions {
|
||||
|
||||
fun ensureTable(db: ThrowawayDatabase) {
|
||||
assertFalse(db.dbObjectExists("ensured"), "The 'ensured' table should not exist")
|
||||
assertFalse(db.dbObjectExists("idx_ensured_key"), "The PK index for the 'ensured' table should not exist")
|
||||
db.conn.ensureTable("ensured")
|
||||
assertTrue(db.dbObjectExists("ensured"), "The 'ensured' table should exist")
|
||||
assertTrue(db.dbObjectExists("idx_ensured_key"), "The PK index for the 'ensured' table should now exist")
|
||||
}
|
||||
|
||||
fun ensureFieldIndex(db: ThrowawayDatabase) {
|
||||
assertFalse(db.dbObjectExists("idx_${TEST_TABLE}_test"), "The test index should not exist")
|
||||
db.conn.ensureFieldIndex(TEST_TABLE, "test", listOf("id", "category"))
|
||||
assertTrue(db.dbObjectExists("idx_${TEST_TABLE}_test"), "The test index should now exist")
|
||||
}
|
||||
|
||||
fun ensureDocumentIndexFull(db: ThrowawayDatabase) {
|
||||
assertFalse(db.dbObjectExists("doc_table"), "The 'doc_table' table should not exist")
|
||||
db.conn.ensureTable("doc_table")
|
||||
assertTrue(db.dbObjectExists("doc_table"), "The 'doc_table' table should exist")
|
||||
assertFalse(db.dbObjectExists("idx_doc_table_document"), "The document index should not exist")
|
||||
db.conn.ensureDocumentIndex("doc_table", DocumentIndex.FULL)
|
||||
assertTrue(db.dbObjectExists("idx_doc_table_document"), "The document index should exist")
|
||||
}
|
||||
|
||||
fun ensureDocumentIndexOptimized(db: ThrowawayDatabase) {
|
||||
assertFalse(db.dbObjectExists("doc_table"), "The 'doc_table' table should not exist")
|
||||
db.conn.ensureTable("doc_table")
|
||||
assertTrue(db.dbObjectExists("doc_table"), "The 'doc_table' table should exist")
|
||||
assertFalse(db.dbObjectExists("idx_doc_table_document"), "The document index should not exist")
|
||||
db.conn.ensureDocumentIndex("doc_table", DocumentIndex.OPTIMIZED)
|
||||
assertTrue(db.dbObjectExists("idx_doc_table_document"), "The document index should exist")
|
||||
}
|
||||
}
|
||||
69
src/kotlinx/src/test/kotlin/integration/DeleteFunctions.kt
Normal file
69
src/kotlinx/src/test/kotlin/integration/DeleteFunctions.kt
Normal file
@@ -0,0 +1,69 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
/**
|
||||
* Integration tests for the `Delete` object
|
||||
*/
|
||||
object DeleteFunctions {
|
||||
|
||||
fun byIdMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteById(TEST_TABLE, "four")
|
||||
assertEquals(4, db.conn.countAll(TEST_TABLE), "There should now be 4 documents in the table")
|
||||
}
|
||||
|
||||
fun byIdNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteById(TEST_TABLE, "negative four")
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
|
||||
}
|
||||
|
||||
fun byFieldsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteByFields(TEST_TABLE, listOf(Field.notEqual("value", "purple")))
|
||||
assertEquals(2, db.conn.countAll(TEST_TABLE), "There should now be 2 documents in the table")
|
||||
}
|
||||
|
||||
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteByFields(TEST_TABLE, listOf(Field.equal("value", "crimson")))
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
|
||||
}
|
||||
|
||||
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteByContains(TEST_TABLE, mapOf("value" to "purple"))
|
||||
assertEquals(3, db.conn.countAll(TEST_TABLE), "There should now be 3 documents in the table")
|
||||
}
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteByContains(TEST_TABLE, mapOf("target" to "acquired"))
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
|
||||
}
|
||||
|
||||
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteByJsonPath(TEST_TABLE, "$.value ? (@ == \"purple\")")
|
||||
assertEquals(3, db.conn.countAll(TEST_TABLE), "There should now be 3 documents in the table")
|
||||
}
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
|
||||
db.conn.deleteByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)")
|
||||
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
|
||||
}
|
||||
}
|
||||
130
src/kotlinx/src/test/kotlin/integration/DocumentFunctions.kt
Normal file
130
src/kotlinx/src/test/kotlin/integration/DocumentFunctions.kt
Normal file
@@ -0,0 +1,130 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.NumIdDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.SubDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.*
|
||||
|
||||
/**
|
||||
* Integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions
|
||||
*/
|
||||
object DocumentFunctions {
|
||||
|
||||
fun insertDefault(db: ThrowawayDatabase) {
|
||||
assertEquals(0L, db.conn.countAll(TEST_TABLE), "There should be no documents in the table")
|
||||
val doc = JsonDocument("turkey", "", 0, SubDocument("gobble", "gobble"))
|
||||
db.conn.insert(TEST_TABLE, doc)
|
||||
val after = db.conn.findAll<JsonDocument>(TEST_TABLE)
|
||||
assertEquals(1, after.size, "There should be one document in the table")
|
||||
assertEquals(doc, after[0], "The document should be what was inserted")
|
||||
}
|
||||
|
||||
fun insertDupe(db: ThrowawayDatabase) {
|
||||
db.conn.insert(TEST_TABLE, JsonDocument("a", "", 0, null))
|
||||
assertThrows<DocumentException>("Inserting a document with a duplicate key should have thrown an exception") {
|
||||
db.conn.insert(TEST_TABLE, JsonDocument("a", "b", 22, null))
|
||||
}
|
||||
}
|
||||
|
||||
fun insertNumAutoId(db: ThrowawayDatabase) {
|
||||
try {
|
||||
Configuration.autoIdStrategy = AutoId.NUMBER
|
||||
Configuration.idField = "key"
|
||||
assertEquals(0L, db.conn.countAll(TEST_TABLE), "There should be no documents in the table")
|
||||
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(0, "one"))
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(0, "two"))
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(77, "three"))
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(0, "four"))
|
||||
|
||||
val after = db.conn.findAll<NumIdDocument>(TEST_TABLE, listOf(Field.named("key")))
|
||||
assertEquals(4, after.size, "There should have been 4 documents returned")
|
||||
assertEquals(
|
||||
"1|2|77|78", after.joinToString("|") { it.key.toString() },
|
||||
"The IDs were not generated correctly"
|
||||
)
|
||||
} finally {
|
||||
Configuration.autoIdStrategy = AutoId.DISABLED
|
||||
Configuration.idField = "id"
|
||||
}
|
||||
}
|
||||
|
||||
fun insertUUIDAutoId(db: ThrowawayDatabase) {
|
||||
try {
|
||||
Configuration.autoIdStrategy = AutoId.UUID
|
||||
assertEquals(0L, db.conn.countAll(TEST_TABLE), "There should be no documents in the table")
|
||||
|
||||
db.conn.insert(TEST_TABLE, JsonDocument(""))
|
||||
|
||||
val after = db.conn.findAll<JsonDocument>(TEST_TABLE)
|
||||
assertEquals(1, after.size, "There should have been 1 document returned")
|
||||
assertEquals(32, after[0].id.length, "The ID was not generated correctly")
|
||||
} finally {
|
||||
Configuration.autoIdStrategy = AutoId.DISABLED
|
||||
}
|
||||
}
|
||||
|
||||
fun insertStringAutoId(db: ThrowawayDatabase) {
|
||||
try {
|
||||
Configuration.autoIdStrategy = AutoId.RANDOM_STRING
|
||||
assertEquals(0L, db.conn.countAll(TEST_TABLE), "There should be no documents in the table")
|
||||
|
||||
db.conn.insert(TEST_TABLE, JsonDocument(""))
|
||||
|
||||
Configuration.idStringLength = 21
|
||||
db.conn.insert(TEST_TABLE, JsonDocument(""))
|
||||
|
||||
val after = db.conn.findAll<JsonDocument>(TEST_TABLE)
|
||||
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(21, after[1].id.length, "The second document's ID was not generated correctly")
|
||||
} finally {
|
||||
Configuration.autoIdStrategy = AutoId.DISABLED
|
||||
Configuration.idStringLength = 16
|
||||
}
|
||||
}
|
||||
|
||||
fun saveMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.save(TEST_TABLE, JsonDocument("two", numValue = 44))
|
||||
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "two")
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("two", doc.id, "An incorrect document was returned")
|
||||
assertEquals("", doc.value, "The \"value\" field was not updated")
|
||||
assertEquals(44, doc.numValue, "The \"numValue\" field was not updated")
|
||||
assertNull(doc.sub, "The \"sub\" field was not updated")
|
||||
}
|
||||
|
||||
fun saveNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.save(TEST_TABLE, JsonDocument("test", sub = SubDocument("a", "b")))
|
||||
assertNotNull(
|
||||
db.conn.findById<String, JsonDocument>(TEST_TABLE, "test"),
|
||||
"The test document should have been saved"
|
||||
)
|
||||
}
|
||||
|
||||
fun updateMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.update(TEST_TABLE, "one", JsonDocument("one", "howdy", 8, SubDocument("y", "z")))
|
||||
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "one")
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("one", doc.id, "An incorrect document was returned")
|
||||
assertEquals("howdy", doc.value, "The \"value\" field was not updated")
|
||||
assertEquals(8, doc.numValue, "The \"numValue\" field was not updated")
|
||||
assertNotNull(doc.sub, "The sub-document should not be null")
|
||||
assertEquals("y", doc.sub.foo, "The sub-document \"foo\" field was not updated")
|
||||
assertEquals("z", doc.sub.bar, "The sub-document \"bar\" field was not updated")
|
||||
}
|
||||
|
||||
fun updateNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse { db.conn.existsById(TEST_TABLE, "two-hundred") }
|
||||
db.conn.update(TEST_TABLE, "two-hundred", JsonDocument("two-hundred", numValue = 200))
|
||||
assertFalse { db.conn.existsById(TEST_TABLE, "two-hundred") }
|
||||
}
|
||||
}
|
||||
66
src/kotlinx/src/test/kotlin/integration/ExistsFunctions.kt
Normal file
66
src/kotlinx/src/test/kotlin/integration/ExistsFunctions.kt
Normal file
@@ -0,0 +1,66 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Integration tests for the `Exists` object
|
||||
*/
|
||||
object ExistsFunctions {
|
||||
|
||||
fun byIdMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertTrue("The document with ID \"three\" should exist") { db.conn.existsById(TEST_TABLE, "three") }
|
||||
}
|
||||
|
||||
fun byIdNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse("The document with ID \"seven\" should not exist") { db.conn.existsById(TEST_TABLE, "seven") }
|
||||
}
|
||||
|
||||
fun byFieldsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertTrue("Matching documents should have been found") {
|
||||
db.conn.existsByFields(TEST_TABLE, listOf(Field.equal("numValue", 10)))
|
||||
}
|
||||
}
|
||||
|
||||
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse("No matching documents should have been found") {
|
||||
db.conn.existsByFields(TEST_TABLE, listOf(Field.equal("nothing", "none")))
|
||||
}
|
||||
}
|
||||
|
||||
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertTrue("Matching documents should have been found") {
|
||||
db.conn.existsByContains(TEST_TABLE, mapOf("value" to "purple"))
|
||||
}
|
||||
}
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse("Matching documents should not have been found") {
|
||||
db.conn.existsByContains(TEST_TABLE, mapOf("value" to "violet"))
|
||||
}
|
||||
}
|
||||
|
||||
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertTrue("Matching documents should have been found") {
|
||||
db.conn.existsByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10)")
|
||||
}
|
||||
}
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse("Matching documents should not have been found") {
|
||||
db.conn.existsByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10.1)")
|
||||
}
|
||||
}
|
||||
}
|
||||
300
src/kotlinx/src/test/kotlin/integration/FindFunctions.kt
Normal file
300
src/kotlinx/src/test/kotlin/integration/FindFunctions.kt
Normal file
@@ -0,0 +1,300 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.ArrayDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.NumIdDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Integration tests for the `Find` object
|
||||
*/
|
||||
object FindFunctions {
|
||||
|
||||
fun allDefault(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(5, db.conn.findAll<JsonDocument>(TEST_TABLE).size, "There should have been 5 documents returned")
|
||||
}
|
||||
|
||||
fun allAscending(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findAll<JsonDocument>(TEST_TABLE, listOf(Field.named("id")))
|
||||
assertEquals(5, docs.size, "There should have been 5 documents returned")
|
||||
assertEquals(
|
||||
"five|four|one|three|two",
|
||||
docs.joinToString("|") { it.id },
|
||||
"The documents were not ordered correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun allDescending(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findAll<JsonDocument>(TEST_TABLE, listOf(Field.named("id DESC")))
|
||||
assertEquals(5, docs.size, "There should have been 5 documents returned")
|
||||
assertEquals(
|
||||
"two|three|one|four|five",
|
||||
docs.joinToString("|") { it.id },
|
||||
"The documents were not ordered correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun allNumOrder(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findAll<JsonDocument>(
|
||||
TEST_TABLE,
|
||||
listOf(Field.named("sub.foo NULLS LAST"), Field.named("n:numValue"))
|
||||
)
|
||||
assertEquals(5, docs.size, "There should have been 5 documents returned")
|
||||
assertEquals(
|
||||
"two|four|one|three|five",
|
||||
docs.joinToString("|") { it.id },
|
||||
"The documents were not ordered correctly"
|
||||
)
|
||||
}
|
||||
|
||||
fun allEmpty(db: ThrowawayDatabase) =
|
||||
assertEquals(0, db.conn.findAll<JsonDocument>(TEST_TABLE).size, "There should have been no documents returned")
|
||||
|
||||
fun byIdString(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "two")
|
||||
assertNotNull(doc, "The document should have been returned")
|
||||
assertEquals("two", doc.id, "An incorrect document was returned")
|
||||
}
|
||||
|
||||
fun byIdNumber(db: ThrowawayDatabase) {
|
||||
Configuration.idField = "key"
|
||||
try {
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(18, "howdy"))
|
||||
val doc = db.conn.findById<Int, NumIdDocument>(TEST_TABLE, 18)
|
||||
assertNotNull(doc, "The document should have been returned")
|
||||
} finally {
|
||||
Configuration.idField = "id"
|
||||
}
|
||||
}
|
||||
|
||||
fun byIdNotFound(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertNull(
|
||||
db.conn.findById<String, JsonDocument>(TEST_TABLE, "x"),
|
||||
"There should have been no document returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun byFieldsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByFields<JsonDocument>(
|
||||
TEST_TABLE,
|
||||
listOf(Field.any("value", listOf("blue", "purple")), Field.exists("sub")),
|
||||
FieldMatch.ALL
|
||||
)
|
||||
assertEquals(1, docs.size, "There should have been a document returned")
|
||||
assertEquals("four", docs[0].id, "The incorrect document was returned")
|
||||
}
|
||||
|
||||
fun byFieldsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByFields<JsonDocument>(
|
||||
TEST_TABLE,
|
||||
listOf(Field.equal("value", "purple")),
|
||||
orderBy = listOf(Field.named("id"))
|
||||
)
|
||||
assertEquals(2, docs.size, "There should have been 2 documents returned")
|
||||
assertEquals("five|four", docs.joinToString("|") { it.id }, "The documents were not ordered correctly")
|
||||
}
|
||||
|
||||
fun byFieldsMatchNumIn(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByFields<JsonDocument>(TEST_TABLE, listOf(Field.any("numValue", listOf(2, 4, 6, 8))))
|
||||
assertEquals(1, docs.size, "There should have been a document returned")
|
||||
assertEquals("three", docs[0].id, "The incorrect document was returned")
|
||||
}
|
||||
|
||||
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
0,
|
||||
db.conn.findByFields<JsonDocument>(TEST_TABLE, listOf(Field.greater("numValue", 100))).size,
|
||||
"There should have been no documents returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun byFieldsMatchInArray(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
val docs =
|
||||
db.conn.findByFields<ArrayDocument>(TEST_TABLE, listOf(Field.inArray("values", TEST_TABLE, listOf("c"))))
|
||||
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[1].id), "An incorrect document was returned (${docs[1].id})")
|
||||
}
|
||||
|
||||
fun byFieldsNoMatchInArray(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
assertEquals(
|
||||
0,
|
||||
db.conn.findByFields<ArrayDocument>(
|
||||
TEST_TABLE,
|
||||
listOf(Field.inArray("values", TEST_TABLE, listOf("j")))
|
||||
).size,
|
||||
"There should have been no documents returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "purple"))
|
||||
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[1].id), "An incorrect document was returned (${docs[1].id})")
|
||||
}
|
||||
|
||||
fun byContainsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByContains<JsonDocument, Map<String, Map<String, String>>>(
|
||||
TEST_TABLE,
|
||||
mapOf("sub" to mapOf("foo" to "green")),
|
||||
listOf(Field.named("value"))
|
||||
)
|
||||
assertEquals(2, docs.size, "There should have been 2 documents returned")
|
||||
assertEquals("two|four", docs.joinToString("|") { it.id }, "The documents were not ordered correctly")
|
||||
}
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
0,
|
||||
db.conn.findByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "indigo")).size,
|
||||
"There should have been no documents returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 10)")
|
||||
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[1].id), "An incorrect document was returned (${docs[1].id})")
|
||||
}
|
||||
|
||||
fun byJsonPathMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 10)", listOf(Field.named("id")))
|
||||
assertEquals(2, docs.size, "There should have been 2 documents returned")
|
||||
assertEquals("five|four", docs.joinToString("|") { it.id }, "The documents were not ordered correctly")
|
||||
}
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertEquals(
|
||||
0,
|
||||
db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 100)").size,
|
||||
"There should have been no documents returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun firstByFieldsMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByFields<JsonDocument>(TEST_TABLE, listOf(Field.equal("value", "another")))
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("two", doc.id, "The incorrect document was returned")
|
||||
}
|
||||
|
||||
fun firstByFieldsMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByFields<JsonDocument>(TEST_TABLE, listOf(Field.equal("sub.foo", "green")))
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertTrue(listOf("two", "four").contains(doc.id), "An incorrect document was returned (${doc.id})")
|
||||
}
|
||||
|
||||
fun firstByFieldsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByFields<JsonDocument>(
|
||||
TEST_TABLE,
|
||||
listOf(Field.equal("sub.foo", "green")),
|
||||
orderBy = listOf(Field.named("n:numValue DESC"))
|
||||
)
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("four", doc.id, "An incorrect document was returned")
|
||||
}
|
||||
|
||||
fun firstByFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertNull(
|
||||
db.conn.findFirstByFields(TEST_TABLE, listOf(Field.equal("value", "absent"))),
|
||||
"There should have been no document returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun firstByContainsMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "FIRST!"))
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("one", doc.id, "An incorrect document was returned")
|
||||
}
|
||||
|
||||
fun firstByContainsMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(TEST_TABLE, mapOf("value" to "purple"))
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertTrue(listOf("four", "five").contains(doc.id), "An incorrect document was returned (${doc.id})")
|
||||
}
|
||||
|
||||
fun firstByContainsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(
|
||||
TEST_TABLE,
|
||||
mapOf("value" to "purple"),
|
||||
listOf(Field.named("sub.bar NULLS FIRST"))
|
||||
)
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("five", doc.id, "An incorrect document was returned")
|
||||
}
|
||||
|
||||
fun firstByContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertNull(
|
||||
db.conn.findFirstByContains<JsonDocument, Map<String, String>>(
|
||||
TEST_TABLE,
|
||||
mapOf("value" to "indigo")
|
||||
), "There should have been no document returned"
|
||||
)
|
||||
}
|
||||
|
||||
fun firstByJsonPathMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ == 10)")
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("two", doc.id, "An incorrect document was returned")
|
||||
}
|
||||
|
||||
fun firstByJsonPathMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 10)")
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertTrue(listOf("four", "five").contains(doc.id), "An incorrect document was returned (${doc.id})")
|
||||
}
|
||||
|
||||
fun firstByJsonPathMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val doc = db.conn.findFirstByJsonPath<JsonDocument>(
|
||||
TEST_TABLE,
|
||||
"$.numValue ? (@ > 10)",
|
||||
listOf(Field.named("id DESC"))
|
||||
)
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("four", doc.id, "An incorrect document was returned")
|
||||
}
|
||||
|
||||
fun firstByJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertNull(
|
||||
db.conn.findFirstByJsonPath<JsonDocument>(TEST_TABLE, "$.numValue ? (@ > 100)"),
|
||||
"There should have been no document returned"
|
||||
)
|
||||
}
|
||||
}
|
||||
719
src/kotlinx/src/test/kotlin/integration/JsonFunctions.kt
Normal file
719
src/kotlinx/src/test/kotlin/integration/JsonFunctions.kt
Normal file
@@ -0,0 +1,719 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import solutions.bitbadger.documents.Dialect
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.*
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Tests for the JSON-returning functions
|
||||
*
|
||||
* NOTE: PostgreSQL JSONB columns do not preserve the original JSON with which a document was stored. These tests are
|
||||
* the most complex within the library, as they have split testing based on the backing data store. The PostgreSQL tests
|
||||
* check IDs (and, in the case of ordered queries, which ones occur before which others) vs. the entire JSON string.
|
||||
* Meanwhile, SQLite stores JSON as text, and will return exactly the JSON it was given when it was originally written.
|
||||
* These tests can ensure the expected round-trip of the entire JSON string.
|
||||
*/
|
||||
object JsonFunctions {
|
||||
|
||||
/**
|
||||
* PostgreSQL, when returning JSONB as a string, has spaces after commas and colons delineating fields and values.
|
||||
* This function will do a crude string replacement to match the target string based on the dialect being tested.
|
||||
*
|
||||
* @param json The JSON which should be returned
|
||||
* @return The actual expected JSON based on the database being tested
|
||||
*/
|
||||
fun maybeJsonB(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> json
|
||||
Dialect.POSTGRESQL -> json.replace("\":", "\": ").replace(",\"", ", \"")
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a snippet of JSON to find a document ID
|
||||
*
|
||||
* @param id The ID of the document
|
||||
* @return A connection-aware ID to check for presence and positioning
|
||||
*/
|
||||
private fun docId(id: String) =
|
||||
maybeJsonB("{\"id\":\"$id\"")
|
||||
|
||||
private fun checkAllDefault(json: String) {
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> {
|
||||
assertTrue(json.contains(JsonDocument.one), "Document 'one' not found in JSON ($json)")
|
||||
assertTrue(json.contains(JsonDocument.two), "Document 'two' not found in JSON ($json)")
|
||||
assertTrue(json.contains(JsonDocument.three), "Document 'three' not found in JSON ($json)")
|
||||
assertTrue(json.contains(JsonDocument.four), "Document 'four' not found in JSON ($json)")
|
||||
assertTrue(json.contains(JsonDocument.five), "Document 'five' not found in JSON ($json)")
|
||||
}
|
||||
Dialect.POSTGRESQL -> {
|
||||
assertTrue(json.contains(docId("one")), "Document 'one' not found in JSON ($json)")
|
||||
assertTrue(json.contains(docId("two")), "Document 'two' not found in JSON ($json)")
|
||||
assertTrue(json.contains(docId("three")), "Document 'three' not found in JSON ($json)")
|
||||
assertTrue(json.contains(docId("four")), "Document 'four' not found in JSON ($json)")
|
||||
assertTrue(json.contains(docId("five")), "Document 'five' not found in JSON ($json)")
|
||||
}
|
||||
}
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
|
||||
fun allDefault(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkAllDefault(db.conn.jsonAll(TEST_TABLE))
|
||||
}
|
||||
|
||||
fun writeAllDefault(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonAll(TEST_TABLE, writer)
|
||||
checkAllDefault(output.toString())
|
||||
}
|
||||
|
||||
private fun checkAllEmpty(json: String) =
|
||||
assertEquals("[]", json, "There should have been no documents returned")
|
||||
|
||||
fun allEmpty(db: ThrowawayDatabase) =
|
||||
checkAllEmpty(db.conn.jsonAll(TEST_TABLE))
|
||||
|
||||
fun writeAllEmpty(db: ThrowawayDatabase) {
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonAll(TEST_TABLE, writer)
|
||||
checkAllEmpty(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByIdString(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.two, json, "An incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("two")), "An incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun byIdString(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByIdString(db.conn.jsonById(TEST_TABLE, "two"))
|
||||
}
|
||||
|
||||
fun writeByIdString(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonById(TEST_TABLE, writer, "two")
|
||||
checkByIdString(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByIdNumber(json: String) =
|
||||
assertEquals(
|
||||
maybeJsonB("""{"key":18,"text":"howdy"}"""),
|
||||
json,
|
||||
"The document should have been found by numeric ID"
|
||||
)
|
||||
|
||||
fun byIdNumber(db: ThrowawayDatabase) {
|
||||
Configuration.idField = "key"
|
||||
try {
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(18, "howdy"))
|
||||
checkByIdNumber(db.conn.jsonById(TEST_TABLE, 18))
|
||||
} finally {
|
||||
Configuration.idField = "id"
|
||||
}
|
||||
}
|
||||
|
||||
fun writeByIdNumber(db: ThrowawayDatabase) {
|
||||
Configuration.idField = "key"
|
||||
try {
|
||||
db.conn.insert(TEST_TABLE, NumIdDocument(18, "howdy"))
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonById(TEST_TABLE, writer, 18)
|
||||
checkByIdNumber(output.toString())
|
||||
} finally {
|
||||
Configuration.idField = "id"
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkByIdNotFound(json: String) =
|
||||
assertEquals("{}", json, "There should have been no document returned")
|
||||
|
||||
fun byIdNotFound(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByIdNotFound(db.conn.jsonById(TEST_TABLE, "x"))
|
||||
}
|
||||
|
||||
fun writeByIdNotFound(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonById(TEST_TABLE, writer, "x")
|
||||
checkByIdNotFound(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByFieldsMatch(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals("[${JsonDocument.four}]", json, "The incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> {
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
assertTrue(json.contains(docId("four")),"The incorrect document was returned ($json)")
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
}
|
||||
|
||||
fun byFieldsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByFieldsMatch(
|
||||
db.conn.jsonByFields(
|
||||
TEST_TABLE, listOf(Field.any("value", listOf("blue", "purple")), Field.exists("sub")), FieldMatch.ALL
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun writeByFieldsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByFields(
|
||||
TEST_TABLE,
|
||||
writer,
|
||||
listOf(Field.any("value", listOf("blue", "purple")), Field.exists("sub")),
|
||||
FieldMatch.ALL
|
||||
)
|
||||
checkByFieldsMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByFieldsMatchOrdered(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(
|
||||
"[${JsonDocument.five},${JsonDocument.four}]", json, "The documents were not ordered correctly"
|
||||
)
|
||||
|
||||
Dialect.POSTGRESQL -> {
|
||||
val fiveIdx = json.indexOf(docId("five"))
|
||||
val fourIdx = json.indexOf(docId("four"))
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
assertTrue(fiveIdx >= 0, "Document 'five' not found ($json)")
|
||||
assertTrue(fourIdx >= 0, "Document 'four' not found ($json)")
|
||||
assertTrue(fiveIdx < fourIdx, "Document 'five' should have been before 'four' ($json)")
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
}
|
||||
|
||||
fun byFieldsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByFieldsMatchOrdered(
|
||||
db.conn.jsonByFields(
|
||||
TEST_TABLE, listOf(Field.equal("value", "purple")), orderBy = listOf(Field.named("id"))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun writeByFieldsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByFields(
|
||||
TEST_TABLE, writer, listOf(Field.equal("value", "purple")), orderBy = listOf(Field.named("id"))
|
||||
)
|
||||
checkByFieldsMatchOrdered(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByFieldsMatchNumIn(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals("[${JsonDocument.three}]", json, "The incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> {
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
assertTrue(json.contains(docId("three")), "The incorrect document was returned ($json)")
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
}
|
||||
|
||||
fun byFieldsMatchNumIn(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByFieldsMatchNumIn(db.conn.jsonByFields(TEST_TABLE, listOf(Field.any("numValue", listOf(2, 4, 6, 8)))))
|
||||
}
|
||||
|
||||
fun writeByFieldsMatchNumIn(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByFields(TEST_TABLE, writer, listOf(Field.any("numValue", listOf(2, 4, 6, 8))))
|
||||
checkByFieldsMatchNumIn(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByFieldsNoMatch(json: String) =
|
||||
assertEquals("[]", json, "There should have been no documents returned")
|
||||
|
||||
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByFieldsNoMatch(db.conn.jsonByFields(TEST_TABLE, listOf(Field.greater("numValue", 100))))
|
||||
}
|
||||
|
||||
fun writeByFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByFields(TEST_TABLE, writer, listOf(Field.greater("numValue", 100)))
|
||||
checkByFieldsNoMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByFieldsMatchInArray(json: String) {
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
assertTrue(json.contains(docId("first")), "The 'first' document was not found ($json)")
|
||||
assertTrue(json.contains(docId("second")), "The 'second' document was not found ($json)")
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
|
||||
fun byFieldsMatchInArray(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
checkByFieldsMatchInArray(
|
||||
db.conn.jsonByFields(TEST_TABLE, listOf(Field.inArray("values", TEST_TABLE, listOf("c"))))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeByFieldsMatchInArray(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByFields(TEST_TABLE, writer, listOf(Field.inArray("values", TEST_TABLE, listOf("c"))))
|
||||
checkByFieldsMatchInArray(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByFieldsNoMatchInArray(json: String) =
|
||||
assertEquals("[]", json, "There should have been no documents returned")
|
||||
|
||||
fun byFieldsNoMatchInArray(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
checkByFieldsNoMatchInArray(
|
||||
db.conn.jsonByFields(TEST_TABLE, listOf(Field.inArray("values", TEST_TABLE, listOf("j"))))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeByFieldsNoMatchInArray(db: ThrowawayDatabase) {
|
||||
ArrayDocument.testDocuments.forEach { db.conn.insert(TEST_TABLE, it) }
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByFields(TEST_TABLE, writer, listOf(Field.inArray("values", TEST_TABLE, listOf("j"))))
|
||||
checkByFieldsNoMatchInArray(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByContainsMatch(json: String) {
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> {
|
||||
assertTrue(json.contains(JsonDocument.four), "Document 'four' not found ($json)")
|
||||
assertTrue(json.contains(JsonDocument.five), "Document 'five' not found ($json)")
|
||||
}
|
||||
Dialect.POSTGRESQL -> {
|
||||
assertTrue(json.contains(docId("four")), "Document 'four' not found ($json)")
|
||||
assertTrue(json.contains(docId("five")), "Document 'five' not found ($json)")
|
||||
}
|
||||
}
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
|
||||
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByContainsMatch(db.conn.jsonByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "purple")))
|
||||
}
|
||||
|
||||
fun writeByContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByContains<Map<String, String>>(TEST_TABLE, writer, mapOf("value" to "purple"))
|
||||
checkByContainsMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByContainsMatchOrdered(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(
|
||||
"[${JsonDocument.two},${JsonDocument.four}]", json, "The documents were not ordered correctly"
|
||||
)
|
||||
Dialect.POSTGRESQL -> {
|
||||
val twoIdx = json.indexOf(docId("two"))
|
||||
val fourIdx = json.indexOf(docId("four"))
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
assertTrue(twoIdx >= 0, "Document 'two' not found ($json)")
|
||||
assertTrue(fourIdx >= 0, "Document 'four' not found ($json)")
|
||||
assertTrue(twoIdx < fourIdx, "Document 'two' should have been before 'four' ($json)")
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
}
|
||||
|
||||
fun byContainsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByContainsMatchOrdered(
|
||||
db.conn.jsonByContains<Map<String, Map<String, String>>>(
|
||||
TEST_TABLE, mapOf("sub" to mapOf("foo" to "green")), listOf(Field.named("value"))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun writeByContainsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByContains<Map<String, Map<String, String>>>(
|
||||
TEST_TABLE, writer, mapOf("sub" to mapOf("foo" to "green")), listOf(Field.named("value"))
|
||||
)
|
||||
checkByContainsMatchOrdered(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByContainsNoMatch(json: String) =
|
||||
assertEquals("[]", json, "There should have been no documents returned")
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByContainsNoMatch(db.conn.jsonByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "indigo")))
|
||||
}
|
||||
|
||||
fun writeByContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByContains<Map<String, String>>(TEST_TABLE, writer, mapOf("value" to "indigo"))
|
||||
checkByContainsNoMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByJsonPathMatch(json: String) {
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> {
|
||||
assertTrue(json.contains(JsonDocument.four), "Document 'four' not found ($json)")
|
||||
assertTrue(json.contains(JsonDocument.five), "Document 'five' not found ($json)")
|
||||
}
|
||||
Dialect.POSTGRESQL -> {
|
||||
assertTrue(json.contains(docId("four")), "Document 'four' not found ($json)")
|
||||
assertTrue(json.contains(docId("five")), "Document 'five' not found ($json)")
|
||||
}
|
||||
}
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
|
||||
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByJsonPathMatch(db.conn.jsonByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)"))
|
||||
}
|
||||
|
||||
fun writeByJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ > 10)")
|
||||
checkByJsonPathMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByJsonPathMatchOrdered(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(
|
||||
"[${JsonDocument.five},${JsonDocument.four}]", json, "The documents were not ordered correctly"
|
||||
)
|
||||
|
||||
Dialect.POSTGRESQL -> {
|
||||
val fiveIdx = json.indexOf(docId("five"))
|
||||
val fourIdx = json.indexOf(docId("four"))
|
||||
assertTrue(json.startsWith("["), "JSON should start with '[' ($json)")
|
||||
assertTrue(fiveIdx >= 0, "Document 'five' not found ($json)")
|
||||
assertTrue(fourIdx >= 0, "Document 'four' not found ($json)")
|
||||
assertTrue(fiveIdx < fourIdx, "Document 'five' should have been before 'four' ($json)")
|
||||
assertTrue(json.endsWith("]"), "JSON should end with ']' ($json)")
|
||||
}
|
||||
}
|
||||
|
||||
fun byJsonPathMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByJsonPathMatchOrdered(
|
||||
db.conn.jsonByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)", listOf(Field.named("id")))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeByJsonPathMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ > 10)", listOf(Field.named("id")))
|
||||
checkByJsonPathMatchOrdered(output.toString())
|
||||
}
|
||||
|
||||
private fun checkByJsonPathNoMatch(json: String) =
|
||||
assertEquals("[]", json, "There should have been no documents returned")
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkByJsonPathNoMatch(db.conn.jsonByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)"))
|
||||
}
|
||||
|
||||
fun writeByJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ > 100)")
|
||||
checkByJsonPathNoMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByFieldsMatchOne(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.two, json, "The incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("two")), "The incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun firstByFieldsMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByFieldsMatchOne(db.conn.jsonFirstByFields(TEST_TABLE, listOf(Field.equal("value", "another"))))
|
||||
}
|
||||
|
||||
fun writeFirstByFieldsMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByFields(TEST_TABLE, writer, listOf(Field.equal("value", "another")))
|
||||
checkFirstByFieldsMatchOne(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByFieldsMatchMany(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertTrue(
|
||||
json.contains(JsonDocument.two) || json.contains(JsonDocument.four),
|
||||
"Expected document 'two' or 'four' ($json)"
|
||||
)
|
||||
Dialect.POSTGRESQL -> assertTrue(
|
||||
json.contains(docId("two")) || json.contains(docId("four")),
|
||||
"Expected document 'two' or 'four' ($json)"
|
||||
)
|
||||
}
|
||||
|
||||
fun firstByFieldsMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByFieldsMatchMany(db.conn.jsonFirstByFields(TEST_TABLE, listOf(Field.equal("sub.foo", "green"))))
|
||||
}
|
||||
|
||||
fun writeFirstByFieldsMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByFields(TEST_TABLE, writer, listOf(Field.equal("sub.foo", "green")))
|
||||
checkFirstByFieldsMatchMany(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByFieldsMatchOrdered(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.four, json, "An incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("four")), "An incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun firstByFieldsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByFieldsMatchOrdered(
|
||||
db.conn.jsonFirstByFields(
|
||||
TEST_TABLE, listOf(Field.equal("sub.foo", "green")), orderBy = listOf(Field.named("n:numValue DESC"))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun writeFirstByFieldsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByFields(
|
||||
TEST_TABLE,
|
||||
writer,
|
||||
listOf(Field.equal("sub.foo", "green")),
|
||||
orderBy = listOf(Field.named("n:numValue DESC"))
|
||||
)
|
||||
checkFirstByFieldsMatchOrdered(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByFieldsNoMatch(json: String) =
|
||||
assertEquals("{}", json, "There should have been no document returned")
|
||||
|
||||
fun firstByFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByFieldsNoMatch(db.conn.jsonFirstByFields(TEST_TABLE, listOf(Field.equal("value", "absent"))))
|
||||
}
|
||||
|
||||
fun writeFirstByFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByFields(TEST_TABLE, writer, listOf(Field.equal("value", "absent")))
|
||||
checkFirstByFieldsNoMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByContainsMatchOne(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.one, json, "An incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("one")), "An incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun firstByContainsMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByContainsMatchOne(
|
||||
db.conn.jsonFirstByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "FIRST!"))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeFirstByContainsMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByContains<Map<String, String>>(TEST_TABLE, writer, mapOf("value" to "FIRST!"))
|
||||
}
|
||||
|
||||
private fun checkFirstByContainsMatchMany(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertTrue(
|
||||
json.contains(JsonDocument.four) || json.contains(JsonDocument.five),
|
||||
"Expected document 'four' or 'five' ($json)"
|
||||
)
|
||||
Dialect.POSTGRESQL -> assertTrue(
|
||||
json.contains(docId("four")) || json.contains(docId("five")),
|
||||
"Expected document 'four' or 'five' ($json)"
|
||||
)
|
||||
}
|
||||
|
||||
fun firstByContainsMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByContainsMatchMany(
|
||||
db.conn.jsonFirstByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "purple"))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeFirstByContainsMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByContains<Map<String, String>>(TEST_TABLE, writer, mapOf("value" to "purple"))
|
||||
checkFirstByContainsMatchMany(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByContainsMatchOrdered(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.five, json, "An incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("five")), "An incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun firstByContainsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByContainsMatchOrdered(
|
||||
db.conn.jsonFirstByContains<Map<String, String>>(
|
||||
TEST_TABLE, mapOf("value" to "purple"), listOf(Field.named("sub.bar NULLS FIRST"))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun writeFirstByContainsMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByContains<Map<String, String>>(
|
||||
TEST_TABLE, writer, mapOf("value" to "purple"), listOf(Field.named("sub.bar NULLS FIRST"))
|
||||
)
|
||||
checkFirstByContainsMatchOrdered(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByContainsNoMatch(json: String) =
|
||||
assertEquals("{}", json, "There should have been no document returned")
|
||||
|
||||
fun firstByContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByContainsNoMatch(
|
||||
db.conn.jsonFirstByContains<Map<String, String>>(TEST_TABLE, mapOf("value" to "indigo"))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeFirstByContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByContains<Map<String, String>>(TEST_TABLE, writer, mapOf("value" to "indigo"))
|
||||
checkFirstByContainsNoMatch(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByJsonPathMatchOne(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.two, json, "An incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("two")), "An incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun firstByJsonPathMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByJsonPathMatchOne(db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10)"))
|
||||
}
|
||||
|
||||
fun writeFirstByJsonPathMatchOne(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ == 10)")
|
||||
checkFirstByJsonPathMatchOne(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByJsonPathMatchMany(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertTrue(
|
||||
json.contains(JsonDocument.four) || json.contains(JsonDocument.five),
|
||||
"Expected document 'four' or 'five' ($json)"
|
||||
)
|
||||
Dialect.POSTGRESQL -> assertTrue(
|
||||
json.contains(docId("four")) || json.contains(docId("five")),
|
||||
"Expected document 'four' or 'five' ($json)"
|
||||
)
|
||||
}
|
||||
|
||||
fun firstByJsonPathMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByJsonPathMatchMany(db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)"))
|
||||
}
|
||||
|
||||
fun writeFirstByJsonPathMatchMany(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ > 10)")
|
||||
checkFirstByJsonPathMatchMany(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByJsonPathMatchOrdered(json: String) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.SQLITE -> assertEquals(JsonDocument.four, json, "An incorrect document was returned")
|
||||
Dialect.POSTGRESQL -> assertTrue(json.contains(docId("four")), "An incorrect document was returned ($json)")
|
||||
}
|
||||
|
||||
fun firstByJsonPathMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByJsonPathMatchOrdered(
|
||||
db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 10)", listOf(Field.named("id DESC")))
|
||||
)
|
||||
}
|
||||
|
||||
fun writeFirstByJsonPathMatchOrdered(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ > 10)", listOf(Field.named("id DESC")))
|
||||
checkFirstByJsonPathMatchOrdered(output.toString())
|
||||
}
|
||||
|
||||
private fun checkFirstByJsonPathNoMatch(json: String) =
|
||||
assertEquals("{}", json, "There should have been no document returned")
|
||||
|
||||
fun firstByJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
checkFirstByJsonPathNoMatch(db.conn.jsonFirstByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)"))
|
||||
}
|
||||
|
||||
fun writeFirstByJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val output = StringWriter()
|
||||
val writer = PrintWriter(output)
|
||||
db.conn.writeJsonFirstByJsonPath(TEST_TABLE, writer, "$.numValue ? (@ > 100)")
|
||||
checkFirstByJsonPathNoMatch(output.toString())
|
||||
}
|
||||
}
|
||||
90
src/kotlinx/src/test/kotlin/integration/PatchFunctions.kt
Normal file
90
src/kotlinx/src/test/kotlin/integration/PatchFunctions.kt
Normal file
@@ -0,0 +1,90 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Integration tests for the `Patch` object
|
||||
*/
|
||||
object PatchFunctions {
|
||||
|
||||
fun byIdMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.patchById(TEST_TABLE, "one", mapOf("numValue" to 44))
|
||||
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "one")
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("one", doc.id, "An incorrect document was returned")
|
||||
assertEquals(44, doc.numValue, "The document was not patched")
|
||||
}
|
||||
|
||||
fun byIdNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse("Document with ID \"forty-seven\" should not exist") {
|
||||
db.conn.existsById(TEST_TABLE, "forty-seven")
|
||||
}
|
||||
db.conn.patchById(TEST_TABLE, "forty-seven", mapOf("foo" to "green")) // no exception = pass
|
||||
}
|
||||
|
||||
fun byFieldsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.patchByFields(TEST_TABLE, listOf(Field.equal("value", "purple")), mapOf("numValue" to 77))
|
||||
assertEquals(
|
||||
2,
|
||||
db.conn.countByFields(TEST_TABLE, listOf(Field.equal("numValue", 77))),
|
||||
"There should have been 2 documents with numeric value 77"
|
||||
)
|
||||
}
|
||||
|
||||
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val fields = listOf(Field.equal("value", "burgundy"))
|
||||
assertFalse("There should be no documents with value of \"burgundy\"") {
|
||||
db.conn.existsByFields(TEST_TABLE, fields)
|
||||
}
|
||||
db.conn.patchByFields(TEST_TABLE, fields, mapOf("foo" to "green")) // no exception = pass
|
||||
}
|
||||
|
||||
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val contains = mapOf("value" to "another")
|
||||
db.conn.patchByContains(TEST_TABLE, contains, mapOf("numValue" to 12))
|
||||
val doc = db.conn.findFirstByContains<JsonDocument, Map<String, String>>(TEST_TABLE, contains)
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("two", doc.id, "The incorrect document was returned")
|
||||
assertEquals(12, doc.numValue, "The document was not updated")
|
||||
}
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val contains = mapOf("value" to "updated")
|
||||
assertFalse("There should be no matching documents") { db.conn.existsByContains(TEST_TABLE, contains) }
|
||||
db.conn.patchByContains(TEST_TABLE, contains, mapOf("sub.foo" to "green")) // no exception = pass
|
||||
}
|
||||
|
||||
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val path = "$.numValue ? (@ > 10)"
|
||||
db.conn.patchByJsonPath(TEST_TABLE, path, mapOf("value" to "blue"))
|
||||
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, path)
|
||||
assertEquals(2, docs.size, "There should have been two documents returned")
|
||||
docs.forEach {
|
||||
assertTrue(listOf("four", "five").contains(it.id), "An incorrect document was returned (${it.id})")
|
||||
assertEquals("blue", it.value, "The value for ID ${it.id} was incorrect")
|
||||
}
|
||||
}
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val path = "$.numValue ? (@ > 100)"
|
||||
assertFalse("There should be no documents with numeric values over 100") {
|
||||
db.conn.existsByJsonPath(TEST_TABLE, path)
|
||||
}
|
||||
db.conn.patchByJsonPath(TEST_TABLE, path, mapOf("value" to "blue")) // no exception = pass
|
||||
}
|
||||
}
|
||||
47
src/kotlinx/src/test/kotlin/integration/PgDB.kt
Normal file
47
src/kotlinx/src/test/kotlin/integration/PgDB.kt
Normal file
@@ -0,0 +1,47 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.Results
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
|
||||
/**
|
||||
* A wrapper for a throwaway PostgreSQL database
|
||||
*/
|
||||
class PgDB : ThrowawayDatabase() {
|
||||
|
||||
init {
|
||||
Configuration.connectionString = connString("postgres")
|
||||
Configuration.dbConn().use { it.customNonQuery("CREATE DATABASE $dbName") }
|
||||
Configuration.connectionString = connString(dbName)
|
||||
}
|
||||
|
||||
override val conn = Configuration.dbConn()
|
||||
|
||||
init {
|
||||
conn.ensureTable(TEST_TABLE)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
conn.close()
|
||||
Configuration.connectionString = connString("postgres")
|
||||
Configuration.dbConn().use { it.customNonQuery("DROP DATABASE $dbName") }
|
||||
Configuration.connectionString = null
|
||||
}
|
||||
|
||||
override fun dbObjectExists(name: String) =
|
||||
conn.customScalar("SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = :name) AS it",
|
||||
listOf(Parameter(":name", ParameterType.STRING, name)), Results::toExists)
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Create a connection string for the given database
|
||||
*
|
||||
* @param database The database to which the library should connect
|
||||
* @return The connection string for the database
|
||||
*/
|
||||
private fun connString(database: String) =
|
||||
"jdbc:postgresql://localhost/$database?user=postgres&password=postgres"
|
||||
}
|
||||
}
|
||||
46
src/kotlinx/src/test/kotlin/integration/PostgreSQLCountIT.kt
Normal file
46
src/kotlinx/src/test/kotlin/integration/PostgreSQLCountIT.kt
Normal file
@@ -0,0 +1,46 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Count` object / `count*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Count")
|
||||
class PostgreSQLCountIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("all counts all documents")
|
||||
fun all() =
|
||||
PgDB().use(CountFunctions::all)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields counts documents by a numeric value")
|
||||
fun byFieldsNumeric() =
|
||||
PgDB().use(CountFunctions::byFieldsNumeric)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields counts documents by a alphanumeric value")
|
||||
fun byFieldsAlpha() =
|
||||
PgDB().use(CountFunctions::byFieldsAlpha)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains counts documents when matches are found")
|
||||
fun byContainsMatch() =
|
||||
PgDB().use(CountFunctions::byContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains counts documents when no matches are found")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(CountFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath counts documents when matches are found")
|
||||
fun byJsonPathMatch() =
|
||||
PgDB().use(CountFunctions::byJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath counts documents when no matches are found")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(CountFunctions::byJsonPathNoMatch)
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Custom")
|
||||
class PostgreSQLCustomIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("list succeeds with empty list")
|
||||
fun listEmpty() =
|
||||
PgDB().use(CustomFunctions::listEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("list succeeds with a non-empty list")
|
||||
fun listAll() =
|
||||
PgDB().use(CustomFunctions::listAll)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonArray succeeds with empty array")
|
||||
fun jsonArrayEmpty() =
|
||||
PgDB().use(CustomFunctions::jsonArrayEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonArray succeeds with a single-item array")
|
||||
fun jsonArraySingle() =
|
||||
PgDB().use(CustomFunctions::jsonArraySingle)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonArray succeeds with a multi-item array")
|
||||
fun jsonArrayMany() =
|
||||
PgDB().use(CustomFunctions::jsonArrayMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeJsonArray succeeds with empty array")
|
||||
fun writeJsonArrayEmpty() =
|
||||
PgDB().use(CustomFunctions::writeJsonArrayEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeJsonArray succeeds with a single-item array")
|
||||
fun writeJsonArraySingle() =
|
||||
PgDB().use(CustomFunctions::writeJsonArraySingle)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeJsonArray succeeds with a multi-item array")
|
||||
fun writeJsonArrayMany() =
|
||||
PgDB().use(CustomFunctions::writeJsonArrayMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("single succeeds when document not found")
|
||||
fun singleNone() =
|
||||
PgDB().use(CustomFunctions::singleNone)
|
||||
|
||||
@Test
|
||||
@DisplayName("single succeeds when a document is found")
|
||||
fun singleOne() =
|
||||
PgDB().use(CustomFunctions::singleOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonSingle succeeds when document not found")
|
||||
fun jsonSingleNone() =
|
||||
PgDB().use(CustomFunctions::jsonSingleNone)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonSingle succeeds when a document is found")
|
||||
fun jsonSingleOne() =
|
||||
PgDB().use(CustomFunctions::jsonSingleOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("nonQuery makes changes")
|
||||
fun nonQueryChanges() =
|
||||
PgDB().use(CustomFunctions::nonQueryChanges)
|
||||
|
||||
@Test
|
||||
@DisplayName("nonQuery makes no changes when where clause matches nothing")
|
||||
fun nonQueryNoChanges() =
|
||||
PgDB().use(CustomFunctions::nonQueryNoChanges)
|
||||
|
||||
@Test
|
||||
@DisplayName("scalar succeeds")
|
||||
fun scalar() =
|
||||
PgDB().use(CustomFunctions::scalar)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Definition` object / `ensure*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Definition")
|
||||
class PostgreSQLDefinitionIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureTable creates table and index")
|
||||
fun ensureTable() =
|
||||
PgDB().use(DefinitionFunctions::ensureTable)
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureFieldIndex creates an index")
|
||||
fun ensureFieldIndex() =
|
||||
PgDB().use(DefinitionFunctions::ensureFieldIndex)
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureDocumentIndex creates a full index")
|
||||
fun ensureDocumentIndexFull() =
|
||||
PgDB().use(DefinitionFunctions::ensureDocumentIndexFull)
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureDocumentIndex creates an optimized index")
|
||||
fun ensureDocumentIndexOptimized() =
|
||||
PgDB().use(DefinitionFunctions::ensureDocumentIndexOptimized)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Delete` object / `deleteBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Delete")
|
||||
class PostgreSQLDeleteIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId deletes a matching ID")
|
||||
fun byIdMatch() =
|
||||
PgDB().use(DeleteFunctions::byIdMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds when no ID matches")
|
||||
fun byIdNoMatch() =
|
||||
PgDB().use(DeleteFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields deletes matching documents")
|
||||
fun byFieldsMatch() =
|
||||
PgDB().use(DeleteFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
PgDB().use(DeleteFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains deletes matching documents")
|
||||
fun byContainsMatch() =
|
||||
PgDB().use(DeleteFunctions::byContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains succeeds when no documents match")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(DeleteFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath deletes matching documents")
|
||||
fun byJsonPathMatch() =
|
||||
PgDB().use(DeleteFunctions::byJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath succeeds when no documents match")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(DeleteFunctions::byJsonPathNoMatch)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Document")
|
||||
class PostgreSQLDocumentIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("insert works with default values")
|
||||
fun insertDefault() =
|
||||
PgDB().use(DocumentFunctions::insertDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert fails with duplicate key")
|
||||
fun insertDupe() =
|
||||
PgDB().use(DocumentFunctions::insertDupe)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert succeeds with numeric auto IDs")
|
||||
fun insertNumAutoId() =
|
||||
PgDB().use(DocumentFunctions::insertNumAutoId)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert succeeds with UUID auto ID")
|
||||
fun insertUUIDAutoId() =
|
||||
PgDB().use(DocumentFunctions::insertUUIDAutoId)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert succeeds with random string auto ID")
|
||||
fun insertStringAutoId() =
|
||||
PgDB().use(DocumentFunctions::insertStringAutoId)
|
||||
|
||||
@Test
|
||||
@DisplayName("save updates an existing document")
|
||||
fun saveMatch() =
|
||||
PgDB().use(DocumentFunctions::saveMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("save inserts a new document")
|
||||
fun saveNoMatch() =
|
||||
PgDB().use(DocumentFunctions::saveNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("update replaces an existing document")
|
||||
fun updateMatch() =
|
||||
PgDB().use(DocumentFunctions::updateMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("update succeeds when no document exists")
|
||||
fun updateNoMatch() =
|
||||
PgDB().use(DocumentFunctions::updateNoMatch)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Exists` object / `existsBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Exists")
|
||||
class PostgreSQLExistsIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns true when a document matches the ID")
|
||||
fun byIdMatch() =
|
||||
PgDB().use(ExistsFunctions::byIdMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns false when no document matches the ID")
|
||||
fun byIdNoMatch() =
|
||||
PgDB().use(ExistsFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields returns true when documents match")
|
||||
fun byFieldsMatch() =
|
||||
PgDB().use(ExistsFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields returns false when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
PgDB().use(ExistsFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains returns true when documents match")
|
||||
fun byContainsMatch() =
|
||||
PgDB().use(ExistsFunctions::byContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains returns false when no documents match")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(ExistsFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath returns true when documents match")
|
||||
fun byJsonPathMatch() =
|
||||
PgDB().use(ExistsFunctions::byJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath returns false when no documents match")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(ExistsFunctions::byJsonPathNoMatch)
|
||||
}
|
||||
171
src/kotlinx/src/test/kotlin/integration/PostgreSQLFindIT.kt
Normal file
171
src/kotlinx/src/test/kotlin/integration/PostgreSQLFindIT.kt
Normal file
@@ -0,0 +1,171 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Find` object / `find*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Find")
|
||||
class PostgreSQLFindIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("all retrieves all documents")
|
||||
fun allDefault() =
|
||||
PgDB().use(FindFunctions::allDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("all sorts data ascending")
|
||||
fun allAscending() =
|
||||
PgDB().use(FindFunctions::allAscending)
|
||||
|
||||
@Test
|
||||
@DisplayName("all sorts data descending")
|
||||
fun allDescending() =
|
||||
PgDB().use(FindFunctions::allDescending)
|
||||
|
||||
@Test
|
||||
@DisplayName("all sorts data numerically")
|
||||
fun allNumOrder() =
|
||||
PgDB().use(FindFunctions::allNumOrder)
|
||||
|
||||
@Test
|
||||
@DisplayName("all succeeds with an empty table")
|
||||
fun allEmpty() =
|
||||
PgDB().use(FindFunctions::allEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a string ID")
|
||||
fun byIdString() =
|
||||
PgDB().use(FindFunctions::byIdString)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a numeric ID")
|
||||
fun byIdNumber() =
|
||||
PgDB().use(FindFunctions::byIdNumber)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns null when a matching ID is not found")
|
||||
fun byIdNotFound() =
|
||||
PgDB().use(FindFunctions::byIdNotFound)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents")
|
||||
fun byFieldsMatch() =
|
||||
PgDB().use(FindFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves ordered matching documents")
|
||||
fun byFieldsMatchOrdered() =
|
||||
PgDB().use(FindFunctions::byFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with a numeric IN clause")
|
||||
fun byFieldsMatchNumIn() =
|
||||
PgDB().use(FindFunctions::byFieldsMatchNumIn)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
PgDB().use(FindFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with an IN_ARRAY comparison")
|
||||
fun byFieldsMatchInArray() =
|
||||
PgDB().use(FindFunctions::byFieldsMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match an IN_ARRAY comparison")
|
||||
fun byFieldsNoMatchInArray() =
|
||||
PgDB().use(FindFunctions::byFieldsNoMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains retrieves matching documents")
|
||||
fun byContainsMatch() =
|
||||
PgDB().use(FindFunctions::byContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains retrieves ordered matching documents")
|
||||
fun byContainsMatchOrdered() =
|
||||
PgDB().use(FindFunctions::byContainsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains succeeds when no documents match")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(FindFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath retrieves matching documents")
|
||||
fun byJsonPathMatch() =
|
||||
PgDB().use(FindFunctions::byJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath retrieves ordered matching documents")
|
||||
fun byJsonPathMatchOrdered() =
|
||||
PgDB().use(FindFunctions::byJsonPathMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath succeeds when no documents match")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(FindFunctions::byJsonPathNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document")
|
||||
fun firstByFieldsMatchOne() =
|
||||
PgDB().use(FindFunctions::firstByFieldsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many")
|
||||
fun firstByFieldsMatchMany() =
|
||||
PgDB().use(FindFunctions::firstByFieldsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many (ordered)")
|
||||
fun firstByFieldsMatchOrdered() =
|
||||
PgDB().use(FindFunctions::firstByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields returns null when no document matches")
|
||||
fun firstByFieldsNoMatch() =
|
||||
PgDB().use(FindFunctions::firstByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains retrieves a matching document")
|
||||
fun firstByContainsMatchOne() =
|
||||
PgDB().use(FindFunctions::firstByContainsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains retrieves a matching document among many")
|
||||
fun firstByContainsMatchMany() =
|
||||
PgDB().use(FindFunctions::firstByContainsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains retrieves a matching document among many (ordered)")
|
||||
fun firstByContainsMatchOrdered() =
|
||||
PgDB().use(FindFunctions::firstByContainsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains returns null when no document matches")
|
||||
fun firstByContainsNoMatch() =
|
||||
PgDB().use(FindFunctions::firstByContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath retrieves a matching document")
|
||||
fun firstByJsonPathMatchOne() =
|
||||
PgDB().use(FindFunctions::firstByJsonPathMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath retrieves a matching document among many")
|
||||
fun firstByJsonPathMatchMany() =
|
||||
PgDB().use(FindFunctions::firstByJsonPathMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath retrieves a matching document among many (ordered)")
|
||||
fun firstByJsonPathMatchOrdered() =
|
||||
PgDB().use(FindFunctions::firstByJsonPathMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath returns null when no document matches")
|
||||
fun firstByJsonPathNoMatch() =
|
||||
PgDB().use(FindFunctions::firstByJsonPathNoMatch)
|
||||
}
|
||||
301
src/kotlinx/src/test/kotlin/integration/PostgreSQLJsonIT.kt
Normal file
301
src/kotlinx/src/test/kotlin/integration/PostgreSQLJsonIT.kt
Normal file
@@ -0,0 +1,301 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Json` object / `json*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Json")
|
||||
class PostgreSQLJsonIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("all retrieves all documents")
|
||||
fun allDefault() =
|
||||
PgDB().use(JsonFunctions::allDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("all succeeds with an empty table")
|
||||
fun allEmpty() =
|
||||
PgDB().use(JsonFunctions::allEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a string ID")
|
||||
fun byIdString() =
|
||||
PgDB().use(JsonFunctions::byIdString)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a numeric ID")
|
||||
fun byIdNumber() =
|
||||
PgDB().use(JsonFunctions::byIdNumber)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns null when a matching ID is not found")
|
||||
fun byIdNotFound() =
|
||||
PgDB().use(JsonFunctions::byIdNotFound)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents")
|
||||
fun byFieldsMatch() =
|
||||
PgDB().use(JsonFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves ordered matching documents")
|
||||
fun byFieldsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::byFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with a numeric IN clause")
|
||||
fun byFieldsMatchNumIn() =
|
||||
PgDB().use(JsonFunctions::byFieldsMatchNumIn)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
PgDB().use(JsonFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with an IN_ARRAY comparison")
|
||||
fun byFieldsMatchInArray() =
|
||||
PgDB().use(JsonFunctions::byFieldsMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match an IN_ARRAY comparison")
|
||||
fun byFieldsNoMatchInArray() =
|
||||
PgDB().use(JsonFunctions::byFieldsNoMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains retrieves matching documents")
|
||||
fun byContainsMatch() =
|
||||
PgDB().use(JsonFunctions::byContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains retrieves ordered matching documents")
|
||||
fun byContainsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::byContainsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains succeeds when no documents match")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(JsonFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath retrieves matching documents")
|
||||
fun byJsonPathMatch() =
|
||||
PgDB().use(JsonFunctions::byJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath retrieves ordered matching documents")
|
||||
fun byJsonPathMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::byJsonPathMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath succeeds when no documents match")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(JsonFunctions::byJsonPathNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document")
|
||||
fun firstByFieldsMatchOne() =
|
||||
PgDB().use(JsonFunctions::firstByFieldsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many")
|
||||
fun firstByFieldsMatchMany() =
|
||||
PgDB().use(JsonFunctions::firstByFieldsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many (ordered)")
|
||||
fun firstByFieldsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::firstByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields returns null when no document matches")
|
||||
fun firstByFieldsNoMatch() =
|
||||
PgDB().use(JsonFunctions::firstByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains retrieves a matching document")
|
||||
fun firstByContainsMatchOne() =
|
||||
PgDB().use(JsonFunctions::firstByContainsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains retrieves a matching document among many")
|
||||
fun firstByContainsMatchMany() =
|
||||
PgDB().use(JsonFunctions::firstByContainsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains retrieves a matching document among many (ordered)")
|
||||
fun firstByContainsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::firstByContainsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains returns null when no document matches")
|
||||
fun firstByContainsNoMatch() =
|
||||
PgDB().use(JsonFunctions::firstByContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath retrieves a matching document")
|
||||
fun firstByJsonPathMatchOne() =
|
||||
PgDB().use(JsonFunctions::firstByJsonPathMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath retrieves a matching document among many")
|
||||
fun firstByJsonPathMatchMany() =
|
||||
PgDB().use(JsonFunctions::firstByJsonPathMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath retrieves a matching document among many (ordered)")
|
||||
fun firstByJsonPathMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::firstByJsonPathMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath returns null when no document matches")
|
||||
fun firstByJsonPathNoMatch() =
|
||||
PgDB().use(JsonFunctions::firstByJsonPathNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeAll retrieves all documents")
|
||||
fun writeAllDefault() =
|
||||
PgDB().use(JsonFunctions::writeAllDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeAll succeeds with an empty table")
|
||||
fun writeAllEmpty() =
|
||||
PgDB().use(JsonFunctions::writeAllEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeById retrieves a document via a string ID")
|
||||
fun writeByIdString() =
|
||||
PgDB().use(JsonFunctions::writeByIdString)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeById retrieves a document via a numeric ID")
|
||||
fun writeByIdNumber() =
|
||||
PgDB().use(JsonFunctions::writeByIdNumber)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeById returns null when a matching ID is not found")
|
||||
fun writeByIdNotFound() =
|
||||
PgDB().use(JsonFunctions::writeByIdNotFound)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves matching documents")
|
||||
fun writeByFieldsMatch() =
|
||||
PgDB().use(JsonFunctions::writeByFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves ordered matching documents")
|
||||
fun writeByFieldsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::writeByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves matching documents with a numeric IN clause")
|
||||
fun writeByFieldsMatchNumIn() =
|
||||
PgDB().use(JsonFunctions::writeByFieldsMatchNumIn)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields succeeds when no documents match")
|
||||
fun writeByFieldsNoMatch() =
|
||||
PgDB().use(JsonFunctions::writeByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves matching documents with an IN_ARRAY comparison")
|
||||
fun writeByFieldsMatchInArray() =
|
||||
PgDB().use(JsonFunctions::writeByFieldsMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields succeeds when no documents match an IN_ARRAY comparison")
|
||||
fun writeByFieldsNoMatchInArray() =
|
||||
PgDB().use(JsonFunctions::writeByFieldsNoMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByContains retrieves matching documents")
|
||||
fun writeByContainsMatch() =
|
||||
PgDB().use(JsonFunctions::writeByContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByContains retrieves ordered matching documents")
|
||||
fun writeByContainsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::writeByContainsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByContains succeeds when no documents match")
|
||||
fun writeByContainsNoMatch() =
|
||||
PgDB().use(JsonFunctions::writeByContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByJsonPath retrieves matching documents")
|
||||
fun writeByJsonPathMatch() =
|
||||
PgDB().use(JsonFunctions::writeByJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByJsonPath retrieves ordered matching documents")
|
||||
fun writeByJsonPathMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::writeByJsonPathMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByJsonPath succeeds when no documents match")
|
||||
fun writeByJsonPathNoMatch() =
|
||||
PgDB().use(JsonFunctions::writeByJsonPathNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields retrieves a matching document")
|
||||
fun writeFirstByFieldsMatchOne() =
|
||||
PgDB().use(JsonFunctions::writeFirstByFieldsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields retrieves a matching document among many")
|
||||
fun writeFirstByFieldsMatchMany() =
|
||||
PgDB().use(JsonFunctions::writeFirstByFieldsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields retrieves a matching document among many (ordered)")
|
||||
fun writeFirstByFieldsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::writeFirstByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields returns null when no document matches")
|
||||
fun writeFirstByFieldsNoMatch() =
|
||||
PgDB().use(JsonFunctions::writeFirstByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByContains retrieves a matching document")
|
||||
fun writeFirstByContainsMatchOne() =
|
||||
PgDB().use(JsonFunctions::writeFirstByContainsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByContains retrieves a matching document among many")
|
||||
fun writeFirstByContainsMatchMany() =
|
||||
PgDB().use(JsonFunctions::writeFirstByContainsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByContains retrieves a matching document among many (ordered)")
|
||||
fun writeFirstByContainsMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::writeFirstByContainsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByContains returns null when no document matches")
|
||||
fun writeFirstByContainsNoMatch() =
|
||||
PgDB().use(JsonFunctions::writeFirstByContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByJsonPath retrieves a matching document")
|
||||
fun writeFirstByJsonPathMatchOne() =
|
||||
PgDB().use(JsonFunctions::writeFirstByJsonPathMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByJsonPath retrieves a matching document among many")
|
||||
fun writeFirstByJsonPathMatchMany() =
|
||||
PgDB().use(JsonFunctions::writeFirstByJsonPathMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByJsonPath retrieves a matching document among many (ordered)")
|
||||
fun writeFirstByJsonPathMatchOrdered() =
|
||||
PgDB().use(JsonFunctions::writeFirstByJsonPathMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByJsonPath returns null when no document matches")
|
||||
fun writeFirstByJsonPathNoMatch() =
|
||||
PgDB().use(JsonFunctions::writeFirstByJsonPathNoMatch)
|
||||
}
|
||||
51
src/kotlinx/src/test/kotlin/integration/PostgreSQLPatchIT.kt
Normal file
51
src/kotlinx/src/test/kotlin/integration/PostgreSQLPatchIT.kt
Normal file
@@ -0,0 +1,51 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `Patch` object / `patchBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: Patch")
|
||||
class PostgreSQLPatchIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId patches an existing document")
|
||||
fun byIdMatch() =
|
||||
PgDB().use(PatchFunctions::byIdMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds for a non-existent document")
|
||||
fun byIdNoMatch() =
|
||||
PgDB().use(PatchFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields patches matching document")
|
||||
fun byFieldsMatch() =
|
||||
PgDB().use(PatchFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
PgDB().use(PatchFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains patches matching document")
|
||||
fun byContainsMatch() =
|
||||
PgDB().use(PatchFunctions::byContainsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains succeeds when no documents match")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(PatchFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath patches matching document")
|
||||
fun byJsonPathMatch() =
|
||||
PgDB().use(PatchFunctions::byJsonPathMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath succeeds when no documents match")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(PatchFunctions::byJsonPathNoMatch)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* PostgreSQL integration tests for the `RemoveFields` object / `removeFieldsBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | PostgreSQL: RemoveFields")
|
||||
class PostgreSQLRemoveFieldsIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId removes fields from an existing document")
|
||||
fun byIdMatchFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byIdMatchFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds when fields do not exist on an existing document")
|
||||
fun byIdMatchNoFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byIdMatchNoFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds when no document exists")
|
||||
fun byIdNoMatch() =
|
||||
PgDB().use(RemoveFieldsFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields removes fields from matching documents")
|
||||
fun byFieldsMatchFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byFieldsMatchFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when fields do not exist on matching documents")
|
||||
fun byFieldsMatchNoFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byFieldsMatchNoFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no matching documents exist")
|
||||
fun byFieldsNoMatch() =
|
||||
PgDB().use(RemoveFieldsFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains removes fields from matching documents")
|
||||
fun byContainsMatchFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byContainsMatchFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains succeeds when fields do not exist on matching documents")
|
||||
fun byContainsMatchNoFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byContainsMatchNoFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains succeeds when no matching documents exist")
|
||||
fun byContainsNoMatch() =
|
||||
PgDB().use(RemoveFieldsFunctions::byContainsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath removes fields from matching documents")
|
||||
fun byJsonPathMatchFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byJsonPathMatchFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath succeeds when fields do not exist on matching documents")
|
||||
fun byJsonPathMatchNoFields() =
|
||||
PgDB().use(RemoveFieldsFunctions::byJsonPathMatchNoFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath succeeds when no matching documents exist")
|
||||
fun byJsonPathNoMatch() =
|
||||
PgDB().use(RemoveFieldsFunctions::byJsonPathNoMatch)
|
||||
}
|
||||
108
src/kotlinx/src/test/kotlin/integration/RemoveFieldsFunctions.kt
Normal file
108
src/kotlinx/src/test/kotlin/integration/RemoveFieldsFunctions.kt
Normal file
@@ -0,0 +1,108 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.JsonDocument
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import kotlin.test.*
|
||||
|
||||
/**
|
||||
* Integration tests for the `RemoveFields` object
|
||||
*/
|
||||
object RemoveFieldsFunctions {
|
||||
|
||||
fun byIdMatchFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
db.conn.removeFieldsById(TEST_TABLE, "two", listOf("sub", "value"))
|
||||
val doc = db.conn.findById<String, JsonDocument>(TEST_TABLE, "two")
|
||||
assertNotNull(doc, "There should have been a document returned")
|
||||
assertEquals("", doc.value, "The value should have been empty")
|
||||
assertNull(doc.sub, "The sub-document should have been removed")
|
||||
}
|
||||
|
||||
fun byIdMatchNoFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse { db.conn.existsByFields(TEST_TABLE, listOf(Field.exists("a_field_that_does_not_exist"))) }
|
||||
db.conn.removeFieldsById(TEST_TABLE, "one", listOf("a_field_that_does_not_exist")) // no exception = pass
|
||||
}
|
||||
|
||||
fun byIdNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse { db.conn.existsById(TEST_TABLE, "fifty") }
|
||||
db.conn.removeFieldsById(TEST_TABLE, "fifty", listOf("sub")) // no exception = pass
|
||||
}
|
||||
|
||||
fun byFieldsMatchFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val fields = listOf(Field.equal("numValue", 17))
|
||||
db.conn.removeFieldsByFields(TEST_TABLE, fields, listOf("sub"))
|
||||
val doc = db.conn.findFirstByFields<JsonDocument>(TEST_TABLE, fields)
|
||||
assertNotNull(doc, "The document should have been returned")
|
||||
assertEquals("four", doc.id, "An incorrect document was returned")
|
||||
assertNull(doc.sub, "The sub-document should have been removed")
|
||||
}
|
||||
|
||||
fun byFieldsMatchNoFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse { db.conn.existsByFields(TEST_TABLE, listOf(Field.exists("nada"))) }
|
||||
db.conn.removeFieldsByFields(TEST_TABLE, listOf(Field.equal("numValue", 17)), listOf("nada")) // no exn = pass
|
||||
}
|
||||
|
||||
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val fields = listOf(Field.notEqual("missing", "nope"))
|
||||
assertFalse { db.conn.existsByFields(TEST_TABLE, fields) }
|
||||
db.conn.removeFieldsByFields(TEST_TABLE, fields, listOf("value")) // no exception = pass
|
||||
}
|
||||
|
||||
fun byContainsMatchFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val criteria = mapOf("sub" to mapOf("foo" to "green"))
|
||||
db.conn.removeFieldsByContains(TEST_TABLE, criteria, listOf("value"))
|
||||
val docs = db.conn.findByContains<JsonDocument, Map<String, Map<String, String>>>(TEST_TABLE, criteria)
|
||||
assertEquals(2, docs.size, "There should have been 2 documents returned")
|
||||
docs.forEach {
|
||||
assertTrue(listOf("two", "four").contains(it.id), "An incorrect document was returned (${it.id})")
|
||||
assertEquals("", it.value, "The value should have been empty")
|
||||
}
|
||||
}
|
||||
|
||||
fun byContainsMatchNoFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse { db.conn.existsByFields(TEST_TABLE, listOf(Field.exists("invalid_field"))) }
|
||||
db.conn.removeFieldsByContains(TEST_TABLE, mapOf("sub" to mapOf("foo" to "green")), listOf("invalid_field"))
|
||||
// no exception = pass
|
||||
}
|
||||
|
||||
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val contains = mapOf("value" to "substantial")
|
||||
assertFalse { db.conn.existsByContains(TEST_TABLE, contains) }
|
||||
db.conn.removeFieldsByContains(TEST_TABLE, contains, listOf("numValue"))
|
||||
}
|
||||
|
||||
fun byJsonPathMatchFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val path = "$.value ? (@ == \"purple\")"
|
||||
db.conn.removeFieldsByJsonPath(TEST_TABLE, path, listOf("sub"))
|
||||
val docs = db.conn.findByJsonPath<JsonDocument>(TEST_TABLE, path)
|
||||
assertEquals(2, docs.size, "There should have been 2 documents returned")
|
||||
docs.forEach {
|
||||
assertTrue(listOf("four", "five").contains(it.id), "An incorrect document was returned (${it.id})")
|
||||
assertNull(it.sub, "The sub-document should have been removed")
|
||||
}
|
||||
}
|
||||
|
||||
fun byJsonPathMatchNoFields(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
assertFalse { db.conn.existsByFields(TEST_TABLE, listOf(Field.exists("submarine"))) }
|
||||
db.conn.removeFieldsByJsonPath(TEST_TABLE, "$.value ? (@ == \"purple\")", listOf("submarine")) // no exn = pass
|
||||
}
|
||||
|
||||
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||
JsonDocument.load(db)
|
||||
val path = "$.value ? (@ == \"mauve\")"
|
||||
assertFalse { db.conn.existsByJsonPath(TEST_TABLE, path) }
|
||||
db.conn.removeFieldsByJsonPath(TEST_TABLE, path, listOf("value")) // no exception = pass
|
||||
}
|
||||
}
|
||||
40
src/kotlinx/src/test/kotlin/integration/SQLiteCountIT.kt
Normal file
40
src/kotlinx/src/test/kotlin/integration/SQLiteCountIT.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Count` object / `count*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Count")
|
||||
class SQLiteCountIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("all counts all documents")
|
||||
fun all() =
|
||||
SQLiteDB().use(CountFunctions::all)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields counts documents by a numeric value")
|
||||
fun byFieldsNumeric() =
|
||||
SQLiteDB().use(CountFunctions::byFieldsNumeric)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields counts documents by a alphanumeric value")
|
||||
fun byFieldsAlpha() =
|
||||
SQLiteDB().use(CountFunctions::byFieldsAlpha)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsMatch() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(CountFunctions::byContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathMatch() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(CountFunctions::byJsonPathMatch) }
|
||||
}
|
||||
}
|
||||
86
src/kotlinx/src/test/kotlin/integration/SQLiteCustomIT.kt
Normal file
86
src/kotlinx/src/test/kotlin/integration/SQLiteCustomIT.kt
Normal file
@@ -0,0 +1,86 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Custom` object / `custom*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Custom")
|
||||
class SQLiteCustomIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("list succeeds with empty list")
|
||||
fun listEmpty() =
|
||||
SQLiteDB().use(CustomFunctions::listEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("list succeeds with a non-empty list")
|
||||
fun listAll() =
|
||||
SQLiteDB().use(CustomFunctions::listAll)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonArray succeeds with empty array")
|
||||
fun jsonArrayEmpty() =
|
||||
SQLiteDB().use(CustomFunctions::jsonArrayEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonArray succeeds with a single-item array")
|
||||
fun jsonArraySingle() =
|
||||
SQLiteDB().use(CustomFunctions::jsonArraySingle)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonArray succeeds with a multi-item array")
|
||||
fun jsonArrayMany() =
|
||||
SQLiteDB().use(CustomFunctions::jsonArrayMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeJsonArray succeeds with empty array")
|
||||
fun writeJsonArrayEmpty() =
|
||||
SQLiteDB().use(CustomFunctions::writeJsonArrayEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeJsonArray succeeds with a single-item array")
|
||||
fun writeJsonArraySingle() =
|
||||
SQLiteDB().use(CustomFunctions::writeJsonArraySingle)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeJsonArray succeeds with a multi-item array")
|
||||
fun writeJsonArrayMany() =
|
||||
SQLiteDB().use(CustomFunctions::writeJsonArrayMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("single succeeds when document not found")
|
||||
fun singleNone() =
|
||||
SQLiteDB().use(CustomFunctions::singleNone)
|
||||
|
||||
@Test
|
||||
@DisplayName("single succeeds when a document is found")
|
||||
fun singleOne() =
|
||||
SQLiteDB().use(CustomFunctions::singleOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonSingle succeeds when document not found")
|
||||
fun jsonSingleNone() =
|
||||
SQLiteDB().use(CustomFunctions::jsonSingleNone)
|
||||
|
||||
@Test
|
||||
@DisplayName("jsonSingle succeeds when a document is found")
|
||||
fun jsonSingleOne() =
|
||||
SQLiteDB().use(CustomFunctions::jsonSingleOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("nonQuery makes changes")
|
||||
fun nonQueryChanges() =
|
||||
SQLiteDB().use(CustomFunctions::nonQueryChanges)
|
||||
|
||||
@Test
|
||||
@DisplayName("nonQuery makes no changes when where clause matches nothing")
|
||||
fun nonQueryNoChanges() =
|
||||
SQLiteDB().use(CustomFunctions::nonQueryNoChanges)
|
||||
|
||||
@Test
|
||||
@DisplayName("scalar succeeds")
|
||||
fun scalar() =
|
||||
SQLiteDB().use(CustomFunctions::scalar)
|
||||
}
|
||||
32
src/kotlinx/src/test/kotlin/integration/SQLiteDB.kt
Normal file
32
src/kotlinx/src/test/kotlin/integration/SQLiteDB.kt
Normal file
@@ -0,0 +1,32 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlinx.extensions.*
|
||||
import solutions.bitbadger.documents.kotlinx.tests.TEST_TABLE
|
||||
import solutions.bitbadger.documents.kotlinx.Results
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* A wrapper for a throwaway SQLite database
|
||||
*/
|
||||
class SQLiteDB : ThrowawayDatabase() {
|
||||
|
||||
init {
|
||||
Configuration.connectionString = "jdbc:sqlite:$dbName"
|
||||
}
|
||||
|
||||
override val conn = Configuration.dbConn()
|
||||
|
||||
init {
|
||||
conn.ensureTable(TEST_TABLE)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
conn.close()
|
||||
File(dbName).delete()
|
||||
}
|
||||
|
||||
override fun dbObjectExists(name: String) =
|
||||
conn.customScalar("SELECT EXISTS (SELECT 1 FROM sqlite_master WHERE name = :name) AS it",
|
||||
listOf(Parameter(":name", ParameterType.STRING, name)), Results::toExists)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Definition` object / `ensure*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Definition")
|
||||
class SQLiteDefinitionIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureTable creates table and index")
|
||||
fun ensureTable() =
|
||||
SQLiteDB().use(DefinitionFunctions::ensureTable)
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureFieldIndex creates an index")
|
||||
fun ensureFieldIndex() =
|
||||
SQLiteDB().use(DefinitionFunctions::ensureFieldIndex)
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureDocumentIndex fails for full index")
|
||||
fun ensureDocumentIndexFull() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(DefinitionFunctions::ensureDocumentIndexFull) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ensureDocumentIndex fails for optimized index")
|
||||
fun ensureDocumentIndexOptimized() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(DefinitionFunctions::ensureDocumentIndexOptimized) }
|
||||
}
|
||||
}
|
||||
45
src/kotlinx/src/test/kotlin/integration/SQLiteDeleteIT.kt
Normal file
45
src/kotlinx/src/test/kotlin/integration/SQLiteDeleteIT.kt
Normal file
@@ -0,0 +1,45 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Delete` object / `deleteBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Delete")
|
||||
class SQLiteDeleteIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId deletes a matching ID")
|
||||
fun byIdMatch() =
|
||||
SQLiteDB().use(DeleteFunctions::byIdMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds when no ID matches")
|
||||
fun byIdNoMatch() =
|
||||
SQLiteDB().use(DeleteFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields deletes matching documents")
|
||||
fun byFieldsMatch() =
|
||||
SQLiteDB().use(DeleteFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
SQLiteDB().use(DeleteFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(DeleteFunctions::byContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(DeleteFunctions::byJsonPathMatch) }
|
||||
}
|
||||
}
|
||||
56
src/kotlinx/src/test/kotlin/integration/SQLiteDocumentIT.kt
Normal file
56
src/kotlinx/src/test/kotlin/integration/SQLiteDocumentIT.kt
Normal file
@@ -0,0 +1,56 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Document")
|
||||
class SQLiteDocumentIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("insert works with default values")
|
||||
fun insertDefault() =
|
||||
SQLiteDB().use(DocumentFunctions::insertDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert fails with duplicate key")
|
||||
fun insertDupe() =
|
||||
SQLiteDB().use(DocumentFunctions::insertDupe)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert succeeds with numeric auto IDs")
|
||||
fun insertNumAutoId() =
|
||||
SQLiteDB().use(DocumentFunctions::insertNumAutoId)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert succeeds with UUID auto ID")
|
||||
fun insertUUIDAutoId() =
|
||||
SQLiteDB().use(DocumentFunctions::insertUUIDAutoId)
|
||||
|
||||
@Test
|
||||
@DisplayName("insert succeeds with random string auto ID")
|
||||
fun insertStringAutoId() =
|
||||
SQLiteDB().use(DocumentFunctions::insertStringAutoId)
|
||||
|
||||
@Test
|
||||
@DisplayName("save updates an existing document")
|
||||
fun saveMatch() =
|
||||
SQLiteDB().use(DocumentFunctions::saveMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("save inserts a new document")
|
||||
fun saveNoMatch() =
|
||||
SQLiteDB().use(DocumentFunctions::saveNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("update replaces an existing document")
|
||||
fun updateMatch() =
|
||||
SQLiteDB().use(DocumentFunctions::updateMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("update succeeds when no document exists")
|
||||
fun updateNoMatch() =
|
||||
SQLiteDB().use(DocumentFunctions::updateNoMatch)
|
||||
}
|
||||
45
src/kotlinx/src/test/kotlin/integration/SQLiteExistsIT.kt
Normal file
45
src/kotlinx/src/test/kotlin/integration/SQLiteExistsIT.kt
Normal file
@@ -0,0 +1,45 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Exists` object / `existsBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Exists")
|
||||
class SQLiteExistsIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns true when a document matches the ID")
|
||||
fun byIdMatch() =
|
||||
SQLiteDB().use(ExistsFunctions::byIdMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns false when no document matches the ID")
|
||||
fun byIdNoMatch() =
|
||||
SQLiteDB().use(ExistsFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields returns true when documents match")
|
||||
fun byFieldsMatch() =
|
||||
SQLiteDB().use(ExistsFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields returns false when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
SQLiteDB().use(ExistsFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(ExistsFunctions::byContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(ExistsFunctions::byJsonPathMatch) }
|
||||
}
|
||||
}
|
||||
127
src/kotlinx/src/test/kotlin/integration/SQLiteFindIT.kt
Normal file
127
src/kotlinx/src/test/kotlin/integration/SQLiteFindIT.kt
Normal file
@@ -0,0 +1,127 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Find` object / `find*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Find")
|
||||
class SQLiteFindIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("all retrieves all documents")
|
||||
fun allDefault() =
|
||||
SQLiteDB().use(FindFunctions::allDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("all sorts data ascending")
|
||||
fun allAscending() =
|
||||
SQLiteDB().use(FindFunctions::allAscending)
|
||||
|
||||
@Test
|
||||
@DisplayName("all sorts data descending")
|
||||
fun allDescending() =
|
||||
SQLiteDB().use(FindFunctions::allDescending)
|
||||
|
||||
@Test
|
||||
@DisplayName("all sorts data numerically")
|
||||
fun allNumOrder() =
|
||||
SQLiteDB().use(FindFunctions::allNumOrder)
|
||||
|
||||
@Test
|
||||
@DisplayName("all succeeds with an empty table")
|
||||
fun allEmpty() =
|
||||
SQLiteDB().use(FindFunctions::allEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a string ID")
|
||||
fun byIdString() =
|
||||
SQLiteDB().use(FindFunctions::byIdString)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a numeric ID")
|
||||
fun byIdNumber() =
|
||||
SQLiteDB().use(FindFunctions::byIdNumber)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns null when a matching ID is not found")
|
||||
fun byIdNotFound() =
|
||||
SQLiteDB().use(FindFunctions::byIdNotFound)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents")
|
||||
fun byFieldsMatch() =
|
||||
SQLiteDB().use(FindFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves ordered matching documents")
|
||||
fun byFieldsMatchOrdered() =
|
||||
SQLiteDB().use(FindFunctions::byFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with a numeric IN clause")
|
||||
fun byFieldsMatchNumIn() =
|
||||
SQLiteDB().use(FindFunctions::byFieldsMatchNumIn)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
SQLiteDB().use(FindFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with an IN_ARRAY comparison")
|
||||
fun byFieldsMatchInArray() =
|
||||
SQLiteDB().use(FindFunctions::byFieldsMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match an IN_ARRAY comparison")
|
||||
fun byFieldsNoMatchInArray() =
|
||||
SQLiteDB().use(FindFunctions::byFieldsNoMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(FindFunctions::byContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(FindFunctions::byJsonPathMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document")
|
||||
fun firstByFieldsMatchOne() =
|
||||
SQLiteDB().use(FindFunctions::firstByFieldsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many")
|
||||
fun firstByFieldsMatchMany() =
|
||||
SQLiteDB().use(FindFunctions::firstByFieldsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many (ordered)")
|
||||
fun firstByFieldsMatchOrdered() =
|
||||
SQLiteDB().use(FindFunctions::firstByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields returns null when no document matches")
|
||||
fun firstByFieldsNoMatch() =
|
||||
SQLiteDB().use(FindFunctions::firstByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains fails")
|
||||
fun firstByContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(FindFunctions::firstByContainsMatchOne) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath fails")
|
||||
fun firstByJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(FindFunctions::firstByJsonPathMatchOne) }
|
||||
}
|
||||
}
|
||||
211
src/kotlinx/src/test/kotlin/integration/SQLiteJsonIT.kt
Normal file
211
src/kotlinx/src/test/kotlin/integration/SQLiteJsonIT.kt
Normal file
@@ -0,0 +1,211 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Json` object / `json*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Json")
|
||||
class SQLiteJsonIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("all retrieves all documents")
|
||||
fun allDefault() =
|
||||
SQLiteDB().use(JsonFunctions::allDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("all succeeds with an empty table")
|
||||
fun allEmpty() =
|
||||
SQLiteDB().use(JsonFunctions::allEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a string ID")
|
||||
fun byIdString() =
|
||||
SQLiteDB().use(JsonFunctions::byIdString)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId retrieves a document via a numeric ID")
|
||||
fun byIdNumber() =
|
||||
SQLiteDB().use(JsonFunctions::byIdNumber)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId returns null when a matching ID is not found")
|
||||
fun byIdNotFound() =
|
||||
SQLiteDB().use(JsonFunctions::byIdNotFound)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents")
|
||||
fun byFieldsMatch() =
|
||||
SQLiteDB().use(JsonFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves ordered matching documents")
|
||||
fun byFieldsMatchOrdered() =
|
||||
SQLiteDB().use(JsonFunctions::byFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with a numeric IN clause")
|
||||
fun byFieldsMatchNumIn() =
|
||||
SQLiteDB().use(JsonFunctions::byFieldsMatchNumIn)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
SQLiteDB().use(JsonFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields retrieves matching documents with an IN_ARRAY comparison")
|
||||
fun byFieldsMatchInArray() =
|
||||
SQLiteDB().use(JsonFunctions::byFieldsMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match an IN_ARRAY comparison")
|
||||
fun byFieldsNoMatchInArray() =
|
||||
SQLiteDB().use(JsonFunctions::byFieldsNoMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::byContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::byJsonPathMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document")
|
||||
fun firstByFieldsMatchOne() =
|
||||
SQLiteDB().use(JsonFunctions::firstByFieldsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many")
|
||||
fun firstByFieldsMatchMany() =
|
||||
SQLiteDB().use(JsonFunctions::firstByFieldsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields retrieves a matching document among many (ordered)")
|
||||
fun firstByFieldsMatchOrdered() =
|
||||
SQLiteDB().use(JsonFunctions::firstByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByFields returns null when no document matches")
|
||||
fun firstByFieldsNoMatch() =
|
||||
SQLiteDB().use(JsonFunctions::firstByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByContains fails")
|
||||
fun firstByContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::firstByContainsMatchOne) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("firstByJsonPath fails")
|
||||
fun firstByJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::firstByJsonPathMatchOne) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("writeAll retrieves all documents")
|
||||
fun writeAllDefault() =
|
||||
SQLiteDB().use(JsonFunctions::writeAllDefault)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeAll succeeds with an empty table")
|
||||
fun writeAllEmpty() =
|
||||
SQLiteDB().use(JsonFunctions::writeAllEmpty)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeById retrieves a document via a string ID")
|
||||
fun writeByIdString() =
|
||||
SQLiteDB().use(JsonFunctions::writeByIdString)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeById retrieves a document via a numeric ID")
|
||||
fun writeByIdNumber() =
|
||||
SQLiteDB().use(JsonFunctions::writeByIdNumber)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeById returns null when a matching ID is not found")
|
||||
fun writeByIdNotFound() =
|
||||
SQLiteDB().use(JsonFunctions::writeByIdNotFound)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves matching documents")
|
||||
fun writeByFieldsMatch() =
|
||||
SQLiteDB().use(JsonFunctions::writeByFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves ordered matching documents")
|
||||
fun writeByFieldsMatchOrdered() =
|
||||
SQLiteDB().use(JsonFunctions::writeByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves matching documents with a numeric IN clause")
|
||||
fun writeByFieldsMatchNumIn() =
|
||||
SQLiteDB().use(JsonFunctions::writeByFieldsMatchNumIn)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields succeeds when no documents match")
|
||||
fun writeByFieldsNoMatch() =
|
||||
SQLiteDB().use(JsonFunctions::writeByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields retrieves matching documents with an IN_ARRAY comparison")
|
||||
fun writeByFieldsMatchInArray() =
|
||||
SQLiteDB().use(JsonFunctions::writeByFieldsMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByFields succeeds when no documents match an IN_ARRAY comparison")
|
||||
fun writeByFieldsNoMatchInArray() =
|
||||
SQLiteDB().use(JsonFunctions::writeByFieldsNoMatchInArray)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByContains fails")
|
||||
fun writeByContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::writeByContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("writeByJsonPath fails")
|
||||
fun writeByJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::writeByJsonPathMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields retrieves a matching document")
|
||||
fun writeFirstByFieldsMatchOne() =
|
||||
SQLiteDB().use(JsonFunctions::writeFirstByFieldsMatchOne)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields retrieves a matching document among many")
|
||||
fun writeFirstByFieldsMatchMany() =
|
||||
SQLiteDB().use(JsonFunctions::writeFirstByFieldsMatchMany)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields retrieves a matching document among many (ordered)")
|
||||
fun writeFirstByFieldsMatchOrdered() =
|
||||
SQLiteDB().use(JsonFunctions::writeFirstByFieldsMatchOrdered)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByFields returns null when no document matches")
|
||||
fun writeFirstByFieldsNoMatch() =
|
||||
SQLiteDB().use(JsonFunctions::writeFirstByFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByContains fails")
|
||||
fun writeFirstByContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::writeFirstByContainsMatchOne) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("writeFirstByJsonPath fails")
|
||||
fun writeFirstByJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(JsonFunctions::writeFirstByJsonPathMatchOne) }
|
||||
}
|
||||
}
|
||||
45
src/kotlinx/src/test/kotlin/integration/SQLitePatchIT.kt
Normal file
45
src/kotlinx/src/test/kotlin/integration/SQLitePatchIT.kt
Normal file
@@ -0,0 +1,45 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `Patch` object / `patchBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: Patch")
|
||||
class SQLitePatchIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId patches an existing document")
|
||||
fun byIdMatch() =
|
||||
SQLiteDB().use(PatchFunctions::byIdMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds for a non-existent document")
|
||||
fun byIdNoMatch() =
|
||||
SQLiteDB().use(PatchFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields patches matching document")
|
||||
fun byFieldsMatch() =
|
||||
SQLiteDB().use(PatchFunctions::byFieldsMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no documents match")
|
||||
fun byFieldsNoMatch() =
|
||||
SQLiteDB().use(PatchFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(PatchFunctions::byContainsMatch) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(PatchFunctions::byJsonPathMatch) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import kotlin.test.Test
|
||||
|
||||
/**
|
||||
* SQLite integration tests for the `RemoveFields` object / `removeFieldsBy*` connection extension functions
|
||||
*/
|
||||
@DisplayName("KotlinX | SQLite: RemoveFields")
|
||||
class SQLiteRemoveFieldsIT {
|
||||
|
||||
@Test
|
||||
@DisplayName("byId removes fields from an existing document")
|
||||
fun byIdMatchFields() =
|
||||
SQLiteDB().use(RemoveFieldsFunctions::byIdMatchFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds when fields do not exist on an existing document")
|
||||
fun byIdMatchNoFields() =
|
||||
SQLiteDB().use(RemoveFieldsFunctions::byIdMatchNoFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byId succeeds when no document exists")
|
||||
fun byIdNoMatch() =
|
||||
SQLiteDB().use(RemoveFieldsFunctions::byIdNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields removes fields from matching documents")
|
||||
fun byFieldsMatchFields() =
|
||||
SQLiteDB().use(RemoveFieldsFunctions::byFieldsMatchFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when fields do not exist on matching documents")
|
||||
fun byFieldsMatchNoFields() =
|
||||
SQLiteDB().use(RemoveFieldsFunctions::byFieldsMatchNoFields)
|
||||
|
||||
@Test
|
||||
@DisplayName("byFields succeeds when no matching documents exist")
|
||||
fun byFieldsNoMatch() =
|
||||
SQLiteDB().use(RemoveFieldsFunctions::byFieldsNoMatch)
|
||||
|
||||
@Test
|
||||
@DisplayName("byContains fails")
|
||||
fun byContainsFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(RemoveFieldsFunctions::byContainsMatchFields) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("byJsonPath fails")
|
||||
fun byJsonPathFails() {
|
||||
assertThrows<DocumentException> { SQLiteDB().use(RemoveFieldsFunctions::byJsonPathMatchFields) }
|
||||
}
|
||||
}
|
||||
24
src/kotlinx/src/test/kotlin/integration/ThrowawayDatabase.kt
Normal file
24
src/kotlinx/src/test/kotlin/integration/ThrowawayDatabase.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package solutions.bitbadger.documents.kotlinx.tests.integration
|
||||
|
||||
import solutions.bitbadger.documents.AutoId
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
* Common interface for PostgreSQL and SQLite throwaway databases
|
||||
*/
|
||||
abstract class ThrowawayDatabase : AutoCloseable {
|
||||
|
||||
/** The name of the throwaway database */
|
||||
protected val dbName = "throwaway_${AutoId.generateRandomString(8)}"
|
||||
|
||||
/** The database connection for the throwaway database */
|
||||
abstract val conn: Connection
|
||||
|
||||
/**
|
||||
* Determine if a database object exists
|
||||
*
|
||||
* @param name The name of the object whose existence should be checked
|
||||
* @return True if the object exists, false if not
|
||||
*/
|
||||
abstract fun dbObjectExists(name: String): Boolean
|
||||
}
|
||||
Reference in New Issue
Block a user