~subsetpark/doozer

78e327072b2de1c07a172e804891561f3e52a42f — Zach Smith 11 months ago 37688e0
minor
1 files changed, 24 insertions(+), 31 deletions(-)

M doozer/from.janet
M doozer/from.janet => doozer/from.janet +24 -31
@@ 1,15 1,6 @@
(import /doozer/common)
(import /doozer/compose)

(defn- validate-length
  [expr-type n form]
  (unless (= n (length form))
    (errorf (string "Query parsing error: expression of type `%s` "
                    "expects exactly %n element(s) "
                    "(got: %q)")
            (string expr-type) n form))
  form)

## Atoms

(defn- make-value


@@ 42,12 33,21 @@
      :table (string tab)
      :column (string col)}))

##

(defn- validate-length
  [expr-type n form]
  (unless (= n (length form))
    (errorf (string "Query parsing error: expression of type `%s` "
                    "expects exactly %n element(s) "
                    "(got: %q)")
            (string expr-type) n form))
  form)

(defn- make-subquery
  [query]
  @{:subquery query})

## Parsing

(defn- op-type
  [op]
  (case op


@@ 63,6 63,8 @@
    'and :and
    'or :or))

## Parsing

(defn- make-expression
  [form]
  (if-not (indexed? form)


@@ 72,10 74,7 @@
      (case head
        # undocumented: this is useful for deterministic test output.
        'override-sym (make-value ;rest)
        '@ (let
             # validate against extra values in a form like (@ sym x y z);
             # otherwise they might be interpreted as a symbol override
             [[val] (validate-length :variable 1 rest)]
        '@ (let [[val] (validate-length :variable 1 rest)]
             (make-value val))
        '. (make-column-ref rest)
        'subquery (let [[subquery] (validate-length :subquery 1 rest)]


@@ 109,7 108,7 @@
                            :as (string alias)}
    (make-expression form)))

(defn- construct-join
(defn- make-join
  [[binding join-expr] &opt alias]

  (defn do-construct


@@ 126,22 125,13 @@
      :binding (string binding)})

  (match join-expr
    @[(@ 'as) inner-join alias] (construct-join [binding inner-join] alias)
    @[(@ 'as) inner-join alias] (make-join [binding inner-join] alias)
    @[tab on-expr] (do-construct {:table tab :on on-expr})
    join (do-construct join)))

(defn- construct-joins
  [joins]
  (->> joins
       (partition 2)
       (map construct-join)))

(defn- construct-selects
  [selects]
  (map make-select selects))

(defn- dsl-to-query
  [forms]

  (def joins @[])
  (def wheres @[])
  (var selects @[])


@@ 149,9 139,10 @@

  # Define handlers for each form type. Since the same form can appear more
  # than once, these are subprocedures which can be re-called as necessary.

  (defn handle-joins
    [rest]
    (let [new-joins (construct-joins rest)]
    (let [new-joins (->> rest (partition 2) (map make-join))]
      (array/concat joins new-joins)))

  (defn handle-wheres


@@ 161,15 152,17 @@

  (defn handle-selects
    [rest]
    (if (not (empty? selects))
    (when (not (empty? selects))
      (errorf "Cannot specify multiple `select`s; already selecting %q" selects))
    (let [new-selects (construct-selects rest)]

    (let [new-selects (map make-select rest)]
      (set selects new-selects)))

  (defn handle-limit
    [rest]
    (if (not (nil? limit))
    (when (not (nil? limit))
      (errorf "Cannot specify multiple `limit`s; already limiting to %q" limit))

    (set limit (first rest)))

  (each form forms