query_custom.cljs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. (ns frontend.db.query-custom
  2. "Handles executing custom queries a.k.a. advanced queries"
  3. (:require [frontend.state :as state]
  4. [frontend.db.query-react :as query-react]
  5. [frontend.db.query-dsl :as query-dsl]
  6. [frontend.db.model :as model]
  7. [frontend.db.rules :as rules]
  8. [frontend.util.datalog :as datalog-util]
  9. [clojure.walk :as walk]))
  10. ;; FIXME: what if users want to query other attributes than block-attrs?
  11. (defn- replace-star-with-block-attrs!
  12. [l]
  13. (walk/postwalk
  14. (fn [f]
  15. (if (and (list? f)
  16. (= 'pull (first f))
  17. (= '?b (second f))
  18. (= '[*] (nth f 2)))
  19. `(~'pull ~'?b ~model/block-attrs)
  20. f))
  21. l))
  22. (defn- add-rules-to-query
  23. "Searches query's :where for rules and adds them to query if used"
  24. [{:keys [query] :as query-m}]
  25. (let [{:keys [where in]} (datalog-util/query-vec->map query)
  26. rules-found (datalog-util/find-rules-in-where where (-> rules/query-dsl-rules keys set))]
  27. (if (seq rules-found)
  28. (if (= '% (last in))
  29. ;; Add to existing :inputs rules
  30. (update query-m
  31. :inputs
  32. (fn [inputs]
  33. (assoc (vec inputs)
  34. ;; last position is rules
  35. (dec (count inputs))
  36. (->> (mapv rules/query-dsl-rules rules-found)
  37. (into (last inputs))
  38. ;; user could give rules that we already have
  39. distinct
  40. vec))))
  41. ;; Add new rules
  42. (-> query-m
  43. (update :query
  44. (fn [q]
  45. (if (contains? (set q) :in)
  46. (datalog-util/add-to-end-of-query-section q :in ['%])
  47. (into q [:in '$ '%]))))
  48. (assoc :rules (mapv rules/query-dsl-rules rules-found))))
  49. query-m)))
  50. (defn custom-query
  51. "Executes a datalog query through query-react, given either a regular datalog
  52. query or a simple query"
  53. ([query]
  54. (custom-query query {}))
  55. ([query query-opts]
  56. (custom-query (state/get-current-repo) query query-opts))
  57. ([repo query query-opts]
  58. (let [query' (replace-star-with-block-attrs! query)]
  59. (if (or (list? (:query query'))
  60. (not= :find (first (:query query')))) ; dsl query
  61. (query-dsl/custom-query repo query' query-opts)
  62. (query-react/react-query repo (add-rules-to-query query') query-opts)))))