query_custom.cljs 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. [logseq.db.frontend.rules :as rules]
  8. [frontend.util.datalog :as datalog-util]
  9. [clojure.walk :as walk]
  10. [frontend.config :as config]))
  11. ;; FIXME: what if users want to query other attributes than block-attrs?
  12. (defn- replace-star-with-block-attrs!
  13. [l]
  14. (let [block-attrs (butlast model/file-graph-block-attrs)]
  15. (walk/postwalk
  16. (fn [f]
  17. (if (and (list? f)
  18. (= 'pull (first f))
  19. (= '?b (second f))
  20. (= '[*] (nth f 2)))
  21. `(~'pull ~'?b ~block-attrs)
  22. f))
  23. l)))
  24. (defn- add-rules-to-query
  25. "Searches query's :where for rules and adds them to query if used"
  26. [{:keys [query] :as query-m} {:keys [db-graph?]}]
  27. (let [{:keys [where in]} (datalog-util/query-vec->map query)
  28. query-dsl-rules (if db-graph? rules/db-query-dsl-rules rules/query-dsl-rules)
  29. rules-found (datalog-util/find-rules-in-where where (-> query-dsl-rules keys set))]
  30. (if (seq rules-found)
  31. (if (and (= '% (last in)) (vector? (last (:inputs query-m))))
  32. ;; Add to existing :inputs rules
  33. (update query-m
  34. :inputs
  35. (fn [inputs]
  36. (assoc (vec inputs)
  37. ;; last position is rules
  38. (dec (count inputs))
  39. (->> (rules/extract-rules query-dsl-rules
  40. rules-found
  41. (when db-graph?
  42. {:deps rules/rules-dependencies}))
  43. (into (last inputs))
  44. ;; user could give rules that we already have
  45. distinct
  46. vec))))
  47. ;; Add new rules
  48. (-> query-m
  49. (update :query
  50. (fn [q]
  51. (if (contains? (set q) :in)
  52. ;; only add '% if not already present
  53. (if (not (contains? (set q) '%))
  54. (datalog-util/add-to-end-of-query-section q :in ['%])
  55. q)
  56. (into q [:in '$ '%]))))
  57. (update :rules
  58. (fn [rules]
  59. (into (or rules [])
  60. (rules/extract-rules query-dsl-rules
  61. rules-found
  62. (when db-graph?
  63. {:deps rules/rules-dependencies})))))))
  64. query-m)))
  65. (defn custom-query
  66. "Executes a datalog query through query-react, given either a regular datalog
  67. query or a simple query"
  68. ([query]
  69. (custom-query query {}))
  70. ([query query-opts]
  71. (custom-query (state/get-current-repo) query query-opts))
  72. ([repo query query-opts]
  73. (let [db-graph? (config/db-based-graph? repo)
  74. query' (if db-graph? query (replace-star-with-block-attrs! query))
  75. query-opts (if (:query-string query-opts) query-opts
  76. (assoc query-opts :query-string (str query)))]
  77. (if (or (list? (:query query'))
  78. (not= :find (first (:query query')))) ; dsl query
  79. (query-dsl/custom-query repo query' query-opts)
  80. (query-react/react-query repo
  81. (add-rules-to-query query' {:db-graph? db-graph?})
  82. query-opts)))))