From 97ad8e49ac14b6d441c200ef06169daebf663424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Fri, 26 Mar 2021 14:17:50 +0100 Subject: [PATCH] [Editor] Add support deleting data with Query Result view --- .../database/controller/DatabaseController.kt | 19 +++++----- .../editor/database/model/data/DataRecord.kt | 36 +++++++++++++++---- .../base/editor/database/model/data/Query.kt | 11 +++--- .../database/service/DatabaseService.kt | 3 +- .../database/service/H2DatabaseService.kt | 8 +++-- .../database/view/list/TablesListView.kt | 2 +- .../database/view/query/QueryResultView.kt | 12 +++---- .../base/editor/database/viewmodel/QueryVM.kt | 4 +-- 8 files changed, 61 insertions(+), 34 deletions(-) diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/controller/DatabaseController.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/controller/DatabaseController.kt index 73030d28..47ac4c14 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/controller/DatabaseController.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/controller/DatabaseController.kt @@ -2,19 +2,21 @@ package com.bartlomiejpluta.base.editor.database.controller import com.bartlomiejpluta.base.editor.database.model.data.DataRecord import com.bartlomiejpluta.base.editor.database.model.data.Query +import com.bartlomiejpluta.base.editor.database.model.schema.SchemaTable import com.bartlomiejpluta.base.editor.database.service.DatabaseService import org.springframework.stereotype.Component import tornadofx.Controller import tornadofx.error import java.sql.Connection +import java.sql.PreparedStatement import java.sql.SQLException @Component class DatabaseController : Controller() { private val databaseService: DatabaseService by di() - fun execute(statement: String, name: String, table: String? = null): Query? = try { - databaseService.execute(statement, name, table) + fun execute(statement: String, name: String, schema: SchemaTable? = null): Query? = try { + databaseService.execute(statement, name, schema) } catch (e: SQLException) { sqlErrorAlert(e) null @@ -30,15 +32,12 @@ class DatabaseController : Controller() { } } ?: false - fun submitBatch(table: String, records: List) = execute { + fun submitBatch(records: List) = execute { autoCommit = false - records.forEach { - it.prepareStatement(table)?.let { sql -> - val statement = prepareStatement(sql) - it.fields.values.forEachIndexed { index, field -> statement.setObject(index + 1, field.value) } - statement.execute() - } - } + + records + .mapNotNull { it.prepareStatement(this) } + .forEach(PreparedStatement::execute) commit() } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/DataRecord.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/DataRecord.kt index fd2a1aba..f115b585 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/DataRecord.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/DataRecord.kt @@ -1,12 +1,18 @@ package com.bartlomiejpluta.base.editor.database.model.data +import com.bartlomiejpluta.base.editor.database.model.schema.SchemaTable import tornadofx.getValue import tornadofx.setValue import tornadofx.toProperty +import java.sql.Connection import kotlin.collections.component1 import kotlin.collections.component2 -class DataRecord(val fields: Map, operation: Operation = Operation.DO_NOTHING) { +class DataRecord( + val fields: Map, + operation: Operation = Operation.DO_NOTHING, + private val schema: SchemaTable? +) { val operationProperty = operation.toProperty() var operation by operationProperty @@ -14,10 +20,28 @@ class DataRecord(val fields: Map, operation: Operation = Oper fields.forEach { (_, field) -> field.record = this } } - fun prepareStatement(table: String) = when (operation) { - Operation.INSERT -> "INSERT INTO `$table` SET $parameters;" - else -> null - } + fun prepareStatement(connection: Connection) = schema?.let { schema -> + when (operation) { + Operation.INSERT -> { + val parametersClause = fields.map { (column, _) -> "`$column` = ?" }.joinToString(", ") + val sql = "INSERT INTO `${schema.name}` SET $parametersClause" + val statement = connection.prepareStatement(sql) + fields.values.forEachIndexed { index, field -> statement.setObject(index + 1, field.value) } - private val parameters = fields.map { (column, _) -> "`$column` = ?" }.joinToString(", ") + statement + } + + Operation.DELETE -> { + val pk = schema.columns.filtered { it.primary } + val filterClause = pk.joinToString(" AND ") { "`${it.name}` = ?" } + val sql = "DELETE FROM `${schema.name}` WHERE $filterClause" + val statement = connection.prepareStatement(sql) + pk.forEachIndexed { index, column -> statement.setObject(index + 1, fields[column.name]!!.value) } + + statement + } + + else -> null + } + } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/Query.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/Query.kt index d6ad015b..fc853449 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/Query.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/model/data/Query.kt @@ -1,7 +1,8 @@ package com.bartlomiejpluta.base.editor.database.model.data +import com.bartlomiejpluta.base.editor.database.model.schema.SchemaTable import javafx.beans.property.SimpleListProperty -import javafx.beans.property.SimpleStringProperty +import javafx.beans.property.SimpleObjectProperty import javafx.collections.ObservableList import tornadofx.getValue import tornadofx.toProperty @@ -11,10 +12,10 @@ class Query( query: String, columns: ObservableList, data: ObservableList, - table: String? = null + schema: SchemaTable? = null ) { - val tableProperty = SimpleStringProperty(table) - val table by tableProperty + val schemaProperty = SimpleObjectProperty(schema) + val schema by schemaProperty val nameProperty = name.toProperty() val name by nameProperty @@ -30,6 +31,6 @@ class Query( fun addEmptyRecord() { val fields = columns.map { it to DataField(null) }.toMap() - data += DataRecord(fields, Operation.INSERT) + data += DataRecord(fields, Operation.INSERT, schema) } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/DatabaseService.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/DatabaseService.kt index 38c9138d..42e75403 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/DatabaseService.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/DatabaseService.kt @@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.database.service import com.bartlomiejpluta.base.editor.database.model.data.Query import com.bartlomiejpluta.base.editor.database.model.schema.SchemaDatabase +import com.bartlomiejpluta.base.editor.database.model.schema.SchemaTable import java.sql.Connection interface DatabaseService { @@ -9,5 +10,5 @@ interface DatabaseService { fun run(op: Connection.() -> T): T? - fun execute(statement: String, name: String, table: String? = null): Query? + fun execute(statement: String, name: String, schema: SchemaTable? = null): Query? } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/H2DatabaseService.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/H2DatabaseService.kt index 5f434eeb..a3d1eff5 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/H2DatabaseService.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/service/H2DatabaseService.kt @@ -2,8 +2,10 @@ package com.bartlomiejpluta.base.editor.database.service import com.bartlomiejpluta.base.editor.database.model.data.DataField import com.bartlomiejpluta.base.editor.database.model.data.DataRecord +import com.bartlomiejpluta.base.editor.database.model.data.Operation import com.bartlomiejpluta.base.editor.database.model.data.Query import com.bartlomiejpluta.base.editor.database.model.schema.SchemaDatabase +import com.bartlomiejpluta.base.editor.database.model.schema.SchemaTable import com.bartlomiejpluta.base.editor.project.context.ProjectContext import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service @@ -49,7 +51,7 @@ class H2DatabaseService : DatabaseService { return projectContext.project?.database?.connection?.use(op) } - override fun execute(statement: String, name: String, table: String?): Query? = run { + override fun execute(statement: String, name: String, schema: SchemaTable?): Query? = run { val stmt = prepareStatement(statement).apply { execute() } val results = stmt.resultSet val metadata = stmt.metaData @@ -70,10 +72,10 @@ class H2DatabaseService : DatabaseService { record[metadata.getColumnLabel(i)] = field } - data += DataRecord(record) + data += DataRecord(record, Operation.DO_NOTHING, schema) } - return@run Query(name, statement, columns, data, table) + return@run Query(name, statement, columns, data, schema) } return@run null diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/list/TablesListView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/list/TablesListView.kt index 3efb0270..9298a993 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/list/TablesListView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/list/TablesListView.kt @@ -35,7 +35,7 @@ class TablesListView : View() { val selected = selectionModel?.selectedItem?.value if (event.clickCount == 2 && selected is SchemaTable) { databaseController - .execute("SELECT * FROM ${selected.name}", selected.name, selected.name) + .execute("SELECT * FROM ${selected.name}", selected.name, selected) ?.let(mainController::openQuery) } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/query/QueryResultView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/query/QueryResultView.kt index ed166bbb..803c9ea9 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/query/QueryResultView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/view/query/QueryResultView.kt @@ -17,7 +17,7 @@ class QueryResultView : View() { private val queryVM = find() private val table = tableview(queryVM.dataProperty) { - editableProperty().bind(queryVM.tableProperty.isNotNull) + editableProperty().bind(queryVM.schemaProperty.isNotNull) setRowFactory { DataRecordRow() } } @@ -55,7 +55,7 @@ class QueryResultView : View() { } button(graphic = FontIcon("fa-plus")) { - enableWhen(queryVM.tableProperty.isNotNull) + enableWhen(queryVM.schemaProperty.isNotNull) action { queryVM.item?.addEmptyRecord() @@ -63,7 +63,7 @@ class QueryResultView : View() { } button(graphic = FontIcon("fa-minus")) { - enableWhen(queryVM.tableProperty.isNotNull) + enableWhen(queryVM.schemaProperty.isNotNull) action { val selected = table.selectionModel.selectedItem @@ -75,10 +75,10 @@ class QueryResultView : View() { } button(graphic = FontIcon("fa-check")) { - enableWhen(queryVM.tableProperty.isNotNull) + enableWhen(queryVM.schemaProperty.isNotNull) action { - val success = databaseController.submitBatch(queryVM.name, queryVM.data) + val success = databaseController.submitBatch(queryVM.data) if (success) { refresh() } @@ -90,7 +90,7 @@ class QueryResultView : View() { } private fun refresh() { - databaseController.execute(queryVM.query, queryVM.name, queryVM.table)?.let { + databaseController.execute(queryVM.query, queryVM.name, queryVM.schema)?.let { queryVM.item = it } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/viewmodel/QueryVM.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/viewmodel/QueryVM.kt index e5f7caca..5998e1fd 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/viewmodel/QueryVM.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/database/viewmodel/QueryVM.kt @@ -5,8 +5,8 @@ import tornadofx.ItemViewModel import tornadofx.getValue class QueryVM(query: Query) : ItemViewModel(query) { - val tableProperty = bind(Query::tableProperty) - val table by tableProperty + val schemaProperty = bind(Query::schemaProperty) + val schema by schemaProperty val nameProperty = bind(Query::nameProperty) val name by nameProperty