mirror of
https://github.com/logseq/logseq.git
synced 2026-04-28 16:15:21 +00:00
Introduce rules to query-dsl
Fixes #4217 as each use of page-property have unique bindings that don't clobber each other
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
[frontend.db.model :as model]
|
||||
[frontend.db.query-react :as react]
|
||||
[frontend.db.utils :as db-utils]
|
||||
[frontend.db.rules :as rules]
|
||||
[frontend.template :as template]
|
||||
[frontend.text :as text]
|
||||
[frontend.util :as util]
|
||||
@@ -50,8 +51,10 @@
|
||||
(when where
|
||||
(let [q (if blocks? ; FIXME: it doesn't need to be either blocks or pages
|
||||
`[:find (~'pull ~'?b ~model/block-attrs)
|
||||
:in ~'$ ~'%
|
||||
:where]
|
||||
'[:find (pull ?p [*])
|
||||
:in $ %
|
||||
:where])
|
||||
result (if (coll? (first where))
|
||||
(apply conj q where)
|
||||
@@ -156,16 +159,6 @@
|
||||
;; For integer pages that aren't strings
|
||||
[(list 'contains? sym (str v))])]))
|
||||
|
||||
(defn ->page-property-query
|
||||
[k v]
|
||||
[['?p :block/name]
|
||||
['?p :block/properties '?prop]
|
||||
[(list 'get '?prop (keyword k)) '?v]
|
||||
(list
|
||||
'or
|
||||
[(list '= '?v v)]
|
||||
[(list 'contains? '?v v)])])
|
||||
|
||||
(defn- build-query-property-two-arg
|
||||
[e current-filter counter]
|
||||
(let [k (string/replace (name (nth e 1)) "_" "-")
|
||||
@@ -183,15 +176,17 @@
|
||||
[fe clauses current-filter nested-and?]
|
||||
(cond
|
||||
(= fe 'not)
|
||||
(let [clauses (if (coll? (first clauses))
|
||||
(apply concat clauses)
|
||||
clauses)
|
||||
clauses (if (and (= 1 (count clauses))
|
||||
(= 'and (ffirst clauses)))
|
||||
;; unflatten
|
||||
(rest (first clauses))
|
||||
clauses)]
|
||||
(cons fe (seq clauses)))
|
||||
(if (every? list? clauses)
|
||||
(cons fe (seq clauses))
|
||||
(let [clauses (if (coll? (first clauses))
|
||||
(apply concat clauses)
|
||||
clauses)
|
||||
clauses (if (and (= 1 (count clauses))
|
||||
(= 'and (ffirst clauses)))
|
||||
;; unflatten
|
||||
(rest (first clauses))
|
||||
clauses)]
|
||||
(cons fe (seq clauses))))
|
||||
|
||||
(coll? (first clauses))
|
||||
(cond
|
||||
@@ -205,10 +200,12 @@
|
||||
|
||||
:else
|
||||
(->> (map (fn [result]
|
||||
(let [result (if (vector? (ffirst result))
|
||||
(apply concat result)
|
||||
result)]
|
||||
(cons 'and (seq result)))) clauses)
|
||||
(if (list? result)
|
||||
result
|
||||
(let [result (if (vector? (ffirst result))
|
||||
(apply concat result)
|
||||
result)]
|
||||
(cons 'and (seq result))))) clauses)
|
||||
(apply list fe)))
|
||||
|
||||
:else
|
||||
@@ -218,35 +215,41 @@
|
||||
|
||||
(defn- build-query-and-or-not
|
||||
[repo e {:keys [current-filter vars] :as env} level fe]
|
||||
(let [clauses (->> (map (fn [form]
|
||||
(build-query repo form (assoc env :current-filter fe) (inc level)))
|
||||
(rest e))
|
||||
(let [raw-clauses (map (fn [form]
|
||||
(build-query repo form (assoc env :current-filter fe) (inc level)))
|
||||
(rest e))
|
||||
clauses (->> raw-clauses
|
||||
(map :query)
|
||||
remove-nil?
|
||||
(distinct))
|
||||
nested-and? (and (= fe 'and) (= current-filter 'and))]
|
||||
(when (seq clauses)
|
||||
(let [result (build-query-and-or-not-result
|
||||
fe clauses current-filter nested-and?)
|
||||
vars' (set/union (set @vars) (collect-vars result))]
|
||||
vars' (set/union (set @vars) (collect-vars result))
|
||||
query (cond
|
||||
;; TODO: more thoughts
|
||||
(and (= current-filter 'and)
|
||||
(= 'or fe)
|
||||
(= #{'?b} vars'))
|
||||
[(concat result [['?b]])]
|
||||
|
||||
nested-and?
|
||||
result
|
||||
|
||||
(and (zero? level) (= 'and fe))
|
||||
(if (list? (first clauses))
|
||||
result
|
||||
(distinct (apply concat clauses)))
|
||||
|
||||
(and (zero? level) (= 'or fe))
|
||||
result
|
||||
|
||||
:else
|
||||
[result])]
|
||||
(reset! vars vars')
|
||||
(cond
|
||||
;; TODO: more thoughts
|
||||
(and (= current-filter 'and)
|
||||
(= 'or fe)
|
||||
(= #{'?b} vars'))
|
||||
[(concat result [['?b]])]
|
||||
|
||||
nested-and?
|
||||
result
|
||||
|
||||
(and (zero? level) (= 'and fe))
|
||||
(distinct (apply concat clauses))
|
||||
|
||||
(and (zero? level) (= 'or fe))
|
||||
result
|
||||
|
||||
:else
|
||||
[result])))))
|
||||
{:query query
|
||||
:rules (distinct (mapcat :rules raw-clauses))}))))
|
||||
|
||||
(defn- build-query-between-two-arg
|
||||
[e]
|
||||
@@ -291,14 +294,13 @@
|
||||
[e]
|
||||
(let [[k v] (rest e)
|
||||
k (string/replace (name k) "_" "-")]
|
||||
(if-not (nil? v)
|
||||
(let [v (text/parse-property k v)
|
||||
v (if (coll? v) (first v) v)]
|
||||
(->page-property-query k v))
|
||||
[['?p :block/name]
|
||||
['?p :block/properties '?prop]
|
||||
[(list 'get '?prop (keyword k)) '?prop-v]
|
||||
[true]])))
|
||||
(if (some? v)
|
||||
(let [v' (text/parse-property k v)
|
||||
val (if (coll? v') (first v') v')]
|
||||
{:query (list 'page-property '?p (keyword k) val)
|
||||
:rules [:page-property]})
|
||||
{:query (list 'has-page-property '?p (keyword k))
|
||||
:rules [:has-page-property]})))
|
||||
|
||||
(defn- build-query-page-tags
|
||||
[e counter]
|
||||
@@ -333,20 +335,21 @@
|
||||
page-ref?
|
||||
(let [page-name (-> (text/page-ref-un-brackets! e)
|
||||
(util/page-name-sanity-lc))]
|
||||
[['?b :block/path-refs [:block/name page-name]]])
|
||||
{:query [['?b :block/path-refs [:block/name page-name]]]})
|
||||
|
||||
(string? e) ; block content full-text search, could be slow
|
||||
(do
|
||||
(reset! blocks? true)
|
||||
[['?b :block/content '?content]
|
||||
[(list 'clojure.string/includes? '?content e)]])
|
||||
{:query
|
||||
[['?b :block/content '?content]
|
||||
[(list 'clojure.string/includes? '?content e)]]})
|
||||
|
||||
(contains? #{'and 'or 'not} fe)
|
||||
(build-query-and-or-not repo e env level fe)
|
||||
|
||||
(and (= 'between fe)
|
||||
(= 3 (count e)))
|
||||
(build-query-between-two-arg e)
|
||||
{:query (build-query-between-two-arg e)}
|
||||
|
||||
;; (between created_at -1d today)
|
||||
(and (= 'between fe)
|
||||
@@ -361,24 +364,24 @@
|
||||
(when (and start end)
|
||||
(let [[start end] (sort [start end])
|
||||
sym '?v]
|
||||
[['?b :block/properties '?prop]
|
||||
[(list 'get '?prop k) sym]
|
||||
[(list '>= sym start)]
|
||||
[(list '< sym end)]])))))
|
||||
{:query [['?b :block/properties '?prop]
|
||||
[(list 'get '?prop k) sym]
|
||||
[(list '>= sym start)]
|
||||
[(list '< sym end)]]})))))
|
||||
|
||||
(and (= 'property fe)
|
||||
(= 3 (count e)))
|
||||
(build-query-property-two-arg e current-filter counter)
|
||||
{:query (build-query-property-two-arg e current-filter counter)}
|
||||
|
||||
(and (= 'property fe)
|
||||
(= 2 (count e)))
|
||||
(build-query-property-one-arg e)
|
||||
{:query (build-query-property-one-arg e)}
|
||||
|
||||
(or (= 'todo fe) (= 'task fe))
|
||||
(build-query-todo e)
|
||||
{:query (build-query-todo e)}
|
||||
|
||||
(= 'priority fe)
|
||||
(build-query-priority e)
|
||||
{:query (build-query-priority e)}
|
||||
|
||||
(= 'sort-by fe)
|
||||
(let [[k order] (rest e)
|
||||
@@ -408,24 +411,24 @@
|
||||
(= 'page fe)
|
||||
(let [page-name (text/page-ref-un-brackets! (str (first (rest e))))
|
||||
page-name (util/page-name-sanity-lc page-name)]
|
||||
[['?b :block/page [:block/name page-name]]])
|
||||
{:query [['?b :block/page [:block/name page-name]]]})
|
||||
|
||||
(and (= 'namespace fe)
|
||||
(= 2 (count e)))
|
||||
(let [page-name (text/page-ref-un-brackets! (str (first (rest e))))
|
||||
page (util/page-name-sanity-lc page-name)]
|
||||
(when-not (string/blank? page)
|
||||
[['?p :block/namespace '?parent]
|
||||
['?parent :block/name page]]))
|
||||
{:query [['?p :block/namespace '?parent]
|
||||
['?parent :block/name page]]}))
|
||||
|
||||
(= 'page-property fe)
|
||||
(build-page-property e)
|
||||
|
||||
(= 'page-tags fe)
|
||||
(build-query-page-tags e counter)
|
||||
{:query (build-query-page-tags e counter)}
|
||||
|
||||
(= 'all-page-tags fe)
|
||||
[['?e :block/tags '?p]]
|
||||
{:query [['?e :block/tags '?p]]}
|
||||
|
||||
(= 'sample fe)
|
||||
(when-let [num (second e)]
|
||||
@@ -505,10 +508,11 @@
|
||||
(let [sort-by (atom nil)
|
||||
blocks? (atom nil)
|
||||
sample (atom nil)
|
||||
result (when form (build-query repo form {:sort-by sort-by
|
||||
:blocks? blocks?
|
||||
:counter counter
|
||||
:sample sample}))]
|
||||
{result :query rules :rules}
|
||||
(when form (build-query repo form {:sort-by sort-by
|
||||
:blocks? blocks?
|
||||
:counter counter
|
||||
:sample sample}))]
|
||||
(cond
|
||||
(and (nil? result) (string? form))
|
||||
form
|
||||
@@ -528,6 +532,7 @@
|
||||
result)]
|
||||
(add-bindings! form result)))]
|
||||
{:query result
|
||||
:rules (mapv rules/query-dsl-rules rules)
|
||||
:sort-by @sort-by
|
||||
:blocks? (boolean @blocks?)
|
||||
:sample sample})))))
|
||||
@@ -541,7 +546,7 @@
|
||||
(when (string? query-string)
|
||||
(let [query-string (template/resolve-dynamic-template! query-string)]
|
||||
(when-not (string/blank? query-string)
|
||||
(let [{:keys [query sort-by blocks? sample] :as result} (parse repo query-string)
|
||||
(let [{:keys [query rules sort-by blocks? sample] :as result} (parse repo query-string)
|
||||
query (if (string? query) (string/trim query) query)
|
||||
full-text-query? (and (string? result)
|
||||
(not (string/includes? result " ")))]
|
||||
@@ -558,6 +563,7 @@
|
||||
transform-fn (comp sort-by random-samples)]
|
||||
(react/react-query repo
|
||||
{:query query
|
||||
:rules rules
|
||||
:query-string query-string}
|
||||
{:use-cache? false
|
||||
:transform-fn transform-fn}))))))))))
|
||||
|
||||
Reference in New Issue
Block a user