Created
November 27, 2018 20:44
-
-
Save bwalex/bb3d3a757ab6071a2623f10512710907 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(comment | |
(jdbc/query db sqlvec {:identifiers ... | |
:keywordize? ... | |
:qualifier ...}) | |
(def sql-schema | |
{:tables {:location "locations" | |
:part "parts" | |
:stock "stock" | |
:stock-log "stock_log"} | |
:columns {:location | |
#{:id :name :description} | |
:part | |
#{:id :mpn :manufacturer} | |
:stock | |
#{:id :part-id :location-id :qty} | |
:stock-log | |
#{:id :part-id :location-id :qty :qty-change}} | |
:idents {:locations/all :location | |
:parts/all :part | |
:stock-log/by-location :stock-log/location-id | |
:stock-log/by-part :stock-log/part-id} | |
:joins {:part/stock [:part/id :stock/part-id] | |
:location/stock [:location/id :stock/location-id] | |
:part/stock-log [:part/id :stock-log/part-id] | |
:location/stock-log [:location/id :stock-log/location-id]} | |
:reversed-joins {:stock/part :part/stock | |
:stock/location :location/stock | |
:stock-log/part :part/stock-log | |
:stock-log/location :location/stock-log} | |
:cardinality {:part/updated-by :one | |
:stock/updated-by :one | |
:stock-log/updated-by :one | |
:location/updated-by :one | |
:stock/part :one | |
:stock/location :one | |
:stock-log/part :one | |
:stock-log/location :one} | |
:alias-cols {:stock/part-id :part/id | |
:stock/location-id :location/id | |
:stock-log/part-id :part/id | |
:stock-log/location-id :location/id}}) | |
;; 1. for each ident, generate a resolver | |
;; a. if RHS doesn't have a namespace, it's a query without inputs | |
;; b. if RHS does have a namespace, it's a query WHERE rhs_field = input_value | |
;; 2. for each join, generate a resolver with output of LHS FROM ns-of-rhs_field.2 WHERE rhs_field.2 = input_value (where input is rhs_field.1) | |
;; depending on cardinality, do a (first) on the result... | |
;; 3. turn reversed join into forward joins by renaming LHS, swapping RHS entries and do step 2 again. | |
;; 4. for each alias-col, do a pc/alias-resolver2 thing | |
(defn expand-joins [{:keys [joins reversed-joins]}] | |
(reduce | |
(fn [a [k v]] | |
(let [fwd-join (get joins v)] | |
(assoc a k [(second fwd-join) (first fwd-join)]))) | |
joins | |
reversed-joins)) | |
(expand-joins sql-schema) | |
(defn compile-schema [schema] | |
(merge schema | |
{::expanded-joins (expand-joins schema)})) | |
(def compiled-schema (compile-schema sql-schema)) | |
(defn query-fields [{::keys [expanded-joins]} pq] | |
(->> pq | |
(mapcat #(if (map? %) (keys %) [%])) | |
(map (fn [x] | |
(if-let [join (get expanded-joins x)] | |
(first join) | |
x))))) | |
(query-fields compiled-schema | |
[:stock/id :stock/qty :stock/part-id]) | |
(query-fields compiled-schema | |
[:stock/id :stock/qty :stock/part-id {:stock/location [:location/id]}]) | |
(defn build-query [qmap] | |
qmap) | |
(defn build-joins [schema] | |
(for [join (::expanded-joins schema)] | |
(let [[output [input ns-col]] join | |
table (namespace ns-col) | |
col (name ns-col) | |
target-cols (get-in schema [:columns (keyword table)]) | |
;; e.g: env {::p/parent-query [:stock/id :stock/qty :stock/part-id {:stock/location [:location/id]}]} | |
resolve-fn | |
(fn [env entity] | |
(let [fields (->> (::p/parent-query env) | |
(query-fields schema) | |
(filter #(= (namespace %) table)) | |
(map (comp keyword name)) | |
(filter target-cols)) ] | |
(build-query {:select fields | |
:from [table] | |
:where [:= col]})))] | |
{::pc/sym (gensym) | |
::pc/input #{input} | |
::pc/output [{output (mapv (comp (partial keyword table) name) target-cols)}] | |
::pc/resolve resolve-fn}))) | |
(build-joins compiled-schema) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment