diff options
Diffstat (limited to 'database')
7 files changed, 87 insertions, 13 deletions
diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/Column.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/Column.kt index d1294f7..33727de 100644 --- a/database/core/src/main/kotlin/moe/nea/ledger/database/Column.kt +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/Column.kt @@ -1,10 +1,31 @@ package moe.nea.ledger.database +import moe.nea.ledger.database.sql.IntoSelectable +import moe.nea.ledger.database.sql.Selectable +import java.sql.PreparedStatement + class Column<T> @Deprecated("Use Table.column instead") constructor( val table: Table, val name: String, val type: DBType<T> -) { +) : IntoSelectable<T> { + override fun asSelectable() = object : Selectable<T> { + override fun asSql(): String { + return qualifiedSqlName + } + + override val dbType: DBType<T> + get() = this@Column.type + + override fun guessColumn(): Column<T>? { + return this@Column + } + + override fun appendToStatement(stmt: PreparedStatement, startIndex: Int): Int { + return startIndex + } + } + val sqlName get() = "`$name`" val qualifiedSqlName get() = table.sqlName + "." + sqlName }
\ No newline at end of file diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/Query.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/Query.kt index 7829fbb..e58eef4 100644 --- a/database/core/src/main/kotlin/moe/nea/ledger/database/Query.kt +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/Query.kt @@ -3,19 +3,22 @@ package moe.nea.ledger.database import moe.nea.ledger.database.sql.ANDExpression import moe.nea.ledger.database.sql.BooleanExpression import moe.nea.ledger.database.sql.Clause +import moe.nea.ledger.database.sql.IntoSelectable import moe.nea.ledger.database.sql.Join import moe.nea.ledger.database.sql.SQLQueryComponent import moe.nea.ledger.database.sql.SQLQueryGenerator.concatToFilledPreparedStatement +import moe.nea.ledger.database.sql.Selectable import java.sql.Connection class Query( val connection: Connection, - val selectedColumns: MutableList<Column<*>>, + val selectedColumns: MutableList<Selectable<*>>, var table: Table, var limit: UInt? = null, var skip: UInt? = null, val joins: MutableList<Join> = mutableListOf(), val conditions: MutableList<BooleanExpression> = mutableListOf(), + var distinct: Boolean = false, // var order: OrderClause?= null, ) : Iterable<ResultRow> { fun join(table: Table, on: Clause): Query { @@ -28,8 +31,10 @@ class Query( return this } - fun select(vararg columns: Column<*>): Query { - selectedColumns.addAll(columns) + fun select(vararg columns: IntoSelectable<*>): Query { + for (column in columns) { + this.selectedColumns.add(column.asSelectable()) + } return this } @@ -39,16 +44,29 @@ class Query( return this } + fun distinct(): Query { + this.distinct = true + return this + } + fun limit(limit: UInt): Query { this.limit = limit return this } override fun iterator(): Iterator<ResultRow> { - val columnSelections = selectedColumns.joinToString { it.qualifiedSqlName } val elements = mutableListOf( - SQLQueryComponent.standalone("SELECT $columnSelections FROM ${table.sqlName}"), + SQLQueryComponent.standalone("SELECT"), ) + if (distinct) + elements.add(SQLQueryComponent.standalone("DISTINCT")) + selectedColumns.forEachIndexed { idx, it -> + elements.add(it) + if (idx != selectedColumns.lastIndex) { + elements.add(SQLQueryComponent.standalone(",")) + } + } + elements.add(SQLQueryComponent.standalone("FROM ${table.sqlName}")) elements.addAll(joins) if (conditions.any()) { elements.add(SQLQueryComponent.standalone("WHERE")) @@ -84,7 +102,7 @@ class Query( } hasAdvanced = false return ResultRow(selectedColumns.withIndex().associate { - it.value to it.value.type.get(results, it.index + 1) + it.value to it.value.dbType.get(results, it.index + 1) }) } diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/ResultRow.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/ResultRow.kt index d92f913..6715f27 100644 --- a/database/core/src/main/kotlin/moe/nea/ledger/database/ResultRow.kt +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/ResultRow.kt @@ -1,9 +1,22 @@ package moe.nea.ledger.database -class ResultRow(val columnValues: Map<Column<*>, *>) { +import moe.nea.ledger.database.sql.Selectable + +class ResultRow(val selectableValues: Map<Selectable<*>, *>) { + val columnValues = selectableValues.mapNotNull { + val col = it.key.guessColumn() ?: return@mapNotNull null + col to it.value + }.toMap() + operator fun <T> get(column: Column<T>): T { val value = columnValues[column] ?: error("Invalid column ${column.name}. Only ${columnValues.keys.joinToString { it.name }} are available.") return value as T } + + operator fun <T> get(column: Selectable<T>): T { + val value = selectableValues[column] + ?: error("Invalid selectable ${column}. Only ${selectableValues.keys} are available.") + return value as T + } }
\ No newline at end of file diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/Table.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/Table.kt index c136f48..61dc8f0 100644 --- a/database/core/src/main/kotlin/moe/nea/ledger/database/Table.kt +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/Table.kt @@ -98,6 +98,6 @@ abstract class Table(val name: String) { } fun selectAll(connection: Connection): Query { - return Query(connection, columns.toMutableList(), this) + return Query(connection, columns.mapTo(mutableListOf()) { it.asSelectable() }, this) } }
\ No newline at end of file diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/sql/IntoSelectable.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/sql/IntoSelectable.kt new file mode 100644 index 0000000..0068f6b --- /dev/null +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/sql/IntoSelectable.kt @@ -0,0 +1,5 @@ +package moe.nea.ledger.database.sql + +interface IntoSelectable<T> { + fun asSelectable(): Selectable<T> +}
\ No newline at end of file diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/sql/SQLQueryGenerator.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/sql/SQLQueryGenerator.kt index be81ff2..2eb54fd 100644 --- a/database/core/src/main/kotlin/moe/nea/ledger/database/sql/SQLQueryGenerator.kt +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/sql/SQLQueryGenerator.kt @@ -6,14 +6,14 @@ import java.sql.PreparedStatement object SQLQueryGenerator { fun List<SQLQueryComponent>.concatToFilledPreparedStatement(connection: Connection): PreparedStatement { - var query = "" + val query = StringBuilder() for (element in this) { if (query.isNotEmpty()) { - query += " " + query.append(" ") } - query += element.asSql() + query.append(element.asSql()) } - val statement = connection.prepareAndLog(query) + val statement = connection.prepareAndLog(query.toString()) var index = 1 for (element in this) { val nextIndex = element.appendToStatement(statement, index) diff --git a/database/core/src/main/kotlin/moe/nea/ledger/database/sql/Selectable.kt b/database/core/src/main/kotlin/moe/nea/ledger/database/sql/Selectable.kt new file mode 100644 index 0000000..a95b66b --- /dev/null +++ b/database/core/src/main/kotlin/moe/nea/ledger/database/sql/Selectable.kt @@ -0,0 +1,17 @@ +package moe.nea.ledger.database.sql + +import moe.nea.ledger.database.Column +import moe.nea.ledger.database.DBType + +/** + * Something that can be selected. Like a column, or an expression thereof + */ +interface Selectable<T> : SQLQueryComponent, IntoSelectable<T> { + override fun asSelectable(): Selectable<T> { + return this + } + + val dbType: DBType<T> + fun guessColumn(): Column<T>? +} + |