From ced0c79490865f673b413f10d4de78ce00051908 Mon Sep 17 00:00:00 2001 From: Chris Smothers Date: Tue, 15 Dec 2020 19:02:21 -0500 Subject: [PATCH] fix(query): bools and combined queries (#43) - fix queries on boolean attributes - allow queries on multiple attributes of an entity --- src/homebase/js.cljs | 22 +++++++++++++--------- src/homebase/js_test.cljs | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/homebase/js.cljs b/src/homebase/js.cljs index 4e4e8621..806c4805 100644 --- a/src/homebase/js.cljs +++ b/src/homebase/js.cljs @@ -105,14 +105,17 @@ (defn js->datalog [data] (let [{find "$find" where "$where"} (js->clj data)] {:find [(symbol (str "?" find))] - :where (mapv - (fn build-where-clause [[e av]] - (let [[[a v]] (seq av) - pred [(symbol (str "?" e)) - (keyword e a)]] - (if (= v "$any") pred - (into pred [v])))) - where)})) + :where (reduce-kv + (fn [acc nmspc attrs+values] + (into acc + (reduce-kv + (fn [acc a v] + (conj acc + (let [pred [(symbol (str "?" nmspc)) (js->key nmspc a)]] + (if (= v "$any") pred + (into pred [v]))))) + [] attrs+values))) + [] where)})) (comment (= @@ -327,7 +330,8 @@ For example: query({ (str "Expected to see '" var "' in both the $find and $where clauses." (example-js-query var))) - #"((?! is not ISeqable).+) is not ISeqable" + ;; #"((?! is not ISeqable).+) is not ISeqable" + #"No protocol method IKVReduce.-kv-reduce defined for type .*: (.*)" :>> (fn [[_ v]] (str "Expected $where clause to be a nested object, not " v "." (example-js-query))) diff --git a/src/homebase/js_test.cljs b/src/homebase/js_test.cljs index 4ce8ce84..609346e7 100644 --- a/src/homebase/js_test.cljs +++ b/src/homebase/js_test.cljs @@ -8,7 +8,12 @@ (d/conn-from-db (d/init-db #{(d/datom 3 :todo/project 2) - (d/datom 2 :project/name "abc")} + (d/datom 2 :project/name "abc") + (d/datom 4 :project/name "xyz") + (d/datom 4 :project/number 23) + (d/datom 4 :project/completed? true) + (d/datom 5 :project/name "abc") + (d/datom 6 :project/name "p4")} {:todo/project {:db/valueType :db.type/ref :db/cardinality :db.cardinality/one}}))) @@ -110,6 +115,29 @@ "$where" {"item" {"name" "$any"}}}) (d/create-conn)))) (is (array? (hbjs/q (clj->js "[:find ?e :where [?e :item/name]]") (d/create-conn))))) + (testing "$any" + (is (= 4 (count (hbjs/q (clj->js {"$find" "project" + "$where" {"project" {"name" "$any"}}}) + test-conn))))) + (testing "filter by string" + (is (= 2 (count (hbjs/q (clj->js {"$find" "project" + "$where" {"project" {"name" "abc"}}}) + test-conn))))) + (testing "filter by bool" + (is (= 1 (count (hbjs/q (clj->js {"$find" "project" + "$where" {"project" {"isCompleted" true}}}) + test-conn))))) + (testing "filter by number" + (is (= 1 (count (hbjs/q (clj->js {"$find" "project" + "$where" {"project" {"number" 23}}}) + test-conn))))) + (testing "filter by multiple" + (is (= 1 (count (hbjs/q (clj->js {"$find" "project" + "$where" {"project" {"number" 23 "isCompleted" true}}}) + test-conn)))) + (is (= 0 (count (hbjs/q (clj->js {"$find" "project" + "$where" {"project" {"number" 23 "isCompleted" false}}}) + test-conn))))) (testing "should fail with humanized errors" (is (thrown-with-msg? js/Error @@ -145,6 +173,11 @@ #"(?s)Expected \$where clause to be a nested object, not 1.*For example:" (hbjs/q (clj->js {"$find" "todo" "$where" {"todo" 1}}) (d/create-conn)))) + (is (thrown-with-msg? + js/Error + #"(?s)Expected \$where clause to be a nested object, not yolo.*For example:" + (hbjs/q (clj->js {"$find" "todo" + "$where" {"todo" "yolo"}}) (d/create-conn)))) (is (thrown-with-msg? js/Error #"(?s)Cannot parse :find, expected: \(find-rel \| find-coll \| find-tuple \| find-scalar\)"