Initial Development #1
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>solutions.bitbadger.documents</groupId>
|
||||
<artifactId>java</artifactId>
|
||||
<artifactId>jvm</artifactId>
|
||||
<version>4.0.0-alpha1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</parent>
|
||||
|
||||
<name>${project.groupId}:${project.artifactId}</name>
|
||||
<description>Expose a document store interface for PostgreSQL and SQLite (Java Library)</description>
|
||||
<description>Expose a document store interface for PostgreSQL and SQLite (Standard JVM Library)</description>
|
||||
<url>https://bitbadger.solutions/open-source/relational-documents/jvm/</url>
|
||||
|
||||
<scm>
|
||||
|
@ -28,16 +28,10 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>solutions.bitbadger.documents</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<artifactId>jvm</artifactId>
|
||||
<version>4.0.0-alpha1-SNAPSHOT</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/../common/target/common-4.0.0-alpha1-SNAPSHOT.jar</systemPath>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>solutions.bitbadger.documents</groupId>
|
||||
<artifactId>java</artifactId>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/../java/target/java-4.0.0-alpha1-SNAPSHOT.jar</systemPath>
|
||||
<systemPath>${project.basedir}/../jvm/target/jvm-4.0.0-alpha1-SNAPSHOT.jar</systemPath>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@ -57,11 +51,6 @@
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirs>
|
||||
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
|
||||
</sourceDirs>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
@ -69,12 +58,6 @@
|
||||
<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>
|
||||
|
@ -1,10 +1,7 @@
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.ParameterType
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlin.extensions.*
|
||||
import solutions.bitbadger.documents.query.Count
|
||||
|
||||
import java.sql.Connection
|
||||
@ -21,7 +18,6 @@ object Count {
|
||||
* @param conn The connection over which documents should be counted
|
||||
* @return A count of the documents in the table
|
||||
*/
|
||||
@JvmStatic
|
||||
fun all(tableName: String, conn: Connection) =
|
||||
conn.customScalar(Count.all(tableName), mapFunc = Results::toCount)
|
||||
|
||||
@ -31,7 +27,6 @@ object Count {
|
||||
* @param tableName The name of the table in which documents should be counted
|
||||
* @return A count of the documents in the table
|
||||
*/
|
||||
@JvmStatic
|
||||
fun all(tableName: String) =
|
||||
Configuration.dbConn().use { all(tableName, it) }
|
||||
|
||||
@ -44,8 +39,6 @@ object Count {
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
* @return A count of the matching documents in the table
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
@ -68,8 +61,6 @@ object Count {
|
||||
* @param howMatched How the fields should be matched
|
||||
* @return A count of the matching documents in the table
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
|
||||
|
||||
@ -82,7 +73,6 @@ object Count {
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
@JvmStatic
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
conn.customScalar(Count.byContains(tableName), listOf(Parameters.json(":criteria", criteria)), Results::toCount)
|
||||
|
||||
@ -94,7 +84,6 @@ object Count {
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
@JvmStatic
|
||||
inline fun <reified TContains> byContains(tableName: String, criteria: TContains) =
|
||||
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||
|
||||
@ -107,7 +96,6 @@ object Count {
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
@JvmStatic
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
conn.customScalar(
|
||||
Count.byJsonPath(tableName),
|
||||
@ -123,7 +111,6 @@ object Count {
|
||||
* @return A count of the matching documents in the table
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
@JvmStatic
|
||||
fun byJsonPath(tableName: String, path: String) =
|
||||
Configuration.dbConn().use { byJsonPath(tableName, path, it) }
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import solutions.bitbadger.documents.jvm.Parameters
|
||||
import solutions.bitbadger.documents.jvm.Custom as JvmCustom
|
||||
import java.sql.Connection
|
||||
import java.sql.ResultSet
|
||||
|
@ -1,4 +1,8 @@
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.DocumentException
|
||||
import solutions.bitbadger.documents.DocumentIndex
|
||||
import solutions.bitbadger.documents.jvm.Definition as JvmDefinition
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
@ -13,10 +17,7 @@ object Definition {
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
fun ensureTable(tableName: String, conn: Connection) =
|
||||
Configuration.dialect("ensure $tableName exists").let {
|
||||
conn.customNonQuery(Definition.ensureTable(tableName, it))
|
||||
conn.customNonQuery(Definition.ensureKey(tableName, it))
|
||||
}
|
||||
JvmDefinition.ensureTable(tableName, conn)
|
||||
|
||||
/**
|
||||
* Create a document table if necessary
|
||||
@ -24,7 +25,7 @@ object Definition {
|
||||
* @param tableName The table whose existence should be ensured (may include schema)
|
||||
*/
|
||||
fun ensureTable(tableName: String) =
|
||||
Configuration.dbConn().use { ensureTable(tableName, it) }
|
||||
JvmDefinition.ensureTable(tableName)
|
||||
|
||||
/**
|
||||
* Create an index on field(s) within documents in the specified table if necessary
|
||||
@ -35,7 +36,7 @@ object Definition {
|
||||
* @param conn The connection on which the query should be executed
|
||||
*/
|
||||
fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>, conn: Connection) =
|
||||
conn.customNonQuery(Definition.ensureIndexOn(tableName, indexName, fields))
|
||||
JvmDefinition.ensureFieldIndex(tableName, indexName, fields, conn)
|
||||
|
||||
/**
|
||||
* Create an index on field(s) within documents in the specified table if necessary
|
||||
@ -45,7 +46,7 @@ object Definition {
|
||||
* @param fields One or more fields to be indexed<
|
||||
*/
|
||||
fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection<String>) =
|
||||
Configuration.dbConn().use { ensureFieldIndex(tableName, indexName, fields, it) }
|
||||
JvmDefinition.ensureFieldIndex(tableName, indexName, fields)
|
||||
|
||||
/**
|
||||
* Create a document index on a table (PostgreSQL only)
|
||||
@ -56,7 +57,7 @@ object Definition {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex, conn: Connection) =
|
||||
conn.customNonQuery(Definition.ensureDocumentIndexOn(tableName, indexType))
|
||||
JvmDefinition.ensureDocumentIndex(tableName, indexType, conn)
|
||||
|
||||
/**
|
||||
* Create a document index on a table (PostgreSQL only)
|
||||
@ -66,5 +67,5 @@ object Definition {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun ensureDocumentIndex(tableName: String, indexType: DocumentIndex) =
|
||||
Configuration.dbConn().use { ensureDocumentIndex(tableName, indexType, it) }
|
||||
JvmDefinition.ensureDocumentIndex(tableName, indexType)
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.ParameterType
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.jvm.Delete as JvmDelete
|
||||
import solutions.bitbadger.documents.kotlin.extensions.*
|
||||
import solutions.bitbadger.documents.query.Delete
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
@ -17,10 +19,7 @@ object Delete {
|
||||
* @param conn The connection on which the deletion should be executed
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
conn.customNonQuery(
|
||||
Delete.byId(tableName, docId),
|
||||
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id")))
|
||||
)
|
||||
JvmDelete.byId(tableName, docId, conn)
|
||||
|
||||
/**
|
||||
* Delete a document by its ID
|
||||
@ -29,7 +28,7 @@ object Delete {
|
||||
* @param docId The ID of the document to be deleted
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey) =
|
||||
Configuration.dbConn().use { byId(tableName, docId, it) }
|
||||
JvmDelete.byId(tableName, docId)
|
||||
|
||||
/**
|
||||
* Delete documents using a field comparison
|
||||
@ -39,10 +38,8 @@ object Delete {
|
||||
* @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) {
|
||||
val named = Parameters.nameFields(fields)
|
||||
conn.customNonQuery(Delete.byFields(tableName, named, howMatched), Parameters.addFields(named))
|
||||
}
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null, conn: Connection) =
|
||||
JvmDelete.byFields(tableName, fields, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Delete documents using a field comparison
|
||||
@ -52,7 +49,7 @@ object Delete {
|
||||
* @param howMatched How the fields should be matched
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
|
||||
JvmDelete.byFields(tableName, fields, howMatched)
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
||||
@ -84,7 +81,7 @@ object Delete {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
conn.customNonQuery(Delete.byJsonPath(tableName), listOf(Parameter(":path", ParameterType.STRING, path)))
|
||||
JvmDelete.byJsonPath(tableName, path, conn)
|
||||
|
||||
/**
|
||||
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||
@ -94,5 +91,5 @@ object Delete {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String) =
|
||||
Configuration.dbConn().use { byJsonPath(tableName, path, it) }
|
||||
JvmDelete.byJsonPath(tableName, path)
|
||||
}
|
||||
|
114
src/kotlin/src/main/kotlin/Document.kt
Normal file
114
src/kotlin/src/main/kotlin/Document.kt
Normal file
@ -0,0 +1,114 @@
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.AutoId
|
||||
import solutions.bitbadger.documents.Configuration
|
||||
import solutions.bitbadger.documents.Dialect
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.extensions.customNonQuery
|
||||
import solutions.bitbadger.documents.query.Document
|
||||
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) {
|
||||
Document.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"
|
||||
}
|
||||
|
||||
Document.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(Document.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(Document.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) }
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.ParameterType
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.jvm.Exists as JvmExists
|
||||
import solutions.bitbadger.documents.kotlin.extensions.*
|
||||
import solutions.bitbadger.documents.query.Exists
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
@ -18,11 +20,7 @@ object Exists {
|
||||
* @return True if the document exists, false if not
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
conn.customScalar(
|
||||
Exists.byId(tableName, docId),
|
||||
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))),
|
||||
Results::toExists
|
||||
)
|
||||
JvmExists.byId(tableName, docId, conn)
|
||||
|
||||
/**
|
||||
* Determine a document's existence by its ID
|
||||
@ -32,7 +30,7 @@ object Exists {
|
||||
* @return True if the document exists, false if not
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey) =
|
||||
Configuration.dbConn().use { byId(tableName, docId, it) }
|
||||
JvmExists.byId(tableName, docId)
|
||||
|
||||
/**
|
||||
* Determine document existence using a field comparison
|
||||
@ -43,19 +41,8 @@ object Exists {
|
||||
* @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
|
||||
): Boolean {
|
||||
val named = Parameters.nameFields(fields)
|
||||
return conn.customScalar(
|
||||
Exists.byFields(tableName, named, howMatched),
|
||||
Parameters.addFields(named),
|
||||
Results::toExists
|
||||
)
|
||||
}
|
||||
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
|
||||
@ -66,7 +53,7 @@ object Exists {
|
||||
* @return True if any matching documents exist, false if not
|
||||
*/
|
||||
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
|
||||
JvmExists.byFields(tableName, fields, howMatched)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||
@ -105,11 +92,7 @@ object Exists {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
conn.customScalar(
|
||||
Exists.byJsonPath(tableName),
|
||||
listOf(Parameter(":path", ParameterType.STRING, path)),
|
||||
Results::toExists
|
||||
)
|
||||
JvmExists.byJsonPath(tableName, path, conn)
|
||||
|
||||
/**
|
||||
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||
@ -120,5 +103,5 @@ object Exists {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String) =
|
||||
Configuration.dbConn().use { byJsonPath(tableName, path, it) }
|
||||
JvmExists.byJsonPath(tableName, path)
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.ParameterType
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlin.extensions.*
|
||||
import solutions.bitbadger.documents.query.Find
|
||||
import solutions.bitbadger.documents.query.orderBy
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
@ -17,7 +19,7 @@ object Find {
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents from the given table
|
||||
*/
|
||||
inline fun <reified TDoc> all(tableName: String, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
inline fun <reified TDoc : Any> all(tableName: String, orderBy: Collection<Field<*>>? = null, conn: Connection) =
|
||||
conn.customList<TDoc>(Find.all(tableName) + (orderBy?.let(::orderBy) ?: ""), mapFunc = Results::fromData)
|
||||
|
||||
/**
|
||||
@ -27,7 +29,7 @@ object Find {
|
||||
* @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> all(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
inline fun <reified TDoc : Any> all(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Configuration.dbConn().use { all<TDoc>(tableName, orderBy, it) }
|
||||
|
||||
/**
|
||||
@ -37,7 +39,7 @@ object Find {
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents from the given table
|
||||
*/
|
||||
inline fun <reified TDoc> all(tableName: String, conn: Connection) =
|
||||
inline fun <reified TDoc : Any> all(tableName: String, conn: Connection) =
|
||||
all<TDoc>(tableName, null, conn)
|
||||
|
||||
/**
|
||||
@ -48,7 +50,7 @@ object Find {
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return The document if it is found, `null` otherwise
|
||||
*/
|
||||
inline fun <TKey, reified TDoc> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
inline fun <TKey, reified TDoc : Any> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||
conn.customSingle<TDoc>(
|
||||
Find.byId(tableName, docId),
|
||||
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))),
|
||||
@ -62,7 +64,7 @@ object Find {
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @return The document if it is found, `null` otherwise
|
||||
*/
|
||||
inline fun <TKey, reified TDoc> byId(tableName: String, docId: TKey) =
|
||||
inline fun <TKey, reified TDoc : Any> byId(tableName: String, docId: TKey) =
|
||||
Configuration.dbConn().use { byId<TKey, TDoc>(tableName, docId, it) }
|
||||
|
||||
/**
|
||||
@ -75,7 +77,7 @@ object Find {
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc> byFields(
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -99,7 +101,7 @@ object Find {
|
||||
* @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> byFields(
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -116,7 +118,7 @@ object Find {
|
||||
* @param conn The connection over which documents should be retrieved
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc> byFields(
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -132,7 +134,7 @@ object Find {
|
||||
* @param howMatched How the fields should be matched
|
||||
* @return A list of documents matching the field comparison
|
||||
*/
|
||||
inline fun <reified TDoc> byFields(
|
||||
inline fun <reified TDoc : Any> byFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null
|
||||
@ -149,7 +151,7 @@ object Find {
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc, reified TContains> byContains(
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
@ -170,7 +172,7 @@ object Find {
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc, reified TContains> byContains(
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
@ -186,7 +188,11 @@ object Find {
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc, reified TContains> byContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
conn: Connection
|
||||
) =
|
||||
byContains<TDoc, TContains>(tableName, criteria, null, conn)
|
||||
|
||||
/**
|
||||
@ -197,7 +203,7 @@ object Find {
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc, reified TContains> byContains(tableName: String, criteria: TContains) =
|
||||
inline fun <reified TDoc : Any, reified TContains> byContains(tableName: String, criteria: TContains) =
|
||||
Configuration.dbConn().use { byContains<TDoc, TContains>(tableName, criteria, it) }
|
||||
|
||||
/**
|
||||
@ -210,7 +216,7 @@ object Find {
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc> byJsonPath(
|
||||
inline fun <reified TDoc : Any> byJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
@ -231,7 +237,7 @@ object Find {
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc> byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
inline fun <reified TDoc : Any> byJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Configuration.dbConn().use { byJsonPath<TDoc>(tableName, path, orderBy, it) }
|
||||
|
||||
/**
|
||||
@ -243,7 +249,7 @@ object Find {
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc> byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
inline fun <reified TDoc : Any> byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
byJsonPath<TDoc>(tableName, path, null, conn)
|
||||
|
||||
/**
|
||||
@ -256,7 +262,7 @@ object Find {
|
||||
* @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> firstByFields(
|
||||
inline fun <reified TDoc : Any> firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -280,7 +286,7 @@ object Find {
|
||||
* @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> firstByFields(
|
||||
inline fun <reified TDoc : Any> firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -297,7 +303,7 @@ object Find {
|
||||
* @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> firstByFields(
|
||||
inline fun <reified TDoc : Any> firstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -315,7 +321,7 @@ object Find {
|
||||
* @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, reified TContains> firstByContains(
|
||||
inline fun <reified TDoc : Any, reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
@ -336,7 +342,11 @@ object Find {
|
||||
* @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, reified TContains> firstByContains(tableName: String, criteria: TContains, conn: Connection) =
|
||||
inline fun <reified TDoc : Any, reified TContains> firstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
conn: Connection
|
||||
) =
|
||||
firstByContains<TDoc, TContains>(tableName, criteria, null, conn)
|
||||
|
||||
/**
|
||||
@ -348,7 +358,11 @@ object Find {
|
||||
* @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, reified TContains> firstByContains(tableName: String, criteria: TContains, orderBy: Collection<Field<*>>? = null) =
|
||||
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) }
|
||||
|
||||
/**
|
||||
@ -361,7 +375,7 @@ object Find {
|
||||
* @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> firstByJsonPath(
|
||||
inline fun <reified TDoc : Any> firstByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null,
|
||||
@ -382,7 +396,7 @@ object Find {
|
||||
* @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> firstByJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
inline fun <reified TDoc : Any> firstByJsonPath(tableName: String, path: String, conn: Connection) =
|
||||
firstByJsonPath<TDoc>(tableName, path, null, conn)
|
||||
|
||||
/**
|
||||
@ -394,6 +408,10 @@ object Find {
|
||||
* @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> firstByJsonPath(tableName: String, path: String, orderBy: Collection<Field<*>>? = null) =
|
||||
inline fun <reified TDoc : Any> firstByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
) =
|
||||
Configuration.dbConn().use { firstByJsonPath<TDoc>(tableName, path, orderBy, it) }
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.ParameterName
|
||||
import solutions.bitbadger.documents.common.*
|
||||
import solutions.bitbadger.documents.jvm.Parameters as JvmParameters
|
||||
import java.sql.Connection
|
||||
import java.sql.PreparedStatement
|
||||
import java.sql.SQLException
|
||||
import kotlin.jvm.Throws
|
||||
|
||||
/**
|
||||
* Functions to assist with the creation and implementation of parameters for SQL queries
|
||||
@ -19,17 +17,8 @@ object Parameters {
|
||||
* @param fields The collection of fields to be named
|
||||
* @return The collection of fields with parameter names assigned
|
||||
*/
|
||||
@JvmStatic
|
||||
fun nameFields(fields: Collection<Field<*>>): Collection<Field<*>> {
|
||||
val name = ParameterName()
|
||||
return fields.map {
|
||||
if (it.parameterName.isNullOrEmpty() && !listOf(Op.EXISTS, Op.NOT_EXISTS).contains(it.comparison.op)) {
|
||||
it.withParameterName(name.derive(null))
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
fun nameFields(fields: Collection<Field<*>>): Collection<Field<*>> =
|
||||
JvmParameters.nameFields(fields)
|
||||
|
||||
/**
|
||||
* Create a parameter by encoding a JSON object
|
||||
@ -38,9 +27,8 @@ object Parameters {
|
||||
* @param value The object to be encoded as JSON
|
||||
* @return A parameter with the value encoded
|
||||
*/
|
||||
@JvmStatic
|
||||
fun <T> json(name: String, value: T) =
|
||||
Parameter(name, ParameterType.JSON, Configuration.serializer.serialize(value))
|
||||
inline fun <reified T> json(name: String, value: T) =
|
||||
Parameter(name, ParameterType.JSON, DocumentConfig.serialize(value))
|
||||
|
||||
/**
|
||||
* Add field parameters to the given set of parameters
|
||||
@ -49,9 +37,8 @@ object Parameters {
|
||||
* @param existing Any existing parameters for the query (optional, defaults to empty collection)
|
||||
* @return A collection of parameters for the query
|
||||
*/
|
||||
@JvmStatic
|
||||
fun addFields(fields: Collection<Field<*>>, existing: MutableCollection<Parameter<*>> = mutableListOf()) =
|
||||
fields.fold(existing) { acc, field -> field.appendParameter(acc) }
|
||||
JvmParameters.addFields(fields, existing)
|
||||
|
||||
/**
|
||||
* Replace the parameter names in the query with question marks
|
||||
@ -60,9 +47,8 @@ object Parameters {
|
||||
* @param parameters The parameters for the query
|
||||
* @return The query, with name parameters changed to `?`s
|
||||
*/
|
||||
@JvmStatic
|
||||
fun replaceNamesInQuery(query: String, parameters: Collection<Parameter<*>>) =
|
||||
parameters.sortedByDescending { it.name.length }.fold(query) { acc, param -> acc.replace(param.name, "?") }
|
||||
JvmParameters.replaceNamesInQuery(query, parameters)
|
||||
|
||||
/**
|
||||
* Apply the given parameters to the given query, returning a prepared statement
|
||||
@ -73,38 +59,8 @@ object Parameters {
|
||||
* @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
|
||||
*/
|
||||
@Throws(DocumentException::class)
|
||||
@JvmStatic
|
||||
fun apply(conn: Connection, query: String, parameters: Collection<Parameter<*>>): PreparedStatement {
|
||||
|
||||
if (parameters.isEmpty()) return try {
|
||||
conn.prepareStatement(query)
|
||||
} catch (ex: SQLException) {
|
||||
throw DocumentException("Error preparing no-parameter query: ${ex.message}", ex)
|
||||
}
|
||||
|
||||
val replacements = mutableListOf<Pair<Int, Parameter<*>>>()
|
||||
parameters.sortedByDescending { it.name.length }.forEach {
|
||||
var startPos = query.indexOf(it.name)
|
||||
while (startPos > -1) {
|
||||
replacements.add(Pair(startPos, it))
|
||||
startPos = query.indexOf(it.name, startPos + it.name.length + 1)
|
||||
}
|
||||
}
|
||||
|
||||
return try {
|
||||
replaceNamesInQuery(query, parameters)
|
||||
//.also(::println)
|
||||
.let { conn.prepareStatement(it) }
|
||||
.also { stmt ->
|
||||
replacements.sortedBy { it.first }
|
||||
.map { it.second }
|
||||
.forEachIndexed { index, param -> param.bind(stmt, index + 1) }
|
||||
}
|
||||
} catch (ex: SQLException) {
|
||||
throw DocumentException("Error creating query / binding parameters: ${ex.message}", ex)
|
||||
}
|
||||
}
|
||||
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
|
||||
@ -114,17 +70,6 @@ object Parameters {
|
||||
* @return A list of parameters to use for building the query
|
||||
* @throws DocumentException If the dialect has not been set
|
||||
*/
|
||||
@Throws(DocumentException::class)
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun fieldNames(names: Collection<String>, parameterName: String = ":name"): MutableCollection<Parameter<*>> =
|
||||
when (Configuration.dialect("generate field name parameters")) {
|
||||
Dialect.POSTGRESQL -> mutableListOf(
|
||||
Parameter(parameterName, ParameterType.STRING, names.joinToString(",").let { "{$it}" })
|
||||
)
|
||||
|
||||
Dialect.SQLITE -> names.mapIndexed { index, name ->
|
||||
Parameter("$parameterName$index", ParameterType.STRING, name)
|
||||
}.toMutableList()
|
||||
}
|
||||
fun fieldNames(names: Collection<String>, parameterName: String = ":name") =
|
||||
JvmParameters.fieldNames(names, parameterName)
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.ParameterType
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlin.extensions.*
|
||||
import solutions.bitbadger.documents.query.Patch
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,9 @@
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.common.*
|
||||
import solutions.bitbadger.documents.jvm.RemoveFields as JvmRemoveFields
|
||||
import solutions.bitbadger.documents.kotlin.extensions.*
|
||||
import solutions.bitbadger.documents.query.RemoveFields
|
||||
import java.sql.Connection
|
||||
|
||||
/**
|
||||
@ -7,20 +11,6 @@ import java.sql.Connection
|
||||
*/
|
||||
object RemoveFields {
|
||||
|
||||
/**
|
||||
* Translate field paths to JSON paths for SQLite queries
|
||||
*
|
||||
* @param parameters The parameters for the specified fields
|
||||
* @return The parameters for the specified fields, translated if used for SQLite
|
||||
*/
|
||||
private fun translatePath(parameters: MutableCollection<Parameter<*>>): MutableCollection<Parameter<*>> {
|
||||
val dialect = Configuration.dialect("remove fields")
|
||||
return when (dialect) {
|
||||
Dialect.POSTGRESQL -> parameters
|
||||
Dialect.SQLITE -> parameters.map { Parameter(it.name, it.type, "$.${it.value}") }.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove fields from a document by its ID
|
||||
*
|
||||
@ -29,16 +19,8 @@ object RemoveFields {
|
||||
* @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) {
|
||||
val nameParams = Parameters.fieldNames(toRemove)
|
||||
conn.customNonQuery(
|
||||
RemoveFields.byId(tableName, nameParams, docId),
|
||||
Parameters.addFields(
|
||||
listOf(Field.equal(Configuration.idField, docId, ":id")),
|
||||
translatePath(nameParams)
|
||||
)
|
||||
)
|
||||
}
|
||||
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
|
||||
@ -48,7 +30,7 @@ object RemoveFields {
|
||||
* @param toRemove The names of the fields to be removed
|
||||
*/
|
||||
fun <TKey> byId(tableName: String, docId: TKey, toRemove: Collection<String>) =
|
||||
Configuration.dbConn().use { byId(tableName, docId, toRemove, it) }
|
||||
JvmRemoveFields.byId(tableName, docId, toRemove)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a field comparison
|
||||
@ -65,14 +47,8 @@ object RemoveFields {
|
||||
toRemove: Collection<String>,
|
||||
howMatched: FieldMatch? = null,
|
||||
conn: Connection
|
||||
) {
|
||||
val named = Parameters.nameFields(fields)
|
||||
val nameParams = Parameters.fieldNames(toRemove)
|
||||
conn.customNonQuery(
|
||||
RemoveFields.byFields(tableName, nameParams, named, howMatched),
|
||||
Parameters.addFields(named, translatePath(nameParams))
|
||||
)
|
||||
}
|
||||
) =
|
||||
JvmRemoveFields.byFields(tableName, fields, toRemove, howMatched, conn)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a field comparison
|
||||
@ -88,7 +64,7 @@ object RemoveFields {
|
||||
toRemove: Collection<String>,
|
||||
howMatched: FieldMatch? = null
|
||||
) =
|
||||
Configuration.dbConn().use { byFields(tableName, fields, toRemove, howMatched, it) }
|
||||
JvmRemoveFields.byFields(tableName, fields, toRemove, howMatched)
|
||||
|
||||
/**
|
||||
* Remove fields from documents using a JSON containment query (PostgreSQL only)
|
||||
@ -132,13 +108,8 @@ object RemoveFields {
|
||||
* @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) {
|
||||
val nameParams = Parameters.fieldNames(toRemove)
|
||||
conn.customNonQuery(
|
||||
RemoveFields.byJsonPath(tableName, nameParams),
|
||||
listOf(Parameter(":path", ParameterType.STRING, path), *nameParams.toTypedArray())
|
||||
)
|
||||
}
|
||||
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)
|
||||
@ -149,5 +120,5 @@ object RemoveFields {
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
fun byJsonPath(tableName: String, path: String, toRemove: Collection<String>) =
|
||||
Configuration.dbConn().use { byJsonPath(tableName, path, toRemove, it) }
|
||||
JvmRemoveFields.byJsonPath(tableName, path, toRemove)
|
||||
}
|
||||
|
@ -16,21 +16,18 @@ object Results {
|
||||
* Create a domain item from a document, specifying the field in which the document is found
|
||||
*
|
||||
* @param field The field name containing the JSON document
|
||||
* @param rs A `ResultSet` set to the row with the document to be constructed
|
||||
* @return The constructed domain item
|
||||
* @return A function to create the constructed domain item
|
||||
*/
|
||||
inline fun <reified TDoc> fromDocument(field: String): (ResultSet, Class<TDoc>) -> TDoc =
|
||||
{ rs, _ -> Results.fromDocument(field, rs, TDoc::class.java) }
|
||||
inline fun <reified TDoc> fromDocument(field: String): (ResultSet) -> TDoc =
|
||||
{ rs -> DocumentConfig.deserialize(rs.getString(field)) }
|
||||
|
||||
/**
|
||||
* Create a domain item from a document
|
||||
*
|
||||
* @param rs A `ResultSet` set to the row with the document to be constructed<
|
||||
* @param clazz The class of the document to be returned
|
||||
* @return The constructed domain item
|
||||
*/
|
||||
inline fun <reified TDoc> fromData(rs: ResultSet, clazz: Class<TDoc> = TDoc::class.java) =
|
||||
Results.fromDocument("data", rs, TDoc::class.java)
|
||||
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
|
||||
@ -59,7 +56,7 @@ object Results {
|
||||
* @param rs A `ResultSet` set to the row with the count to retrieve
|
||||
* @return The count from the row
|
||||
*/
|
||||
fun toCount(rs: ResultSet, clazz: Class<Long> = Long::class.java) =
|
||||
fun toCount(rs: ResultSet) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.POSTGRESQL -> rs.getInt("it").toLong()
|
||||
Dialect.SQLITE -> rs.getLong("it")
|
||||
@ -71,7 +68,7 @@ object Results {
|
||||
* @param rs A `ResultSet` set to the row with the true/false value to retrieve
|
||||
* @return The true/false value from the row
|
||||
*/
|
||||
fun toExists(rs: ResultSet, clazz: Class<Boolean> = Boolean::class.java) =
|
||||
fun toExists(rs: ResultSet) =
|
||||
when (Configuration.dialect()) {
|
||||
Dialect.POSTGRESQL -> rs.getBoolean("it")
|
||||
Dialect.SQLITE -> toCount(rs) > 0L
|
||||
|
@ -1,10 +1,7 @@
|
||||
package solutions.bitbadger.documents.kotlin
|
||||
package solutions.bitbadger.documents.kotlin.extensions
|
||||
|
||||
import solutions.bitbadger.documents.DocumentIndex
|
||||
import solutions.bitbadger.documents.Field
|
||||
import solutions.bitbadger.documents.FieldMatch
|
||||
import solutions.bitbadger.documents.Parameter
|
||||
import solutions.bitbadger.documents.java.jvm.Document
|
||||
import solutions.bitbadger.documents.*
|
||||
import solutions.bitbadger.documents.kotlin.*
|
||||
import java.sql.Connection
|
||||
import java.sql.ResultSet
|
||||
|
||||
@ -18,8 +15,8 @@ import java.sql.ResultSet
|
||||
* @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> Connection.customList(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), noinline mapFunc: (ResultSet, Class<TDoc>) -> TDoc
|
||||
inline fun <reified TDoc : Any> Connection.customList(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> TDoc
|
||||
) = Custom.list(query, parameters, this, mapFunc)
|
||||
|
||||
/**
|
||||
@ -30,8 +27,8 @@ inline fun <reified TDoc> Connection.customList(
|
||||
* @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> Connection.customSingle(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), noinline mapFunc: (ResultSet, Class<TDoc>) -> TDoc
|
||||
inline fun <reified TDoc : Any> Connection.customSingle(
|
||||
query: String, parameters: Collection<Parameter<*>> = listOf(), mapFunc: (ResultSet) -> TDoc
|
||||
) = Custom.single(query, parameters, this, mapFunc)
|
||||
|
||||
/**
|
||||
@ -54,7 +51,7 @@ fun Connection.customNonQuery(query: String, parameters: Collection<Parameter<*>
|
||||
inline fun <reified T : Any> Connection.customScalar(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
noinline mapFunc: (ResultSet, Class<T>) -> T
|
||||
mapFunc: (ResultSet) -> T
|
||||
) = Custom.scalar(query, parameters, this, mapFunc)
|
||||
|
||||
// ~~~ DEFINITION QUERIES ~~~
|
||||
@ -215,7 +212,7 @@ fun Connection.existsByJsonPath(tableName: String, path: String) =
|
||||
* @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> Connection.findAll(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
inline fun <reified TDoc : Any> Connection.findAll(tableName: String, orderBy: Collection<Field<*>>? = null) =
|
||||
Find.all<TDoc>(tableName, orderBy, this)
|
||||
|
||||
/**
|
||||
@ -225,7 +222,7 @@ inline fun <reified TDoc> Connection.findAll(tableName: String, orderBy: Collect
|
||||
* @param docId The ID of the document to retrieve
|
||||
* @return The document if it is found, `null` otherwise
|
||||
*/
|
||||
inline fun <TKey, reified TDoc> Connection.findById(tableName: String, docId: TKey) =
|
||||
inline fun <TKey, reified TDoc : Any> Connection.findById(tableName: String, docId: TKey) =
|
||||
Find.byId<TKey, TDoc>(tableName, docId, this)
|
||||
|
||||
/**
|
||||
@ -237,7 +234,7 @@ inline fun <TKey, reified TDoc> Connection.findById(tableName: String, docId: TK
|
||||
* @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> Connection.findByFields(
|
||||
inline fun <reified TDoc : Any> Connection.findByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -254,7 +251,7 @@ inline fun <reified TDoc> Connection.findByFields(
|
||||
* @return A list of documents matching the JSON containment query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc, reified TContains> Connection.findByContains(
|
||||
inline fun <reified TDoc : Any, reified TContains> Connection.findByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
@ -270,7 +267,7 @@ inline fun <reified TDoc, reified TContains> Connection.findByContains(
|
||||
* @return A list of documents matching the JSON Path match query
|
||||
* @throws DocumentException If called on a SQLite connection
|
||||
*/
|
||||
inline fun <reified TDoc> Connection.findByJsonPath(
|
||||
inline fun <reified TDoc : Any> Connection.findByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
@ -286,7 +283,7 @@ inline fun <reified TDoc> Connection.findByJsonPath(
|
||||
* @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> Connection.findFirstByFields(
|
||||
inline fun <reified TDoc : Any> Connection.findFirstByFields(
|
||||
tableName: String,
|
||||
fields: Collection<Field<*>>,
|
||||
howMatched: FieldMatch? = null,
|
||||
@ -303,7 +300,7 @@ inline fun <reified TDoc> Connection.findFirstByFields(
|
||||
* @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, reified TContains> Connection.findFirstByContains(
|
||||
inline fun <reified TDoc : Any, reified TContains> Connection.findFirstByContains(
|
||||
tableName: String,
|
||||
criteria: TContains,
|
||||
orderBy: Collection<Field<*>>? = null
|
||||
@ -319,7 +316,7 @@ inline fun <reified TDoc, reified TContains> Connection.findFirstByContains(
|
||||
* @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> Connection.findFirstByJsonPath(
|
||||
inline fun <reified TDoc : Any> Connection.findFirstByJsonPath(
|
||||
tableName: String,
|
||||
path: String,
|
||||
orderBy: Collection<Field<*>>? = null
|
@ -46,6 +46,7 @@
|
||||
|
||||
<modules>
|
||||
<module>jvm</module>
|
||||
<module>kotlin</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
Loading…
x
Reference in New Issue
Block a user