Custom implementation of the Liquibase H2 adapter that uppercases all identifiers. See #20611 for more details. | (ns metabase.db.liquibase.h2 (:require [metabase.util :as u]) (:import (liquibase.database.core H2Database) (liquibase.database.jvm JdbcConnection))) |
(set! *warn-on-reflection* true) | |
(defn- upcase ^String [s] (some-> s u/upper-case-en)) | |
(defn- h2-database* ^H2Database [] (proxy [H2Database] [] (quoteObject [object-name object-type] (let [^H2Database this this] (proxy-super quoteObject (upcase object-name) object-type))) (mustQuoteObjectName [_object-name _object-type] true))) | |
HACK! Create a [[java.lang.Package]] for the proxy class if one does not already exist. This is needed because:
This only does anything in REPL-based development; in the uberjar the proxy class will be AOT'ed and will have a package defined for it when it's loaded by the normal JVM classloader rather than the Clojure DynamicClassLoader | (let [klass (class (h2-database*))] (when-not (.getPackage klass) (let [method (.getDeclaredMethod ClassLoader "definePackage" (into-array Class [String String String String String String String java.net.URL])) class-name (.getName klass) ;; e.g. metabase.db.liquibase.h2.proxy$liquibase.database.core package-name (.substring class-name 0 (.lastIndexOf class-name "."))] (doto method (.setAccessible true) (.invoke (.getClassLoader klass) (into-array Object [package-name nil nil nil nil nil nil nil])) (.setAccessible false)) (assert (.getPackage klass) (format "Failed to create package for proxy class %s." class-name))))) |
A version of the Liquibase H2 implementation that always converts identifiers to uppercase and then quotes them. | (defn h2-database ^H2Database [^JdbcConnection conn] (doto (h2-database*) (.setConnection conn))) |