   [table]
   (drop-constraints table "foreign key"))
 
+(defn fix-identity-sequence
+  "Resets a sequence to the maximum value used in a column. Useful when a
+  sequence gets out of sync due to a bug or after a transfer."
+  [table column]
+  {:pre [(string? table)
+         (string? column)]}
+  (if (postgres?)
+    ;; PostgreSQL specific way
+    (sql/with-query-results _
+      [(str "SELECT setval(
+        pg_get_serial_sequence(?, ?),
+        (SELECT max(" column ") FROM " table "))") table column])
+
+    ;; HSQLDB specific way
+    (let [maxid (sql/with-query-results result-set
+                    [(str "SELECT max(" column ") as id FROM " table)]
+                    (:id (first result-set)))
+          ;; While postgres handles a nil case gracefully, hsqldb does not
+          restart (if (nil? maxid) 1 (inc maxid))]
+      (sql/do-commands
+        (str "ALTER TABLE " table " ALTER COLUMN " column
+          " RESTART WITH " restart)))))
+
+;; Migration functions
+
 (defn initialize-store
   "Create the initial database schema."
   []


            "ALTER TABLE catalog_resources DROP CONSTRAINT catalog_resources_pkey"
            "ALTER TABLE catalog_resources ADD CONSTRAINT catalog_resources_pkey PRIMARY KEY (catalog_id, type, title)"])))

;; The available migrations, as a map from migration version to migration function.
(def migrations

   17 use-bigint-instead-of-catalog-hash
   18 add-index-on-exported-column
   19 differential-edges
   20 differential-catalog-resources
   21 reset-catalog-sequence-to-latest-id})

(def desired-schema-version (apply max (keys migrations)))

