73 lines
3.0 KiB
Kotlin

package solutions.bitbadger.documents.query
import solutions.bitbadger.documents.Configuration
import solutions.bitbadger.documents.Dialect
import solutions.bitbadger.documents.Field
import solutions.bitbadger.documents.FieldFormat
/**
* Functions to create queries to define tables and indexes
*/
object Definition {
/**
* SQL statement to create a document table
*
* @param tableName The name of the table to create (may include schema)
* @param dataType The type of data for the column (`JSON`, `JSONB`, etc.)
* @return A query to create a document table
*/
fun ensureTableFor(tableName: String, dataType: String) =
"CREATE TABLE IF NOT EXISTS $tableName (data $dataType NOT NULL)"
/**
* SQL statement to create a document table in the current dialect
*
* @param tableName The name of the table to create (may include schema)
* @return A query to create a document table
*/
fun ensureTable(tableName: String) =
when (Configuration.dialect("create table creation query")) {
Dialect.POSTGRESQL -> ensureTableFor(tableName, "JSONB")
Dialect.SQLITE -> ensureTableFor(tableName, "TEXT")
}
/**
* Split a schema and table name
*
* @param tableName The name of the table, possibly with a schema
* @return A pair with the first item as the schema and the second as the table name
*/
private fun splitSchemaAndTable(tableName: String) =
tableName.split('.').let { if (it.size == 1) Pair("", tableName) else Pair(it[0], it[1]) }
/**
* SQL statement to create an index on one or more fields in a JSON document
*
* @param tableName The table on which an index should be created (may include schema)
* @param indexName The name of the index to be created
* @param fields One or more fields to include in the index
* @param dialect The SQL dialect to use when creating this index
* @return A query to create the field index
*/
fun ensureIndexOn(tableName: String, indexName: String, fields: Collection<String>, dialect: Dialect): String {
val (_, tbl) = splitSchemaAndTable(tableName)
val jsonFields = fields.joinToString(", ") {
val parts = it.split(' ')
val direction = if (parts.size > 1) " ${parts[1]}" else ""
"(" + Field.nameToPath(parts[0], dialect, FieldFormat.SQL) + ")$direction"
}
return "CREATE INDEX IF NOT EXISTS idx_${tbl}_$indexName ON $tableName ($jsonFields)"
}
/**
* SQL statement to create a key index for a document table
*
* @param tableName The table on which a key index should be created (may include schema)
* @param dialect The SQL dialect to use when creating this index
* @return A query to create the key index
*/
fun ensureKey(tableName: String, dialect: Dialect) =
ensureIndexOn(tableName, "key", listOf(Configuration.idField), dialect).replace("INDEX", "UNIQUE INDEX")
}