Hi all, I seemingly have issues with transformations being not applied on aliased entities in korma selects.
(ns local.korma-lab
(:require [korma.core :as k]))
(set! *warn-on-reflection* true)
(def dispatch-type
{3 :email
4 :other})
(k/defentity customer-actor-dispatch-process
(k/transform #(update % :dispatch-type dispatch-type)))
;; This doesn't apply the transformation on the :dispatch-type field:
(k/select [customer-actor-dispatch-process :cadp]
(k/where {:cadp.bill-id 13}))
;; => [{:bill-id 13,
;; :dispatch-type 3,
;; :id 13,
;; ...}]
;; But this does...
(k/select customer-actor-dispatch-process
(k/where {:customer-actor-dispatch-process.bill-id 13}))
;; => ({:bill-id 13,
;; :dispatch-type :email,
;; :id 13,
;; ...})
(def query-bad (-> (k/select* [customer-actor-dispatch-process :cadp])
(k/where {:cadp.bill-id 13})))
;; => {:alias nil,
;; :aliases #{},
;; :db nil,
;; :ent [{:db nil,
;; :fields [],
;; :name "customer-actor-dispatch-process",
;; :pk :id,
;; :prepares (#<Fn@246b4d80
;; local.korma_lab/make_transform[fn]>),
;; :rel {},
;; :table "customer-actor-dispatch-process",
;; :transforms (#<Fn@5d6a236d
;; local.korma_lab/make_transform[fn]>)} :cadp],
;; :fields [:korma.core/*],
;; :from
;; [[{:db nil,
;; :fields [],
;; :name "customer-actor-dispatch-process",
;; :pk :id,
;; :prepares (#<Fn@246b4d80 local.korma_lab/make_transform[fn]>),
;; :rel {},
;; :table "customer-actor-dispatch-process",
;; :transforms (#<Fn@5d6a236d
;; local.korma_lab/make_transform[fn]>)} :cadp]],
;; :group [],
;; :joins [],
;; :modifiers [],
;; :options nil,
;; :order [],
;; :results :results,
;; :table nil,
;; :type :select,
;; :where
;; [{:korma.sql.utils/args
;; [" AND "
;; ({:korma.sql.utils/args [:cadp.bill-id "=" 13],
;; :korma.sql.utils/pred
;; #<Fn@60784dcb korma.sql.engine/do_infix>})],
;; :korma.sql.utils/pred
;; #<Fn@6028c840 korma.sql.engine/do_group>}]}
(k/exec query-bad)
;; => [{:bill-id 13,
;; :dispatch-type 3,
;; :id 13,
;; ...}]
(def query-good (-> (k/select* customer-actor-dispatch-process)
(k/where {:customer-actor-dispatch-process.bill-id 13})))
;; => {:alias nil,
;; :aliases #{},
;; :db nil,
;; :ent {:db nil,
;; :fields [],
;; :name "customer-actor-dispatch-process",
;; :pk :id,
;; :prepares (#<Fn@246b4d80
;; local.korma_lab/make_transform[fn]>),
;; :rel {},
;; :table "customer-actor-dispatch-process",
;; :transforms (#<Fn@5d6a236d
;; local.korma_lab/make_transform[fn]>)},
;; :fields [:korma.core/*],
;; :from [{:db nil,
;; :fields [],
;; :name "customer-actor-dispatch-process",
;; :pk :id,
;; :prepares (#<Fn@246b4d80
;; local.korma_lab/make_transform[fn]>),
;; :rel {},
;; :table "customer-actor-dispatch-process",
;; :transforms (#<Fn@5d6a236d
;; local.korma_lab/make_transform[fn]>)}],
;; :group [],
;; :joins [],
;; :modifiers [],
;; :options nil,
;; :order [],
;; :results :results,
;; :table "customer-actor-dispatch-process",
;; :type :select,
;; :where
;; [{:korma.sql.utils/args
;; [" AND "
;; ({:korma.sql.utils/args
;; [{:korma.sql.utils/generated
;; "customer_actor_dispatch_process.bill_id"} "=" 13],
;; :korma.sql.utils/pred
;; #<Fn@60784dcb korma.sql.engine/do_infix>})],
;; :korma.sql.utils/pred
;; #<Fn@6028c840 korma.sql.engine/do_group>}]}
(k/exec query-good)
;; => ({:bill-id 13,
;; :dispatch-type :email,
;; :id 13,
;; ...})
;; The below is how exec and apply-transforms are defined in korma.core:
; (defn- apply-transforms
; [query results]
; (if (= (:type query) :delete)
; results
; (if-let [trans (-> query :ent :transforms seq)] ;; <-- Please note this expects :transforms to be found directly on :ent
; (let [trans-fn (apply comp trans)]
; (if (sequential? results)
; (map trans-fn results)
; (trans-fn results)))
; results)))
; (defn exec
; "Execute a query map and return the results."
; [query]
; (let [query (apply-prepares query)
; query (bind-query query (eng/->sql query))
; sql (:sql-str query)
; params (:params query)]
; (cond
; (:sql query) sql
; (= *exec-mode* :sql) sql
; (= *exec-mode* :query) query
; (= *exec-mode* :dry-run) (do
; (println "dry run ::" sql "::" (vec params))
; (let [result-keys (conj (->> query :ent :rel vals
; (map deref)
; (filter (comp #{:belongs-to} :rel-type))
; (map :fk-key))
; (-> query :ent :pk))
; results (apply-posts query [(zipmap result-keys (repeat 1))])]
; (first results)
; results))
; :else (let [results (db/do-query query)]
; (apply-transforms query (apply-posts query results))))))
;; The issue stems from how the transforms are retrieved in the
;; apply-transforms function:
;; 1. In query-bad, the :ent key contains a vector [{...} :cadp] instead
;; of just the entity map. This is due to the aliasing syntax
;; [customer-actor-dispatch-process :cadp] used in k/select*.
;; 2. In query-good, the :ent key directly contains the entity map, which
;; includes the :transforms key.
;; 3. The apply-transforms function tries to access :transforms directly
;; from :ent, which works for query-good but not for query-bad.This is for korma v0.3.3 which I understand is an old one, but the apply-transforms seems to be the same in newer versions anyway.
I mainly wonder if supplying aliases on tables in the query with a vector like [entity :alias] is a supported way of doing things at all? The select query seems to be generated fine, but the transforms do not run.
Is there a more proper way to use aliases so that one doesn’t have to supply the full-blown entity/table name in every where clause and field selectors?
Seems like it's this issue? https://github.com/korma/Korma/issues/96 Looks like Korma is properly abandoned...
Maybe check out https://github.com/seancorfield/honeysql
Heh, that sucks. Moving to honeysql or something else would be a solution in the long run, but not something we can do at the moment, as there’s quite a bunch of korma-based code in the project. 😟
Thanks for looking into this anyway 🙂