   "The entity passed to `-sel-select` gets merged with this dictionary right before `select` gets called. This lets you override some of the korma
    entity fields like `:transforms` or `:table`, if need be."
   {})
+
+(defmulti pre-insert
+  "Gets called by `ins` immediately before inserting a new object immediately before the korma `insert` call.
+   This provides an opportunity to do things like encode JSON or provide default values for certain fields.
+
+    (pre-insert Query [_ query]
+      (let [defaults {:version 1}]
+        (merge defaults query))) ; set some default values"
+  (fn [entity _] entity))
+
+(defmethod pre-insert :default [_ obj]
+  obj)   ; default impl returns object as is
+
+(defn ins
+  "Wrapper around `korma.core/insert` that renames the `:scope_identity()` keyword in output to `:id`
+   and automatically passes &rest KWARGS to `korma.core/values`.
+
+   Returns newly created object by calling `sel`."
+  [entity & kwargs]
+  (let [vals (->> kwargs
+                  (apply assoc {})
+                  (pre-insert entity))]
+    (let [{:keys [id]} (-> (insert entity (values vals))
+                           (clojure.set/rename-keys {(keyword "scope_identity()") :id}))]
+      (sel :one entity :id id))))
 
 (defmacro -sel-select
   "Internal macro used by `sel` (don't call this directly).

  "Should we enable DB call logging? (You might want to disable this if we're doing many in parallel)"
  true)

(defmulti pre-insert
  "Gets called by `ins` immediately before inserting a new object immediately before the korma `insert` call.
   This provides an opportunity to do things like encode JSON or provide default values for certain fields.

    (pre-insert Query [_ query]
      (let [defaults {:version 1}]
        (merge defaults query))) ; set some default values"
  (fn [entity _] entity))

(defmethod pre-insert :default [_ obj]
  obj)   ; default impl returns object as is

(defn ins
  "Wrapper around `korma.core/insert` that renames the `:scope_identity()` keyword in output to `:id`
   and automatically passes &rest KWARGS to `korma.core/values`.

   Returns newly created object by calling `sel`."
  [entity & kwargs]
  (let [vals (->> kwargs
                  (apply assoc {})
                  (pre-insert entity))]
    (let [{:keys [id]} (-> (insert entity (values vals))
                           (clojure.set/rename-keys {(keyword "scope_identity()") :id}))]
      (sel :one entity :id id))))

(defmulti pre-update
  "Like pre-insert but called by `upd` before DB operations happen."

    (sel :many Table :db_id 1)                    -> (select User (where {:id 1}))
    (sel :many Table :db_id 1 (order :name :ASC)) -> (select User (where {:id 1}) (order :name ASC))"
  [one-or-many entity & forms]
  {:pre [(or (println "one-or-many:" one-or-many)
             true)
         (contains? #{:one :many} one-or-many)]}
  `(->> (-sel-select ~entity ~@forms ~@(when (= one-or-many :one) `((limit 1))))
        (map (partial post-select (entity->korma ~entity)))
        ~(case one-or-many
