[Editor] Enable refreshing Queries

This commit is contained in:
2021-03-25 20:12:58 +01:00
parent 128620851f
commit d77d7d116f
7 changed files with 100 additions and 57 deletions

View File

@@ -0,0 +1,34 @@
package com.bartlomiejpluta.base.editor.database.controller
import com.bartlomiejpluta.base.editor.database.model.data.Query
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.SQLException
@Component
class DatabaseController : Controller() {
private val databaseService: DatabaseService by di()
fun execute(statement: String, name: String = ""): Query? = try {
databaseService.execute(statement, name)
} catch (e: SQLException) {
sqlErrorAlert(e)
null
}
fun execute(op: Connection.() -> Unit) {
databaseService.run<Unit> {
try {
op(this)
} catch (e: SQLException) {
sqlErrorAlert(e)
}
}
}
private fun sqlErrorAlert(e: SQLException) =
error("SQL Error ${e.sqlState}", e.joinToString("\n") { e.message ?: "" }, title = "SQL Error")
}

View File

@@ -3,7 +3,10 @@ package com.bartlomiejpluta.base.editor.database.model.data
import tornadofx.getValue
import tornadofx.toProperty
class Query(name: String, val columns: List<String>, val data: List<DataRecord>) {
class Query(name: String, query: String, val columns: List<String>, val data: List<DataRecord>) {
val nameProperty = name.toProperty()
val name by nameProperty
val queryProperty = query.toProperty()
val query by queryProperty
}

View File

@@ -1,9 +1,13 @@
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 java.sql.Connection
interface DatabaseService {
val database: SchemaDatabase
fun run(op: Connection.() -> Unit)
fun <T> run(op: Connection.() -> T): T?
fun execute(statement: String, name: String = ""): Query?
}

View File

@@ -1,5 +1,8 @@
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.Query
import com.bartlomiejpluta.base.editor.database.model.schema.ColumnType
import com.bartlomiejpluta.base.editor.database.model.schema.SchemaDatabase
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
@@ -42,9 +45,38 @@ class H2DatabaseService : DatabaseService {
@Autowired
private lateinit var projectContext: ProjectContext
override fun run(op: Connection.() -> Unit) {
projectContext.project?.database?.connection?.use(op)
override fun <T> run(op: Connection.() -> T): T? {
return projectContext.project?.database?.connection?.use(op)
}
private fun parseType(type: String) = ColumnType.valueOf(type.replace(" ", "_").substringBefore("("))
override fun execute(statement: String, name: String): Query? = run {
val stmt = prepareStatement(statement).apply { execute() }
val results = stmt.resultSet
val metadata = stmt.metaData
if (results != null && metadata != null) {
val columns = mutableListOf<String>()
for (i in 1..metadata.columnCount) {
columns += metadata.getColumnLabel(i)
}
val data = mutableListOf<DataRecord>()
while (results.next()) {
val record = mutableMapOf<String, DataField>()
for (i in 1..metadata.columnCount) {
record[metadata.getColumnLabel(i)] = DataField(results.getObject(i).toString())
}
data += DataRecord(record)
}
return@run Query(name, statement, columns, data)
}
return@run null
}
}

View File

@@ -1,10 +1,8 @@
package com.bartlomiejpluta.base.editor.database.view.list
import com.bartlomiejpluta.base.editor.database.component.SQLElementCell
import com.bartlomiejpluta.base.editor.database.controller.DatabaseController
import com.bartlomiejpluta.base.editor.database.model.*
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.Query
import com.bartlomiejpluta.base.editor.database.model.schema.Schema
import com.bartlomiejpluta.base.editor.database.model.schema.SchemaDatabase
import com.bartlomiejpluta.base.editor.database.model.schema.SchemaTable
@@ -15,13 +13,12 @@ import com.bartlomiejpluta.base.editor.project.context.ProjectContext
import javafx.scene.control.TreeItem
import org.kordamp.ikonli.javafx.FontIcon
import tornadofx.*
import java.sql.Connection
import java.sql.SQLException
class TablesListView : View() {
private val mainController: MainController by di()
private val projectContext: ProjectContext by di()
private val databaseService: DatabaseService by di()
private val databaseController: DatabaseController by di()
private var database: SchemaDatabase? = null
@@ -37,9 +34,9 @@ class TablesListView : View() {
setOnMouseClicked { event ->
val selected = selectionModel?.selectedItem?.value
if (event.clickCount == 2 && selected is SchemaTable) {
onConnection {
executeScript(selected.name, "SELECT * FROM ${selected.name}", this)
}
databaseController
.execute("SELECT * FROM ${selected.name}", selected.name)
?.let(mainController::openQuery)
}
}
}
@@ -57,7 +54,10 @@ class TablesListView : View() {
val name = "Script ${++index}"
mainController.openScript(
fsNode = InMemoryStringFileNode(name, "sql", ""),
execute = { code -> onConnection { executeScript(name, code, this) } },
execute = { code ->
databaseController.execute(code, name)?.let(mainController::openQuery)
refresh()
},
saveable = false
)
}
@@ -84,51 +84,12 @@ class TablesListView : View() {
treeView.root.expandTo(1)
}
private fun onConnection(op: Connection.() -> Unit) {
databaseService.run {
try {
op(this)
} catch (e: SQLException) {
error("SQL Error ${e.sqlState}", e.joinToString("\n") { e.message ?: "" }, title = "SQL Error")
}
}
}
private fun executeScript(name: String, sql: String, conn: Connection) {
val stmt = conn.prepareStatement(sql).apply { execute() }
val results = stmt.resultSet
val metadata = stmt.metaData
if (results != null && metadata != null) {
val columns = mutableListOf<String>()
for (i in 1..metadata.columnCount) {
columns += metadata.getColumnLabel(i)
}
val data = mutableListOf<DataRecord>()
while (results.next()) {
val record = mutableMapOf<String, DataField>()
for (i in 1..metadata.columnCount) {
record[metadata.getColumnLabel(i)] = DataField(results.getObject(i).toString())
}
data += DataRecord(record)
}
mainController.openQuery(Query(name, columns, data))
}
refresh()
}
private fun renameElement(element: Schema, newName: String): Schema {
onConnection { element.rename(this, newName) }
databaseController.execute { element.rename(this, newName) }
return element
}
private fun deleteElement(element: Schema) {
onConnection(element::delete)
databaseController.execute(element::delete)
}
}

View File

@@ -1,17 +1,19 @@
package com.bartlomiejpluta.base.editor.database.view.query
import com.bartlomiejpluta.base.editor.database.component.QueryFieldCell
import com.bartlomiejpluta.base.editor.database.controller.DatabaseController
import com.bartlomiejpluta.base.editor.database.model.data.DataField
import com.bartlomiejpluta.base.editor.database.model.data.DataRecord
import com.bartlomiejpluta.base.editor.database.viewmodel.QueryVM
import javafx.scene.control.TableColumn
import org.kordamp.ikonli.javafx.FontIcon
import tornadofx.*
class QueryResultView : View() {
private val databaseController: DatabaseController by di()
private val queryVM = find<QueryVM>()
private val table = tableview<DataRecord> {
}
private val table = tableview<DataRecord>()
init {
queryVM.itemProperty.addListener { _, _, _ -> refreshData() }
@@ -38,7 +40,11 @@ class QueryResultView : View() {
override val root = borderpane {
top = toolbar {
button(graphic = FontIcon("fa-refresh")) {
action {
databaseController.execute(queryVM.query, queryVM.name)?.let { queryVM.item = it }
}
}
}
center = table

View File

@@ -7,4 +7,7 @@ import tornadofx.getValue
class QueryVM(query: Query) : ItemViewModel<Query>(query) {
val nameProperty = bind(Query::nameProperty)
val name by nameProperty
val queryProperty = bind(Query::queryProperty)
val query by queryProperty
}