浏览代码

Fix property rules for advanced queries with db graphs

and provide a rules var just for db graphs.
Also simplify query-dsl db-graph support as query-dsl/parse-query
doesn't need to know about db graphs for how it's used
Gabriel Horner 2 年之前
父节点
当前提交
e9fecfa280

+ 5 - 5
deps/db/bb.edn

@@ -27,11 +27,11 @@
               [logseq.db.rules :as rules])
    :doc "Lint datalog rules for parsability and unbound variables"
    :task (datalog/lint-rules
-          (into (mapcat val rules/rules)
-                (-> rules/query-dsl-rules
-                    ;; TODO: Update linter to handle false positive on ?str-val
-                    (dissoc :property :property-db-version)
-                    vals)))}}
+          (set
+           (concat (mapcat val rules/rules)
+                  ;; TODO: Update linter to handle false positive on ?str-val for :property
+                   (-> rules/query-dsl-rules (dissoc :property) vals)
+                   (-> rules/db-query-dsl-rules (dissoc :property) vals))))}}
 
  :tasks/config
  {:large-vars

+ 1 - 1
deps/db/script/query.cljs

@@ -29,7 +29,7 @@
   (let [[graph-name query*] args
         conn (read-graph graph-name)
         query (into (edn/read-string query*) [:in '$ '%]) ;; assumes no :in are in queries
-        results (mapv first (apply d/q query @conn [(vals rules/query-dsl-rules)]))]
+        results (mapv first (apply d/q query @conn [(vals rules/db-query-dsl-rules)]))]
     (println "DB contains" (count (d/datoms @conn :eavt)) "datoms")
     (prn results)))
 

+ 35 - 31
deps/db/src/logseq/db/rules.cljc

@@ -61,9 +61,9 @@
 ;;                      [?e ?a ?v]))]
 
 (def ^:large-vars/data-var query-dsl-rules
-  "Rules used by frontend.db.query-dsl. The symbols ?b and ?p respectively refer
-  to block and page. Do not alter them as they are programmatically built by the
-  query-dsl ns"
+  "Rules used by frontend.db.query-dsl for file graphs. The symbols ?b and ?p
+  respectively refer to block and page. Do not alter them as they are
+  programmatically built by the query-dsl ns"
   {:page-property
    '[(page-property ?p ?key ?val)
      [?p :block/name]
@@ -111,16 +111,6 @@
      [(missing? $ ?b :block/name)]
      [(get ?bp ?prop)]]
 
-   :has-property-db-version
-   '[(has-property ?b ?prop)
-     [?b :block/properties ?bp]
-     [(missing? $ ?b :block/name)]
-     [(name ?prop) ?prop-name-str]
-     [?prop-b :block/name ?prop-name-str]
-     [?prop-b :block/type "property"]
-     [?prop-b :block/uuid ?prop-uuid]
-     [(get ?bp ?prop-uuid)]]
-
    :block-content
    '[(block-content ?b ?query)
      [?b :block/content ?content]
@@ -147,25 +137,39 @@
          ;; For integer pages that aren't strings
          [(contains? ?v ?str-val)])]
 
-   :property-db-version
-   '[(property ?b ?key ?val)
-     [?b :block/properties ?prop]
-     [(missing? $ ?b :block/name)]
-     [(name ?key) ?key-str]
-     [?prop-b :block/name ?key-str]
-     [?prop-b :block/type "property"]
-     [?prop-b :block/uuid ?prop-uuid]
-     [(get ?prop ?prop-uuid) ?v]
-     ;; TODO: Need to find a more performant way to do this
-     (or-join [?v]
-              [(= ?v ?val)]
-              (and [(str ?val) ?str-val]
-                    ;; str-val is for integer pages that aren't strings
-                   [?prop-val-b :block/original-name ?str-val]
-                   [?prop-val-b :block/uuid ?val-uuid]
-                   [(contains? ?v ?val-uuid)]))]
-
    :page-ref
    '[(page-ref ?b ?page-name)
      [?b :block/path-refs ?br]
      [?br :block/name ?page-name]]})
+
+(def db-query-dsl-rules
+  "Rules used by frontend.query.dsl for db graphs"
+  (merge
+   query-dsl-rules
+   {:has-property
+    '[(has-property ?b ?prop)
+      [?b :block/properties ?bp]
+      [(missing? $ ?b :block/name)]
+      [(name ?prop) ?prop-name-str]
+      [?prop-b :block/name ?prop-name-str]
+      [?prop-b :block/type "property"]
+      [?prop-b :block/uuid ?prop-uuid]
+      [(get ?bp ?prop-uuid)]]
+
+    :property
+    '[(property ?b ?key ?val)
+      [?b :block/properties ?prop]
+      [(missing? $ ?b :block/name)]
+      [(name ?key) ?key-str]
+      [?prop-b :block/name ?key-str]
+      [?prop-b :block/type "property"]
+      [?prop-b :block/uuid ?prop-uuid]
+      [(get ?prop ?prop-uuid) ?v]
+     ;; TODO: Need to find a more performant way to do this
+      (or-join [?v]
+               [(= ?v ?val)]
+               (and [(str ?val) ?str-val]
+                    ;; str-val is for integer pages that aren't strings
+                    [?prop-val-b :block/original-name ?str-val]
+                    [?prop-val-b :block/uuid ?val-uuid]
+                    [(contains? ?v ?val-uuid)]))]}))

+ 2 - 4
src/main/frontend/components/query.cljs

@@ -14,8 +14,7 @@
             [frontend.extensions.sci :as sci]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.editor.property :as editor-property]
-            [logseq.graph-parser.util :as gp-util]
-            [frontend.config :as config]))
+            [logseq.graph-parser.util :as gp-util]))
 
 (defn built-in-custom-query?
   [title]
@@ -164,8 +163,7 @@
         view-fn (if (keyword? view) (get-in (state/sub-config) [:query/views view]) view)
         view-f (and view-fn (sci/eval-string (pr-str view-fn)))
         dsl-page-query? (and dsl-query?
-                             (false? (:blocks? (query-dsl/parse-query
-                                                query (config/db-based-graph? (state/get-current-repo))))))
+                             (false? (:blocks? (query-dsl/parse-query query))))
         ;; FIXME: This isn't getting set for full-text searches
         full-text-search? (and dsl-query?
                                (util/electron?)

+ 2 - 4
src/main/frontend/components/query/builder.cljs

@@ -16,8 +16,7 @@
             [rum.core :as rum]
             [clojure.string :as string]
             [logseq.graph-parser.util :as gp-util]
-            [logseq.graph-parser.util.page-ref :as page-ref]
-            [frontend.config :as config]))
+            [logseq.graph-parser.util.page-ref :as page-ref]))
 
 (rum/defc page-block-selector
   [*find]
@@ -456,8 +455,7 @@
              (assoc state ::tree *tree)))
    :will-mount (fn [state]
                  (let [q-str (first (:rum/args state))
-                       parsed-query (query-dsl/parse-query q-str (config/db-based-graph? (state/get-current-repo)))
-                       blocks-query? (:blocks? parsed-query)
+                       blocks-query? (:blocks? (query-dsl/parse-query q-str))
                        find-mode (cond
                                    blocks-query?
                                    :block

+ 10 - 6
src/main/frontend/db/query_custom.cljs

@@ -6,7 +6,8 @@
             [frontend.db.model :as model]
             [logseq.db.rules :as rules]
             [frontend.util.datalog :as datalog-util]
-            [clojure.walk :as walk]))
+            [clojure.walk :as walk]
+            [frontend.config :as config]))
 
 ;; FIXME: what if users want to query other attributes than block-attrs?
 (defn- replace-star-with-block-attrs!
@@ -24,9 +25,10 @@
 
 (defn- add-rules-to-query
   "Searches query's :where for rules and adds them to query if used"
-  [{:keys [query] :as query-m}]
+  [{:keys [query] :as query-m} {:keys [db-graph?]}]
   (let [{:keys [where in]} (datalog-util/query-vec->map query)
-        rules-found (datalog-util/find-rules-in-where where (-> rules/query-dsl-rules keys set))]
+        query-dsl-rules (if db-graph? rules/db-query-dsl-rules rules/query-dsl-rules)
+        rules-found (datalog-util/find-rules-in-where where (-> query-dsl-rules keys set))]
     (if (seq rules-found)
       (if (and (= '% (last in)) (vector? (last (:inputs query-m))))
         ;; Add to existing :inputs rules
@@ -36,7 +38,7 @@
                   (assoc (vec inputs)
                          ;; last position is rules
                          (dec (count inputs))
-                         (->> (mapv rules/query-dsl-rules rules-found)
+                         (->> (mapv query-dsl-rules rules-found)
                               (into (last inputs))
                               ;; user could give rules that we already have
                               distinct
@@ -54,7 +56,7 @@
             (update :rules
                     (fn [rules]
                       (into (or rules [])
-                            (mapv rules/query-dsl-rules rules-found))))))
+                            (mapv query-dsl-rules rules-found))))))
       query-m)))
 
 (defn custom-query
@@ -71,4 +73,6 @@
      (if (or (list? (:query query'))
              (not= :find (first (:query query')))) ; dsl query
        (query-dsl/custom-query repo query' query-opts)
-       (query-react/react-query repo (add-rules-to-query query') query-opts)))))
+       (query-react/react-query repo
+                                (add-rules-to-query query' {:db-graph? (config/db-based-graph? repo)})
+                                query-opts)))))

+ 20 - 18
src/main/frontend/db/query_dsl.cljs

@@ -253,7 +253,7 @@
       result)))
 
 (defn- build-property-two-arg
-  [e db-version?]
+  [e]
   (let [k (string/replace (name (nth e 1)) "_" "-")
         v (nth e 2)
         v (if-not (nil? v)
@@ -261,21 +261,21 @@
             v)
         v (if (coll? v) (first v) v)]
     {:query (list 'property '?b (keyword k) v)
-     :rules [(if db-version? :property-db-version :property)]}))
+     :rules [:property]}))
 
 (defn- build-property-one-arg
-  [e db-version?]
+  [e]
   (let [k (string/replace (name (nth e 1)) "_" "-")]
     {:query (list 'has-property '?b (keyword k))
-     :rules [(if db-version? :has-property-db-version :has-property)]}))
+     :rules [:has-property]}))
 
-(defn- build-property [e db-version?]
+(defn- build-property [e]
   (cond
     (= 3 (count e))
-    (build-property-two-arg e db-version?)
+    (build-property-two-arg e)
 
     (= 2 (count e))
-    (build-property-one-arg e db-version?)))
+    (build-property-one-arg e)))
 
 (defn- build-task
   [e]
@@ -386,7 +386,7 @@ Some bindings in this fn:
 * fe - the query operator e.g. `property`"
   ([e env]
    (build-query e (assoc env :vars (atom {})) 0))
-  ([e {:keys [sort-by blocks? sample db-version?] :as env :or {blocks? (atom nil)}} level]
+  ([e {:keys [sort-by blocks? sample] :as env :or {blocks? (atom nil)}} level]
    ; {:post [(or (nil? %) (map? %))]}
    (let [fe (first e)
          fe (when fe (symbol (string/lower-case (name fe))))
@@ -413,7 +413,7 @@ Some bindings in this fn:
        (build-between e)
 
        (= 'property fe)
-       (build-property e db-version?)
+       (build-property e)
 
        ;; task is the new name and todo is the old one
        (or (= 'todo fe) (= 'task fe))
@@ -530,7 +530,7 @@ Some bindings in this fn:
 
 (def custom-readers {:readers {'tag (fn [x] (page-ref/->page-ref x))}})
 (defn parse
-  [s db-version?]
+  [s {:keys [db-graph?]}]
   (when (and (string? s)
              (not (string/blank? s)))
     (let [s (if (= \# (first s)) (page-ref/->page-ref (subs s 1)) s)
@@ -544,8 +544,7 @@ Some bindings in this fn:
           {result :query rules :rules}
           (when form (build-query form {:sort-by sort-by
                                         :blocks? blocks?
-                                        :sample sample
-                                        :db-version? db-version?}))
+                                        :sample sample}))
           result' (when (seq result)
                     (let [key (if (coll? (first result))
                                 ;; Only queries for this branch are not's like:
@@ -555,7 +554,9 @@ Some bindings in this fn:
                       (add-bindings! form
                                      (if (= key :and) (rest result) result))))]
       {:query result'
-       :rules (mapv rules/query-dsl-rules rules)
+       :rules (if db-graph?
+                (mapv rules/db-query-dsl-rules rules)
+                (mapv rules/query-dsl-rules rules))
        :sort-by @sort-by
        :blocks? (boolean @blocks?)
        :sample sample})))
@@ -578,9 +579,10 @@ Some bindings in this fn:
       (conj q where))))
 
 (defn parse-query
-  [q db-version?]
-  (let [q' (template/resolve-dynamic-template! q)]
-    (parse q' db-version?)))
+  ([q] (parse-query q {}))
+  ([q options]
+   (let [q' (template/resolve-dynamic-template! q)]
+     (parse q' options))))
 
 (defn pre-transform-query
   [q]
@@ -593,7 +595,7 @@ Some bindings in this fn:
    (query repo query-string {}))
   ([repo query-string query-opts]
    (when (and (string? query-string) (not= "\"\"" query-string))
-     (let [{:keys [query rules sort-by blocks? sample]} (parse-query query-string (config/db-based-graph? repo))]
+     (let [{:keys [query rules sort-by blocks? sample]} (parse-query query-string {:db-graph? (config/db-based-graph? repo)})]
        (when-let [query' (some-> query (query-wrapper {:blocks? blocks?}))]
          (let [sort-by (or sort-by identity)
                random-samples (if @sample
@@ -615,7 +617,7 @@ Some bindings in this fn:
   [repo query-m query-opts]
   (when (seq (:query query-m))
     (let [query-string (template/resolve-dynamic-template! (pr-str (:query query-m)))
-          {:keys [query sort-by blocks? rules]} (parse query-string (config/db-based-graph? repo))]
+          {:keys [query sort-by blocks? rules]} (parse query-string {:db-graph? (config/db-based-graph? repo)})]
       (when-let [query' (some-> query (query-wrapper {:blocks? blocks?}))]
         (query-react/react-query repo
                            (merge

+ 1 - 1
src/main/frontend/extensions/srs.cljs

@@ -270,7 +270,7 @@
                                                    (string/starts-with? query-string "["))
                                          (page-ref/->page-ref (string/trim query-string))
                                          query-string)
-                          {:keys [query sort-by rules]} (query-dsl/parse query-string (config/db-based-graph? repo))
+                          {:keys [query sort-by rules]} (query-dsl/parse query-string {:db-graph? (config/db-based-graph? repo)})
                           query* (util/concat-without-nil
                                   [['?b :block/refs '?br] ['?br :block/name card-hash-tag]]
                                   (if (coll? (first query)) query [query]))]

+ 3 - 3
src/main/frontend/handler/editor.cljs

@@ -3253,7 +3253,7 @@
 
 (defn- valid-dsl-query-block?
   "Whether block has a valid dsl query."
-  [repo block]
+  [block]
   (->> (:block/macros (db/entity (:db/id block)))
        (some (fn [macro]
                (when-let [query-body (and
@@ -3261,7 +3261,7 @@
                                       (first (:logseq.macro-arguments (:block/properties macro))))]
                  (seq (:query
                        (try
-                         (query-dsl/parse-query query-body (config/db-based-graph? repo))
+                         (query-dsl/parse-query query-body)
                          (catch :default _e
                            nil)))))))))
 
@@ -3284,7 +3284,7 @@
    (when block-id
      (if-let [block (db-model/query-block-by-uuid block-id)]
        (or (db-model/has-children? block-id)
-           (valid-dsl-query-block? (state/get-current-repo) block)
+           (valid-dsl-query-block? block)
            (valid-custom-query-block? block)
            (and
             (:outliner/block-title-collapse-enabled? (state/get-config))