Skip to content

Commit

Permalink
Merge pull request #158 from mbezjak/migrations-table-exists-sql
Browse files Browse the repository at this point in the history
Add :migrations-table-exists-sql option
  • Loading branch information
weavejester authored Nov 6, 2024
2 parents 9aab515 + 120b75b commit 624da4c
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 18 deletions.
36 changes: 27 additions & 9 deletions jdbc/src/ragtime/jdbc.clj
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,44 @@
(str (:table_schem metadata) "." (:table_name metadata))
(:table_name metadata))))

(defn- table-exists? [db-spec ^String table-name]
(defn- table-exists-via-metadata-scan? [db-spec ^String table-name]
(some (partial metadata-matches-table? table-name)
(get-table-metadata db-spec)))

(defn- ensure-migrations-table-exists [db-spec migrations-table]
(when-not (table-exists? db-spec migrations-table)
(defn- table-exists-via-provided-sql? [db-spec sql]
(pos? (count (sql/query db-spec [sql]))))

(defn- table-exists? [datasource table-name migrations-table-exists-sql]
(if migrations-table-exists-sql
(table-exists-via-provided-sql? datasource migrations-table-exists-sql)
(table-exists-via-metadata-scan? datasource table-name)))

(defn- ensure-migrations-table-exists
[db-spec migrations-table migrations-table-exists-sql]
(when-not (table-exists? db-spec migrations-table migrations-table-exists-sql)
(sql/execute! db-spec [(migrations-table-ddl migrations-table)])))

(defn- format-datetime [^Date dt]
(-> (SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss.SSS")
(.format dt)))

(defrecord SqlDatabase [db-spec migrations-table]
(defrecord SqlDatabase [db-spec migrations-table migrations-table-exists-sql]
p/DataStore
(add-migration-id [_ id]
(ensure-migrations-table-exists db-spec migrations-table)
(ensure-migrations-table-exists db-spec migrations-table
migrations-table-exists-sql)
(sql/insert! db-spec migrations-table
{:id (str id)
:created_at (format-datetime (Date.))}))

(remove-migration-id [_ id]
(ensure-migrations-table-exists db-spec migrations-table)
(ensure-migrations-table-exists db-spec migrations-table
migrations-table-exists-sql)
(sql/delete! db-spec migrations-table ["id = ?" id]))

(applied-migration-ids [_]
(ensure-migrations-table-exists db-spec migrations-table)
(ensure-migrations-table-exists db-spec migrations-table
migrations-table-exists-sql)
(sql/query db-spec
[(str "SELECT id FROM " migrations-table " ORDER BY created_at")]
{:row-fn :id})))
Expand All @@ -70,11 +82,17 @@
The following options are allowed:
:migrations-table - the name of the table to store the applied migrations
(defaults to ragtime_migrations)"
(defaults to ragtime_migrations)
:migrations-table-exists-sql - SQL string to check if migrations table
exists. If not supplied, database metadata is
used instead, which can be slow for large DBs."
([db-spec]
(sql-database db-spec {}))
([db-spec options]
(->SqlDatabase db-spec (:migrations-table options "ragtime_migrations"))))
(->SqlDatabase db-spec
(:migrations-table options "ragtime_migrations")
(:migrations-table-exists-sql options))))

(defn- execute-sql! [db-spec statements transaction?]
(doseq [s statements]
Expand Down
14 changes: 14 additions & 0 deletions jdbc/test/ragtime/jdbc_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@
(is (= ["20" "21"]
(sql/query (:db-spec db) ["SELECT * FROM myschema.migrations"] {:row-fn :id})))))

(deftest test-migrations-table-exists-sql
(let [migrations-table-exists-sql (str "SELECT * FROM INFORMATION_SCHEMA.TABLES"
" WHERE TABLE_CATALOG='TESTDB'"
" AND TABLE_NAME='RAGTIME_MIGRATIONS'")
db (jdbc/sql-database db-spec
{:migrations-table-exists-sql migrations-table-exists-sql})]
(p/add-migration-id db "12")
(is (= ["12"]
(sql/query (:db-spec db) ["SELECT * FROM ragtime_migrations"] {:row-fn :id})))

(p/add-migration-id db "13")
(is (= ["12" "13"]
(sql/query (:db-spec db) ["SELECT * FROM ragtime_migrations"] {:row-fn :id})))))

(defn table-names [db]
(set (sql/query (:db-spec db) ["SHOW TABLES"] {:row-fn :table_name})))

Expand Down
37 changes: 28 additions & 9 deletions next-jdbc/src/ragtime/next_jdbc.clj
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,24 @@
(str table_schem "." table_name)
table_name)))

(defn- table-exists? [datasource ^String table-name]
(defn- table-exists-via-metadata-scan? [datasource ^String table-name]
(let [{:keys [tables quote]} (get-db-metadata datasource)
table-name-unquoted (unquote-table-name quote table-name)]
(some (partial metadata-matches-table? table-name-unquoted)
tables)))

(defn- ensure-migrations-table-exists [datasource migrations-table]
(when-not (table-exists? datasource migrations-table)
(defn- table-exists-via-provided-sql? [datasource sql]
(pos? (count (jdbc/execute! datasource [sql]))))

(defn- table-exists? [datasource table-name migrations-table-exists-sql]
(if migrations-table-exists-sql
(table-exists-via-provided-sql? datasource migrations-table-exists-sql)
(table-exists-via-metadata-scan? datasource table-name)))

(defn- ensure-migrations-table-exists
[datasource migrations-table migrations-table-exists-sql]
(when-not (table-exists? datasource migrations-table
migrations-table-exists-sql)
(let [sql (str "create table " migrations-table
" (id varchar(255) primary key, created_at varchar(32))")]
(jdbc/execute! datasource [sql]))))
Expand All @@ -76,20 +86,23 @@
(-> (SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss.SSS")
(.format dt)))

(defrecord SqlDatabase [datasource migrations-table]
(defrecord SqlDatabase [datasource migrations-table migrations-table-exists-sql]
p/DataStore
(add-migration-id [_ id]
(ensure-migrations-table-exists datasource migrations-table)
(ensure-migrations-table-exists datasource migrations-table
migrations-table-exists-sql)
(sql/insert! datasource migrations-table
{:id (str id)
:created_at (format-datetime (Date.))}))

(remove-migration-id [_ id]
(ensure-migrations-table-exists datasource migrations-table)
(ensure-migrations-table-exists datasource migrations-table
migrations-table-exists-sql)
(sql/delete! datasource migrations-table ["id = ?" id]))

(applied-migration-ids [_]
(ensure-migrations-table-exists datasource migrations-table)
(ensure-migrations-table-exists datasource migrations-table
migrations-table-exists-sql)
(let [sql [(str "SELECT id FROM " migrations-table " ORDER BY created_at")]]
(->> (sql/query datasource sql {:builder-fn rs/as-unqualified-lower-maps})
(map :id)))))
Expand All @@ -101,11 +114,17 @@
:migrations-table - the name of the table to store the applied migrations
(defaults to ragtime_migrations). You must include the
schema name if your DB supports that and you are not
using the default one (ex.: myschema.migrations)"
using the default one (ex.: myschema.migrations)
:migrations-table-exists-sql - SQL string to check if migrations table
exists. If not supplied, database metadata is
used instead, which can be slow for large DBs."
([datasource]
(sql-database datasource {}))
([datasource options]
(->SqlDatabase datasource (:migrations-table options "ragtime_migrations"))))
(->SqlDatabase datasource
(:migrations-table options "ragtime_migrations")
(:migrations-table-exists-sql options))))

(defn- execute-sql! [datasource statements transaction?]
(if transaction?
Expand Down
18 changes: 18 additions & 0 deletions next-jdbc/test/ragtime/next_jdbc_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@
(n.j/execute! (:datasource db))
(map :MIGRATIONS/ID))))))

(deftest test-migrations-table-exists-sql
(let [migrations-table-exists-sql (str "SELECT * FROM INFORMATION_SCHEMA.TABLES"
" WHERE TABLE_CATALOG='TESTDB'"
" AND TABLE_NAME='RAGTIME_MIGRATIONS'")
db (jdbc/sql-database datasource
{:migrations-table-exists-sql migrations-table-exists-sql})]
(p/add-migration-id db "12")
(is (= ["12"]
(->> ["SELECT * FROM ragtime_migrations"]
(sql/query (:datasource db))
(map :RAGTIME_MIGRATIONS/ID))))

(p/add-migration-id db "13")
(is (= ["12" "13"]
(->> ["SELECT * FROM ragtime_migrations"]
(sql/query (:datasource db))
(map :RAGTIME_MIGRATIONS/ID))))))

(defn table-names [db]
(set (map :TABLES/TABLE_NAME (sql/query (:datasource db) ["SHOW TABLES"]))))

Expand Down

0 comments on commit 624da4c

Please sign in to comment.