Created
February 18, 2022 02:17
-
-
Save camsaul/492c92b2152ada7a7cd1532a892d8a0a to your computer and use it in GitHub Desktop.
Custom Liquibase Table SQL Generator in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns metabase.db.liquibase.h2 | |
"Loading this namespace will replace the default `H2Database` implementation with our custom subclass that uppercases | |
all identifiers." | |
(:require [metabase.util :as u] | |
[clojure.string :as str]) | |
(:import liquibase.database.DatabaseFactory | |
liquibase.database.jvm.JdbcConnection | |
liquibase.change.ChangeMetaData | |
liquibase.change.core.CreateTableChange | |
liquibase.change.ChangeFactory | |
liquibase.change.Change | |
liquibase.sqlgenerator.SqlGeneratorFactory | |
liquibase.sqlgenerator.SqlGenerator | |
liquibase.statement.SqlStatement | |
liquibase.sqlgenerator.core.CreateTableGenerator | |
liquibase.statement.core.CreateTableStatement | |
liquibase.statement.ForeignKeyConstraint | |
liquibase.database.core.H2Database)) | |
(defonce priority (atom 10)) | |
(defn h2-create-table-generator ^CreateTableGenerator [] | |
(let [priority (swap! priority inc)] | |
(println (format "USING %04d" priority)) | |
(proxy [CreateTableGenerator] [] | |
(getPriority [] priority) | |
(supports [statement database] | |
(let [^CreateTableGenerator this this] | |
(proxy-super supports statement database))) | |
(generateStatementsIsVolatile [database] | |
false) | |
(generateRollbackStatementsIsVolatile [database] | |
(let [^CreateTableGenerator this this] | |
(proxy-super generateRollbackStatementsIsVolatile database))) | |
(validate [statement database sql-generator-chain] | |
nil) | |
(warn [statement-type database sql-generator-chain] | |
nil) | |
(generateSql [^CreateTableStatement statement database sql-generator-chain] | |
(let [^CreateTableGenerator this this] | |
#_(let [fks (.getForeignKeyConstraints statement)] | |
(doseq [^ForeignKeyConstraint fk fks] | |
(let [field (doto (.getDeclaredField ForeignKeyConstraint "references") | |
(.setAccessible true))] | |
(println "(.get field fk):" (.get field fk)) ; NOCOMMIT | |
(.set field fk nil) | |
(println "(.get field fk):" (.get field fk)) ; NOCOMMIT | |
))) | |
#_(doto statement | |
(.addColumnConstraint (doto (liquibase.statement.ForeignKeyConstraint. | |
"my_fk" | |
"bird(nest)" | |
nil #_"WOO" | |
"ID2") | |
(.setColumn "user_id")))) | |
(when-let [fks (not-empty (.getForeignKeyConstraints statement))] | |
(doseq [^liquibase.statement.ForeignKeyConstraint fk fks] | |
(println " FK =>" (pr-str {:name (.getForeignKeyName fk) | |
:references (.getReferences fk) | |
:referenced-columns (.getReferencedColumnNames fk) | |
:referenced-table {:table (.getReferencedTableName fk) | |
:catalog (.getReferencedTableCatalogName fk) | |
:schema (.getReferencedTableSchemaName fk)} | |
:column (.getColumn fk)})))) | |
(let [sqls (proxy-super generateSql ^CreateTableStatement statement database sql-generator-chain)] | |
(doseq [^liquibase.sql.Sql sql sqls] | |
(println "sql:" sql)) ; NOCOMMIT | |
sqls)))))) | |
(println "PRIORITY =>" (.getPriority (h2-create-table-generator))) | |
(defn all-generators [] | |
(let [method (doto (.getDeclaredMethod SqlGeneratorFactory "getGenerators" (into-array Class [])) | |
(.setAccessible true))] | |
(into [] (.invoke method (SqlGeneratorFactory/getInstance) (into-array Object []))))) | |
(doseq [^liquibase.sqlgenerator.SqlGenerator generator (all-generators)] | |
(when (str/starts-with? (.getCanonicalName (class generator)) "metabase") | |
(println (format "UNREGISTER %04d %s" (.getPriority generator) (class generator))) | |
(.unregister (SqlGeneratorFactory/getInstance) (class generator)))) | |
(let [field (doto (.getDeclaredField SqlGeneratorFactory "generatorsByKey") | |
(.setAccessible true))] | |
(.clear ^java.util.Map (.get field (SqlGeneratorFactory/getInstance)))) | |
(println "REGISTER" (class (h2-create-table-generator))) | |
(.register (SqlGeneratorFactory/getInstance) (h2-create-table-generator)) | |
(with-open [conn (.getConnection metabase.db.env/data-source)] | |
(metabase.db.liquibase/with-liquibase [liquibase conn] | |
(println "create table generators:") | |
(let [generators (.getGenerators (SqlGeneratorFactory/getInstance) | |
(liquibase.statement.core.CreateTableStatement. nil "PUBLIC" "woo") | |
(.getDatabase liquibase))] | |
(doseq [^liquibase.sqlgenerator.SqlGenerator generator generators] | |
(println (format "%04d %s" (.getPriority generator) (class generator))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment