|
1631 | 1631 | (instance? ArrayBinaryExpression node) |
1632 | 1632 | (instance? ArrayRegexExpression node))) |
1633 | 1633 |
|
1634 | | -(defn path->nested-map |
1635 | | - "Given path [a b c] and value d, produce {a {b {c d}}}" |
1636 | | - [path value] |
1637 | | - (reduce #(hash-map (parse/maybe-strip-escaped-quotes %2) %1) |
1638 | | - (rseq (conj (vec path) value)))) |
1639 | | - |
1640 | 1634 | (defn parse-dot-query |
1641 | 1635 | "Transforms a dotted query into a JSON structure appropriate |
1642 | 1636 | for comparison in the database." |
1643 | 1637 | [{:keys [field value] :as node} state] |
1644 | | - (let [[column & path] (map parse/maybe-strip-escaped-quotes |
1645 | | - (parse/dotted-query->path field))] |
1646 | | - (if (some #(re-matches #"^\d+$" %) path) |
1647 | | - ;; This path is taken for match() operators that match indexes, |
1648 | | - ;; i.e. facts.foo.match("\d+") because by this point they'll be |
1649 | | - ;; plain integer path components. |
1650 | | - {:node (assoc node :value ["?" "?"] :field column :array-in-path true) |
1651 | | - ;; https://www.postgresql.org/docs/11/arrays.html#ARRAYS-INPUT |
1652 | | - :state (reduce conj state [(jdbc/strs->db-array path) |
| 1638 | + ;; node is JsonContainsExpression |
| 1639 | + (let [[column & path] (parse/parse-field field 0 {:indexes? false |
| 1640 | + :matches? false}) |
| 1641 | + ;; FIXME: this is a conflation - one fix might be to parse all |
| 1642 | + ;; fields *once* at the start of query processing, and then |
| 1643 | + ;; pass that representation all the way through. |
| 1644 | + ;; |
| 1645 | + ;; The handling of match() wrt fact_paths complicates that |
| 1646 | + ;; because right now we don't have any (efficient) way of |
| 1647 | + ;; knowing all the types of the path elements we retrieve from |
| 1648 | + ;; the path_array, i.e. for ["foo" "5" "bar"], is "5" a custom |
| 1649 | + ;; fact name, or an array lookup? The situation could be |
| 1650 | + ;; different if we pushed the path lookups further down, and |
| 1651 | + ;; didn't insinuate them via AST. At the moment, we preserve |
| 1652 | + ;; backward compatibility by just treating everything as a |
| 1653 | + ;; named field by setting indexes? and matches? above. |
| 1654 | + maybe-index? #(re-matches #"[0-9]+" (:name %))] |
| 1655 | + (if (some maybe-index? path) |
| 1656 | + ;; If this matches, then the path component might be an array |
| 1657 | + ;; access, e.g. via the database-generated paths created by |
| 1658 | + ;; maybe-add-match-function-filter like foo.5.bar, and so we |
| 1659 | + ;; have to be conservative and set array-in-path so that we'll |
| 1660 | + ;; eventually use the right json operators (e.g. #> instead of |
| 1661 | + ;; @>). |
| 1662 | + {:node (assoc node |
| 1663 | + :value ["?" "?"] |
| 1664 | + :field (:name column) |
| 1665 | + :array-in-path true) |
| 1666 | + :state (reduce conj state [(jdbc/strs->db-array (map :name path)) |
1653 | 1667 | (su/munge-jsonb-for-storage value)])} |
1654 | | - {:node (assoc node :value "?" :field column :array-in-path false) |
1655 | | - :state (conj state (su/munge-jsonb-for-storage |
1656 | | - (path->nested-map path value)))}))) |
| 1668 | + {:node (assoc node |
| 1669 | + :value "?" |
| 1670 | + :field (:name column) |
| 1671 | + :array-in-path false) |
| 1672 | + :state (conj state |
| 1673 | + (su/munge-jsonb-for-storage |
| 1674 | + ;; Convert path [a b c] and value d to {a {b {c d}}} |
| 1675 | + (reduce (fn [result name] (hash-map name result)) |
| 1676 | + (cons value (reverse (map :name path))))))}))) |
1657 | 1677 |
|
1658 | 1678 | (defn parse-dot-query-with-array-elements |
1659 | 1679 | "Transforms a dotted query into a JSON structure appropriate |
|
0 commit comments