Skip to content

Instantly share code, notes, and snippets.

@konikvranik
Created January 6, 2024 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save konikvranik/15ff54cb2c3b255ce86a689b8e2ba6c6 to your computer and use it in GitHub Desktop.
Save konikvranik/15ff54cb2c3b255ce86a689b8e2ba6c6 to your computer and use it in GitHub Desktop.
SchemaCrawler PlantUML script for more detailed output
import schemacrawler.schema.Catalog
import schemacrawler.schema.Schema
import schemacrawler.schema.Table
println("@startuml")
println('''
!theme plain
hide empty methods
!procedure $schema($name, $slug)
package "$name" as $slug <<Rectangle>>
!endprocedure
!procedure $table($name, $slug)
entity "<b>$name</b>" as $slug << (T, Orange) table >>
!endprocedure
!procedure $view($name, $slug)
entity "<b>$name</b>" as $slug << (V, Aquamarine) view >>
!endprocedure
!procedure $pkfk($name)
{field}<color:#Brown><&key></color> <u><i>$name</i></u>
!endprocedure
!procedure $pk($name)
{field}<color:#GoldenRod><&key></color> <u>$name</u>
!endprocedure
!procedure $fk($name)
{field}<color:#Silver><&key></color> <i>$name</i>
!endprocedure
!procedure $column($name)
{field}<color:#White><&media-record></color> $name
!endprocedure
!procedure $pk_index($name, $columns)
{method}<<PK>> $name ($columns)
!endprocedure
!procedure $fk_constraint($name, $col, $target, $columns)
{method}<<FK>> $name ($col) <&arrow-right> $target ($columns)
!endprocedure
!procedure $unique($name, $columns)
{method}<<unique>> $name ($columns)
!endprocedure
!procedure $index_column($name, $columns)
{method}<<index>> $name ($columns)
!endprocedure
''')
renderTitle(title, catalog)
// Tables
renderSchemas(catalog)
// Foreign keys
renderLinks(catalog)
println()
println("@enduml")
private void renderTitle(String title, Catalog catalog) {
println('title "' + title + '"')
println()
println('legend bottom right')
println('generated by ' + catalog.crawlInfo.schemaCrawlerVersion.toString())
println('generated on ' + catalog.crawlInfo.crawlTimestamp)
println('end legend')
println()
println()
}
private void renderSchemas(Catalog catalog) {
catalog.schemas.forEach { schema ->
if (!catalog.getTables(schema).empty) {
renderSchema(schema, catalog)
println()
}
}
}
private void renderSchema(Schema schema, Catalog catalog) {
println("\$schema(\"${schema.fullName.replaceAll('"', '""')}\", \"${schema.key().slug()}\") {")
println()
renderTables(catalog, schema)
println()
println('}')
}
private void renderTables(Catalog catalog, Schema schema) {
catalog.getTables(schema).forEach { table ->
renderTable(table)
println()
renderTableNote(table)
renderColumnNotes(table)
println()
println()
}
}
private void renderTableNote(Table table) {
if (table.remarks) {
println('note left of ' + table.key().slug() + ' #LemonChiffon')
println(table.remarks)
println('end note')
println()
}
}
private void renderColumnNotes(Table table) {
table.columns.each { column ->
if (column.remarks) {
println('note right of ' + table.key().slug() + '::'
+ column.name + ' #LightCyan')
println(column.remarks)
println('end note')
println()
}
}
}
private void renderTable(Table table) {
def viewType = table.tableType.view ? '$view' : '$table'
println("$viewType(\"${table.name.replaceAll('"', '""')}\", \"${table.key().slug()}\") {")
renderColumns(table)
if (table.primaryKey && !(table.indexes?.any { it.name == table.primaryKey.name })) {
println " \$pk_index(\"${table.primaryKey.name.replaceAll('"', '""')}\",\"${table.primaryKey.constrainedColumns.collect { it.name.replaceAll('"', '""') }.join(',')}\")"
}
table.foreignKeys.each { fk ->
println " \$fk_constraint(\"${fk.name.replaceAll('"', '""')}\", \"${fk.constrainedColumns.collect { it.name.replaceAll('"', '""') }.join(',')}\", \"${fk.referencedTable.name.replaceAll('"', '""')}\", \"${fk.columnReferences.collect { it.primaryKeyColumn.name.replaceAll('"', '""') }.join(',')}\" )"
}
table.indexes.each { index ->
print(' ')
if (table.primaryKey?.name == index.name) {
print('$pk_index')
} else if (index.unique) {
print('$unique')
} else {
print('$index_column')
}
printf("(\"%s\", \"%s\")%n", index.name.replaceAll('"', '""'), index.columns.sort { it.indexOrdinalPosition }.collect { it.name.replaceAll('"', '""') }.join(","))
}
println('}')
}
private void renderColumns(Table table) {
table.columns.each { column ->
def columnType = column.partOfPrimaryKey && column.partOfForeignKey ? '$pkfk' : column.partOfPrimaryKey ? '$pk'
: column.partOfForeignKey ? '$fk'
: '$column'
println(" $columnType(\"$column.name\"): $column.columnDataType.name${column.columnDataType.precision ? "(${column.size}${column.decimalDigits ? ",${column.decimalDigits}" : ''})" : ''}${column.nullable ? '' : ' NOT NULL'}")
}
}
private void renderLinks(Catalog catalog) {
catalog.tables.each { table ->
table.exportedForeignKeys.each { fk ->
def pkTable = fk.primaryKeyTable
def fkTable = fk.foreignKeyTable
print("${pkTable.schema.key().slug()}.${pkTable.key().slug()}")
def primaryColumns = fk.columnReferences.primaryKeyColumn.collect { it.name.replaceAll('"', '""') }
def foreignColumns = fk.columnReferences.foreignKeyColumn.collect { it.name.replaceAll('"', '""') }
if (primaryColumns.size() == 1) {
print("::${primaryColumns.join(',')} ")
}
print(" \"${primaryColumns.join(',')}\" ||--o{ \"${foreignColumns.join(',')}\" ${fkTable.schema.key().slug()}.${fkTable.key().slug()}")
if (foreignColumns.size() == 1) {
print("::${foreignColumns.join(',')} ")
}
if (fk.name && !fk.name.startsWith('SCHCRWLR_')) {
println(' : ' + fk.name)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment