feat(cli): extend Repl with printNames and tableNames
This commit is contained in:
1 parent
9387689ade
commit
aedd88ca70
2 files changed
+102
-15
No files matched your search
@@ -319,12 +319,34 @@ class Repl(
|
||||
}
|
||||
is CreateTableResult -> output.appendLine("Table ${result.tableName} created")
|
||||
is DropTableResult -> output.appendLine("Table ${result.tableName} dropped")
|
||||
is TruncateTableResult -> output.appendLine("Table(s) ${result.tableNames.joinToString(", ")} truncated")
|
||||
is MergeResult -> {
|
||||
output.appendLine(
|
||||
"${rowsWord(result.insertedCount)} inserted, ${rowsWord(result.updatedCount)} updated, " +
|
||||
"${rowsWord(result.deletedCount)} deleted"
|
||||
)
|
||||
result.returning?.let { output.appendLine(TableRenderer.render(it)) }
|
||||
}
|
||||
is AlterTableResult -> output.appendLine("Table ${result.tableName} altered")
|
||||
is CreateIndexResult -> output.appendLine("Index ${result.indexName} created")
|
||||
is DropIndexResult -> output.appendLine("Index ${result.indexName} dropped")
|
||||
is CreateViewResult -> output.appendLine("View ${result.viewName} created")
|
||||
is DropViewResult -> output.appendLine("View ${result.viewName} dropped")
|
||||
is CreateTriggerResult -> output.appendLine("Trigger ${result.triggerName} created")
|
||||
is DropTriggerResult -> output.appendLine("Trigger ${result.triggerName} dropped")
|
||||
is CreateSequenceResult -> output.appendLine("Sequence ${result.sequenceName} created")
|
||||
is DropSequenceResult -> output.appendLine("Sequence ${result.sequenceName} dropped")
|
||||
is AlterSequenceResult -> output.appendLine("Sequence ${result.sequenceName} altered")
|
||||
is ExplainResult -> result.plan.forEach { output.appendLine(it) }
|
||||
BeginResult -> output.appendLine("Transaction started")
|
||||
CommitResult -> output.appendLine("Transaction committed")
|
||||
RollbackResult -> output.appendLine("Transaction rolled back")
|
||||
is SavepointResult -> output.appendLine("Savepoint ${result.name} created")
|
||||
is ReleaseSavepointResult -> output.appendLine("Savepoint ${result.name} released")
|
||||
is RollbackToSavepointResult -> output.appendLine("Rolled back to savepoint ${result.name}")
|
||||
is PrepareResult -> output.appendLine("Prepared statement ${result.name} created")
|
||||
is DeallocateResult ->
|
||||
output.appendLine(if (result.all) "All prepared statements deallocated" else "Prepared statement ${result.name} deallocated")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,14 +354,15 @@ class Repl(
|
||||
val parts = command.split(Regex("\\s+"), limit = 2)
|
||||
when (parts[0]) {
|
||||
".exit", ".quit" -> return true
|
||||
".tables" -> {
|
||||
val names = catalog.tableNames
|
||||
if (names.isEmpty()) output.appendLine("(no tables)") else names.forEach { output.appendLine(it) }
|
||||
}
|
||||
".indexes" -> {
|
||||
val names = catalog.indexNames
|
||||
if (names.isEmpty()) output.appendLine("(no indexes)") else names.forEach { output.appendLine(it) }
|
||||
}
|
||||
".tables" -> printNames(tableNames(), "(no tables)")
|
||||
".indexes" -> printNames(indexNames(), "(no indexes)")
|
||||
".views" -> printNames(viewNames(), "(no views)")
|
||||
".triggers" -> printNames(triggerNames(), "(no triggers)")
|
||||
".sequences" -> printNames(sequenceNames(), "(no sequences)")
|
||||
".prepared" -> printNames(
|
||||
diskExecutor?.preparedStatementNames ?: executor.preparedStatementNames,
|
||||
"(no prepared statements)"
|
||||
)
|
||||
".schema" -> {
|
||||
if (parts.size < 2 || parts[1].isBlank()) {
|
||||
printError("usage: .schema <table>")
|
||||
@@ -352,25 +375,87 @@ class Repl(
|
||||
return false
|
||||
}
|
||||
|
||||
private fun printNames(names: List<String>, emptyMessage: String) {
|
||||
if (names.isEmpty()) output.appendLine(emptyMessage) else names.forEach { output.appendLine(it) }
|
||||
}
|
||||
|
||||
private fun tableNames(): List<String> = diskCatalog?.tableNames ?: catalog.tableNames
|
||||
private fun viewNames(): List<String> = diskCatalog?.viewNames ?: catalog.viewNames
|
||||
private fun triggerNames(): List<String> = diskCatalog?.triggerNames ?: catalog.triggerNames
|
||||
private fun sequenceNames(): List<String> = diskCatalog?.sequenceNames ?: catalog.sequenceNames
|
||||
|
||||
private fun indexNames(): List<String> {
|
||||
val disk = diskCatalog ?: return catalog.indexNames
|
||||
return disk.tableNames.flatMap { disk.table(it).secondaryIndexes.map { index -> index.name } }
|
||||
}
|
||||
|
||||
/** Every `CREATE [UNIQUE] INDEX ...;` line for [tableName], one engine or the other - never both. */
|
||||
private fun indexLines(tableName: String): List<String> {
|
||||
val disk = diskCatalog
|
||||
if (disk != null) {
|
||||
val table = disk.tableOrNull(tableName) ?: return emptyList()
|
||||
return table.secondaryIndexes.map { index ->
|
||||
val uniqueKeyword = if (index.unique) "UNIQUE " else ""
|
||||
"CREATE ${uniqueKeyword}INDEX ${index.name} ON $tableName (${index.columnNames.joinToString(", ")});"
|
||||
}
|
||||
}
|
||||
return catalog.indexDefinitions()
|
||||
.filter { it.tableName.equals(tableName, ignoreCase = true) }
|
||||
.map { index ->
|
||||
val uniqueKeyword = if (index.unique) "UNIQUE " else ""
|
||||
"CREATE ${uniqueKeyword}INDEX ${index.name} ON $tableName (${index.columnDisplayName});"
|
||||
}
|
||||
}
|
||||
|
||||
/** Every `CREATE TRIGGER ...` block for [tableName], one engine or the other - never both. */
|
||||
private fun triggerLines(tableName: String): List<String> {
|
||||
val definitions = diskCatalog?.triggerDefinitions() ?: catalog.triggerDefinitions()
|
||||
return definitions
|
||||
.filter { it.tableName.equals(tableName, ignoreCase = true) }
|
||||
.map { SqlWriter.triggerText(it) }
|
||||
}
|
||||
|
||||
private fun printSchema(tableName: String) {
|
||||
val table = catalog.tableOrNull(tableName)
|
||||
if (table == null) {
|
||||
val schema = diskCatalog?.tableOrNull(tableName)?.schema
|
||||
?: diskCatalog?.temporaryTableOrNull(tableName)?.schema
|
||||
?: catalog.tableOrNull(tableName)?.schema
|
||||
if (schema == null) {
|
||||
printError("no such table: $tableName")
|
||||
return
|
||||
}
|
||||
val schema = table.schema
|
||||
val builder = StringBuilder()
|
||||
builder.appendLine("CREATE TABLE ${schema.name} (")
|
||||
schema.columns.forEachIndexed { index, column ->
|
||||
val lines = mutableListOf<String>()
|
||||
schema.columns.forEach { column ->
|
||||
val constraints = buildString {
|
||||
if (column.primaryKey) append(" PRIMARY KEY")
|
||||
if (column.notNull && !column.primaryKey) append(" NOT NULL")
|
||||
column.default?.let { append(" DEFAULT ${SqlWriter.expressionText(it)}") }
|
||||
}
|
||||
val comma = if (index < schema.columns.size - 1) "," else ""
|
||||
builder.appendLine(" ${column.name} ${column.type.displayName}$constraints$comma")
|
||||
lines.add(" ${column.name} ${column.type.displayWith(column.precision, column.scale)}$constraints")
|
||||
}
|
||||
builder.append(");")
|
||||
if (schema.compositePrimaryKey.isNotEmpty()) {
|
||||
lines.add(" PRIMARY KEY (${schema.compositePrimaryKey.joinToString(", ")})")
|
||||
}
|
||||
schema.foreignKeys.forEach { fk ->
|
||||
val onDelete = if (fk.onDelete != ForeignKeyAction.NoAction) " ON DELETE ${fk.onDelete.sqlKeyword}" else ""
|
||||
val onUpdate = if (fk.onUpdate != ForeignKeyAction.NoAction) " ON UPDATE ${fk.onUpdate.sqlKeyword}" else ""
|
||||
lines.add(
|
||||
" FOREIGN KEY (${fk.columns.joinToString(", ")}) REFERENCES ${fk.referencedTable} " +
|
||||
"(${fk.referencedColumns.joinToString(", ")})$onDelete$onUpdate"
|
||||
)
|
||||
}
|
||||
schema.checks.forEach { check ->
|
||||
lines.add(" CHECK (${SqlWriter.expressionText(check.expression)})")
|
||||
}
|
||||
schema.uniqueConstraints.forEach { unique ->
|
||||
lines.add(" UNIQUE (${unique.columns.joinToString(", ")})")
|
||||
}
|
||||
builder.append(lines.joinToString(",\n"))
|
||||
builder.append("\n);")
|
||||
output.appendLine(builder.toString())
|
||||
indexLines(schema.name).forEach { output.appendLine(it) }
|
||||
triggerLines(schema.name).forEach { output.appendLine(it) }
|
||||
}
|
||||
|
||||
private fun printError(message: String?) {
|
||||
|
||||
@@ -31,6 +31,8 @@ object TableRenderer {
|
||||
is Value.RealValue -> value.value.toString()
|
||||
is Value.TextValue -> value.value
|
||||
is Value.BooleanValue -> value.value.toString()
|
||||
is Value.DecimalValue -> value.value.toPlainString()
|
||||
is Value.DateValue -> value.value.toString()
|
||||
is Value.NullValue -> "NULL"
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user