From 1939e322382b0d8114615cabec8fc7b5cf3aed2f Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Thu, 1 Feb 2024 17:16:45 -0500 Subject: [PATCH 01/34] Add list specs --- .../com/yetanalytics/flint/spec/triple.cljc | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 358a084..6b3e4fe 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -14,15 +14,15 @@ ;; Just paths banned in ;; - CONSTRUCT +;; Variables (and paths) banned in +;; - DELETE DATA +;; - INSERT DATA + ;; Blank nodes (and paths) banned in ;; - DELETE WHERE ;; - DELETE DATA ;; - DELETE -;; Variables (and paths) banned in -;; - DELETE DATA -;; - INSERT DATA - ;; Subjects (def subj-spec @@ -91,6 +91,37 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/literal ax/literal-spec)) +;; Lists + +;; List entries have the same spec as objects + `:triple/list` + +;; Since lists are constructed out of blank nodes, we do not allow list +;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. + +(declare list-spec) +(declare list-novar-spec) + +(def list-entry-spec + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-spec)) + +(def list-entry-novar-spec + (s/or :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-novar-spec)) + +(def list-spec + (s/coll-of list-entry-spec :kind list?)) + +(def list-novar-spec + (s/coll-of list-entry-novar-spec :kind list?)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Combo Specs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From 3300d2f2d31aaa7403d9f11570eb69a4aac96425 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Thu, 1 Feb 2024 17:38:00 -0500 Subject: [PATCH 02/34] Add new triple/object and triple/list tags --- .../com/yetanalytics/flint/format/triple.cljc | 6 +++++ .../com/yetanalytics/flint/spec/triple.cljc | 22 +++++++++++++------ .../yetanalytics/flint/validate/bnode.cljc | 11 +++++++++- .../yetanalytics/flint/validate/variable.cljc | 7 +++++- .../flint/format/triple_test.cljc | 12 ++++++---- .../flint/format/update_test.cljc | 8 +++---- .../yetanalytics/flint/format/where_test.cljc | 4 ++-- .../yetanalytics/flint/spec/triple_test.cljc | 21 +++++++++++------- .../flint/validate/prefix_test.cljc | 2 +- .../flint/validate/scope_test.cljc | 2 +- 10 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 1c38597..6b8e1cd 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -4,6 +4,12 @@ [com.yetanalytics.flint.format.axiom] [com.yetanalytics.flint.format.path])) +(defmethod f/format-ast-node :triple/object [_ [_ object]] + object) + +(defmethod f/format-ast-node :triple/list [_ [_ list]] + (str "( " (cstr/join " " list) " )")) + (defmethod f/format-ast-node :triple/path [_ [_ path]] path) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 6b3e4fe..fb3e162 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -135,17 +135,25 @@ #?(:clj (defmacro make-obj-spec - [obj-spec] - `(s/or :triple/o (s/coll-of ~obj-spec - :min-count 1 - :kind set? - :into [])))) + ([obj-spec] + `(s/or :triple/o + (s/coll-of (s/or :triple/object ~obj-spec) + :min-count 1 + :kind set? + :into []))) + ([obj-spec obj-list-spec] + `(s/or :triple/o + (s/coll-of (s/or :triple/object ~obj-spec + :triple/list ~obj-list-spec) + :min-count 1 + :kind set? + :into []))))) (def obj-set-spec - (make-obj-spec obj-spec)) + (make-obj-spec obj-spec list-spec)) (def obj-set-novar-spec - (make-obj-spec obj-novar-spec)) + (make-obj-spec obj-novar-spec list-novar-spec)) (def obj-set-noblank-spec (make-obj-spec obj-noblank-spec)) diff --git a/src/main/com/yetanalytics/flint/validate/bnode.cljc b/src/main/com/yetanalytics/flint/validate/bnode.cljc index 757ba42..607016a 100644 --- a/src/main/com/yetanalytics/flint/validate/bnode.cljc +++ b/src/main/com/yetanalytics/flint/validate/bnode.cljc @@ -12,8 +12,17 @@ (-> loc ; [:ax/bnode ...] zip/up ; [:triple/vec ...] ) - :triple/o + :triple/list (-> loc ; [:ax/bnode ...] + zip/up ; [:triple/list ...] + zip/up ; [:triple/o ...] + zip/up ; [:triple/po ...] + zip/up ; [:triple/spo ...] + zip/up ; [:triple/nform ...] + ) + :triple/object + (-> loc ; [:ax/bnode ...] + zip/up ; [:triple/object ...] zip/up ; [:triple/o ...] zip/up ; [:triple/po ...] zip/up ; [:triple/spo ...] diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 94103a1..7debf02 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -95,6 +95,12 @@ ;; Basic Graph Pattern +(defmethod get-scope-vars :triple/object [[_ object]] + (get-scope-vars object)) + +(defmethod get-scope-vars :triple/list [[_ list]] + (mapcat get-scope-vars list)) + (defmethod get-scope-vars :triple/vec [[_ spo]] (mapcat get-scope-vars spo)) @@ -181,4 +187,3 @@ (defmethod get-scope-vars :where/values [[_ [_ values]]] (mapcat get-scope-vars (first values))) - diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index bc1c8e9..0cefb51 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -17,15 +17,19 @@ [:triple/spo [[[:ax/iri ""] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]] [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]]]]] [[:ax/var ?s2] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]] [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]]]]]]]] {:pretty? true}))) (is (= "?s ?p ?o ." (f/format-ast diff --git a/src/test/com/yetanalytics/flint/format/update_test.cljc b/src/test/com/yetanalytics/flint/format/update_test.cljc index 31e6237..0c46b38 100644 --- a/src/test/com/yetanalytics/flint/format/update_test.cljc +++ b/src/test/com/yetanalytics/flint/format/update_test.cljc @@ -57,10 +57,10 @@ [:triple/nform [:triple/spo [[[:ax/var ?i] [:triple/po [[[:ax/var ?j] - [:triple/o [[:ax/var ?k]]]]]]] + [:triple/o [[:triple/object [:ax/var ?k]]]]]]]] [[:ax/var ?s] [:triple/po [[[:ax/var ?p] - [:triple/o [[:ax/var ?o]]]]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]]] [:triple/quads [[:ax/iri ""] [:triple/quad-triples @@ -105,10 +105,10 @@ [:triple/spo [[[:ax/var ?x] [:triple/po [[[:ax/var ?y] - [:triple/o [[:ax/var ?z]]]]]]] + [:triple/o [[:triple/object [:ax/var ?z]]]]]]]] [[:ax/var ?a] [:triple/po [[[:ax/var ?b] - [:triple/o [[:ax/var ?c]]]]]]]]]]]]]]] + [:triple/o [[:triple/object [:ax/var ?c]]]]]]]]]]]]]]]] format-ast)))) (testing "Formatting graph management updates" (testing "- LOAD" diff --git a/src/test/com/yetanalytics/flint/format/where_test.cljc b/src/test/com/yetanalytics/flint/format/where_test.cljc index 9ddd7ce..699a9cb 100644 --- a/src/test/com/yetanalytics/flint/format/where_test.cljc +++ b/src/test/com/yetanalytics/flint/format/where_test.cljc @@ -56,8 +56,8 @@ [:triple/nform [:triple/spo [[[:ax/var ?s2] [:triple/po [[[:ax/var ?p2] - [:triple/o [[:ax/var ?o2a] - [:ax/var ?o2b]]]]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o2a]] + [:triple/object [:ax/var ?o2b]]]]]]]]]]] [:where/special [:where/recurse [:where-sub/where diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index eb4f5af..261a6c2 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -5,21 +5,26 @@ (deftest conform-triple-test (testing "Conforming triples" - (is (= '[:triple/spo [[[:ax/var ?s] - [:triple/po [[[:ax/var ?p] - [:triple/o [[:ax/var ?o]]]]]]]]] + (is (= '[:triple/spo + [[[:ax/var ?s] + [:triple/po [[[:ax/var ?p] + [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]] (s/conform ts/normal-form-spec '{?s {?p #{?o}}}))) (is (= '[:triple/spo [[[:ax/var ?s1] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]] [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]]]]] [[:ax/var ?s2] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]] [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] [:ax/var ?o2]]]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o1]] + [:triple/object [:ax/var ?o2]]]]]]]]]] (s/conform ts/normal-form-spec '{?s1 {?p1 #{?o1 ?o2} ?p2 #{?o1 ?o2}} ?s2 {?p1 #{?o1 ?o2} @@ -35,7 +40,7 @@ [:path/paths [[:path/terminal [:ax/prefix-iri :x/one]] [:path/terminal [:ax/prefix-iri :x/two]]]]]]] - [:triple/o [[:ax/var ?o]]]]]]]]] + [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]] (s/conform ts/normal-form-spec '{?s {(cat :x/one :x/two) #{?o}}}))) (is (= '[[:ax/var ?s] diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index a41a4c1..f2b1c76 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -50,7 +50,7 @@ (is (= [{:iri :baz/Qux :prefix :baz :prefixes {:rdf ""} - :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/nform :triple/spo :triple/po :triple/o :ax/prefix-iri]} + :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/nform :triple/spo :triple/po :triple/o :triple/object :ax/prefix-iri]} {:iri :baz/Quu :prefix :baz :prefixes {:rdf ""} diff --git a/src/test/com/yetanalytics/flint/validate/scope_test.cljc b/src/test/com/yetanalytics/flint/validate/scope_test.cljc index 56ab2f4..d406caa 100644 --- a/src/test/com/yetanalytics/flint/validate/scope_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/scope_test.cljc @@ -45,7 +45,7 @@ [:triple/spo [[[:ax/var ?s] [:triple/po [[[:ax/var ?p] - [:triple/o [[:ax/var ?o]]]]]]]]]]))) + [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]]]))) (is (= '[?x ?y ?z] (vv/get-scope-vars '[:where-sub/where From 016c66393e73f2f2ad80e204e46e3fa0fe9f1dfc Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Thu, 1 Feb 2024 18:01:29 -0500 Subject: [PATCH 03/34] Distinguish spo-list from spo --- .../com/yetanalytics/flint/format/triple.cljc | 8 ++++++- .../com/yetanalytics/flint/spec/triple.cljc | 22 ++++++++++++------- .../yetanalytics/flint/validate/bnode.cljc | 8 ++++++- .../yetanalytics/flint/validate/variable.cljc | 8 +++++++ .../yetanalytics/flint/spec/triple_test.cljc | 1 + 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 6b8e1cd..6b26d19 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -19,7 +19,7 @@ (defmethod f/format-ast-node :triple/nform [_ [_ nform]] nform) -(defmethod f/format-ast-node :triple/spo [{:keys [pretty?]} [_ spo]] +(defn- format-spo-map [spo pretty?] (if pretty? (str (->> spo (map (fn [[s po]] @@ -34,6 +34,12 @@ (cstr/join " . ")) " ."))) +(defmethod f/format-ast-node :triple/spo [{:keys [pretty?]} [_ spo]] + (format-spo-map spo pretty?)) + +(defmethod f/format-ast-node :triple/spo-list [{:keys [pretty?]} [_ spo]] + (format-spo-map spo pretty?)) + (defmethod f/format-ast-node :triple/po [{:keys [pretty?]} [_ po]] (let [join-sep (if pretty? " ;\n" " ; ")] (->> po diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index fb3e162..6a7c38c 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -167,7 +167,6 @@ (defmacro make-pred-objs-spec [pred-spec objs-spec] `(s/or :triple/po (s/map-of ~pred-spec ~objs-spec - :min-count 1 :into [])))) (def pred-objs-spec @@ -189,19 +188,26 @@ #?(:clj (defmacro make-nform-spec - [subj-spec pred-objs-spec] - `(s/or :triple/spo (s/map-of ~subj-spec ~pred-objs-spec - :conform-keys true - :into [])))) + ([subj-spec pred-objs-spec] + `(s/or :triple/spo + (s/map-of ~subj-spec (s/and ~pred-objs-spec not-empty) + :conform-keys true :into []))) + ([subj-spec subj-list-spec pred-objs-spec] + `(s/or :triple/spo + (s/map-of ~subj-spec (s/and ~pred-objs-spec not-empty) + :conform-keys true :into []) + :triple/spo-list + (s/map-of ~subj-list-spec ~pred-objs-spec + :conform-keys true :into []))))) (def normal-form-spec - (make-nform-spec subj-spec pred-objs-spec)) + (make-nform-spec subj-spec list-spec pred-objs-spec)) (def normal-form-nopath-spec - (make-nform-spec subj-spec pred-objs-nopath-spec)) + (make-nform-spec subj-spec list-spec pred-objs-nopath-spec)) (def normal-form-novar-spec - (make-nform-spec subj-novar-spec pred-objs-novar-spec)) + (make-nform-spec subj-novar-spec list-novar-spec pred-objs-novar-spec)) (def normal-form-noblank-spec (make-nform-spec subj-noblank-spec pred-objs-noblank-spec)) diff --git a/src/main/com/yetanalytics/flint/validate/bnode.cljc b/src/main/com/yetanalytics/flint/validate/bnode.cljc index 607016a..cdf4dc5 100644 --- a/src/main/com/yetanalytics/flint/validate/bnode.cljc +++ b/src/main/com/yetanalytics/flint/validate/bnode.cljc @@ -32,7 +32,13 @@ (-> loc ; [:ax/bnode ...] zip/up ; [:triple/spo ...] zip/up ; [:triple/nform ...] - )))) + ) + :triple/spo-list + (-> loc ; [:ax/bnode ...] + zip/up ; [:triple/spo-list ...] + zip/up ; [:triple/nform ...] + ) + ))) (defn- bgp-divider? [ast-node] diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 7debf02..15b201a 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -123,6 +123,14 @@ [] spo)) +(defmethod get-scope-vars :triple/spo-list [[_ spo]] + (reduce-kv (fn [acc s po] (apply concat + acc + (mapcat get-scope-vars s) + (map get-scope-vars po))) + [] + spo)) + (defmethod get-scope-vars :triple/nform [[_ nform]] (get-scope-vars nform)) diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index 261a6c2..b7b37c2 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -57,5 +57,6 @@ (is (->> '{?s {(cat :x/one :x/two) #{?o}}} (s/explain-data ts/normal-form-nopath-spec) ::s/problems + (filter #(-> % :path first (= :triple/spo))) (map :val) (every? (partial = '(cat :x/one :x/two)))))))) From 0e380bdc2ee287fc37636b1513ac2f814569bd17 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Fri, 2 Feb 2024 10:05:16 -0500 Subject: [PATCH 04/34] Move all triple and quad specs to triple ns --- .../com/yetanalytics/flint/format/triple.cljc | 13 +++ .../com/yetanalytics/flint/format/update.cljc | 29 ++---- .../com/yetanalytics/flint/spec/query.cljc | 8 +- .../com/yetanalytics/flint/spec/triple.cljc | 91 +++++++++++++++++++ .../com/yetanalytics/flint/spec/update.cljc | 82 +---------------- 5 files changed, 116 insertions(+), 107 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 6b26d19..f1df48d 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -48,3 +48,16 @@ (defmethod f/format-ast-node :triple/o [_ [_ o]] (->> o (cstr/join " , "))) + +(defn format-quads [quads pretty?] + (-> quads + (f/join-clauses pretty?) + (f/wrap-in-braces pretty?))) + +(defmethod f/format-ast-node :triple/quads + [_ [_ [var-or-iri triples-str]]] + (str "GRAPH " var-or-iri " " triples-str)) + +(defmethod f/format-ast-node :triple/quad-triples + [{:keys [pretty?]} [_ triples]] + (format-quads triples pretty?)) diff --git a/src/main/com/yetanalytics/flint/format/update.cljc b/src/main/com/yetanalytics/flint/format/update.cljc index b82f8f1..7cd1b65 100644 --- a/src/main/com/yetanalytics/flint/format/update.cljc +++ b/src/main/com/yetanalytics/flint/format/update.cljc @@ -3,26 +3,9 @@ [com.yetanalytics.flint.format :as f] [com.yetanalytics.flint.format.axiom] [com.yetanalytics.flint.format.prologue] - [com.yetanalytics.flint.format.triple] + [com.yetanalytics.flint.format.triple :as tf] [com.yetanalytics.flint.format.where])) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Quads -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defn- format-quads [quads pretty?] - (-> quads - (f/join-clauses pretty?) - (f/wrap-in-braces pretty?))) - -(defmethod f/format-ast-node :triple/quads - [_ [_ [var-or-iri triples-str]]] - (str "GRAPH " var-or-iri " " triples-str)) - -(defmethod f/format-ast-node :triple/quad-triples - [{:keys [pretty?]} [_ triples]] - (format-quads triples pretty?)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Graph Management ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -128,19 +111,19 @@ (str "WITH " with)) (defmethod f/format-ast-node :insert-data [{:keys [pretty?]} [_ insert-data]] - (str "INSERT DATA " (format-quads insert-data pretty?))) + (str "INSERT DATA " (tf/format-quads insert-data pretty?))) (defmethod f/format-ast-node :delete-data [{:keys [pretty?]} [_ delete-data]] - (str "DELETE DATA " (format-quads delete-data pretty?))) + (str "DELETE DATA " (tf/format-quads delete-data pretty?))) (defmethod f/format-ast-node :delete-where [{:keys [pretty?]} [_ delete-where]] - (str "DELETE WHERE " (format-quads delete-where pretty?))) + (str "DELETE WHERE " (tf/format-quads delete-where pretty?))) (defmethod f/format-ast-node :delete [{:keys [pretty?]} [_ delete]] - (str "DELETE " (format-quads delete pretty?))) + (str "DELETE " (tf/format-quads delete pretty?))) (defmethod f/format-ast-node :insert [{:keys [pretty?]} [_ insert]] - (str "INSERT " (format-quads insert pretty?))) + (str "INSERT " (tf/format-quads insert pretty?))) (defmethod f/format-ast-node :update/insert-data [{:keys [pretty?]} [_ id-update]] (f/join-clauses id-update pretty?)) diff --git a/src/main/com/yetanalytics/flint/spec/query.cljc b/src/main/com/yetanalytics/flint/spec/query.cljc index 0a8f252..1e96eac 100644 --- a/src/main/com/yetanalytics/flint/spec/query.cljc +++ b/src/main/com/yetanalytics/flint/spec/query.cljc @@ -75,13 +75,7 @@ ::vs/values] :key-comp-fn key-comp)) -(def triples-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-nopath-spec - :triple/nform ts/normal-form-nopath-spec) - :min-count 0 - :kind vector?)) - -(s/def ::construct triples-spec) +(s/def ::construct ts/triple-coll-nopath-spec) (def construct-query-spec (sparql-keys :req-un [::construct ::ws/where] diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 6a7c38c..22dbc32 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -231,3 +231,94 @@ (def triple-vec-novar-noblank-spec (s/tuple subj-novar-noblank-spec pred-novar-spec obj-novar-noblank-spec)) + +;; Triples + +(def triple-spec + (s/or :triple/vec triple-vec-spec + :triple/nform normal-form-spec)) + +(def triple-nopath-spec + (s/or :triple/vec triple-vec-nopath-spec + :triple/nform normal-form-nopath-spec)) + +(def triple-novar-spec + (s/or :triple/vec triple-vec-novar-spec + :triple/nform normal-form-novar-spec)) + +(def triple-noblank-spec + (s/or :triple/vec triple-vec-noblank-spec + :triple/nform normal-form-noblank-spec)) + +(def triple-novar-noblank-spec + (s/or :triple/vec triple-vec-novar-noblank-spec + :triple/nform normal-form-novar-noblank-spec)) + +;; Collection of Triples + +(def triple-coll-spec + (s/coll-of triple-spec :kind vector?)) + +(def triple-coll-nopath-spec + (s/coll-of triple-nopath-spec :kind vector?)) + +(def triple-coll-novar-spec + (s/coll-of triple-novar-spec :kind vector?)) + +(def triple-coll-noblank-spec + (s/coll-of triple-noblank-spec :kind vector?)) + +(def triple-coll-novar-noblank-spec + (s/coll-of triple-novar-noblank-spec :kind vector?)) + +;; Quads (for UPDATE) + +(def quad-nopath-spec + (s/and (s/tuple #{:graph} + ax/iri-or-var-spec + (s/or :triple/quad-triples triple-coll-nopath-spec)) + (s/conformer (fn [[_ iri triples]] [iri triples])))) + +(def quad-novar-spec + (s/and (s/tuple #{:graph} + ax/iri-or-var-spec + (s/or :triple/quad-triples triple-coll-novar-spec)) + (s/conformer (fn [[_ iri triples]] [iri triples])))) + +(def quad-noblank-spec + (s/and (s/tuple #{:graph} + ax/iri-or-var-spec + (s/or :triple/quad-triples triple-coll-noblank-spec)) + (s/conformer (fn [[_ iri triples]] [iri triples])))) + +(def quad-novar-noblank-spec + (s/and (s/tuple #{:graph} + ax/iri-or-var-spec + (s/or :triple/quad-triples triple-coll-novar-noblank-spec)) + (s/conformer (fn [[_ iri triples]] [iri triples])))) + +;; Collection of Quads (for UPDATE) + +(def quad-coll-nopath-spec + (s/coll-of (s/or :triple/vec triple-vec-nopath-spec + :triple/nform normal-form-nopath-spec + :triple/quads quad-nopath-spec) + :kind vector?)) + +(def quad-coll-novar-spec + (s/coll-of (s/or :triple/vec triple-vec-novar-spec + :triple/nform normal-form-novar-spec + :triple/quads quad-novar-spec) + :kind vector?)) + +(def quad-coll-noblank-spec + (s/coll-of (s/or :triple/vec triple-vec-noblank-spec + :triple/nform normal-form-noblank-spec + :triple/quads quad-noblank-spec) + :kind vector?)) + +(def quad-coll-novar-noblank-spec + (s/coll-of (s/or :triple/vec triple-vec-novar-noblank-spec + :triple/nform normal-form-novar-noblank-spec + :triple/quads quad-novar-noblank-spec) + :kind vector?)) diff --git a/src/main/com/yetanalytics/flint/spec/update.cljc b/src/main/com/yetanalytics/flint/spec/update.cljc index e34db19..6503d59 100644 --- a/src/main/com/yetanalytics/flint/spec/update.cljc +++ b/src/main/com/yetanalytics/flint/spec/update.cljc @@ -45,78 +45,6 @@ n2 (get key-order-map k2 100)] (- n1 n2))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Quad specs -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(def triples-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-nopath-spec - :triple/nform ts/normal-form-nopath-spec) - :kind vector?)) - -(def triples-novar-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-novar-spec - :triple/nform ts/normal-form-novar-spec) - :kind vector?)) - -(def triples-noblank-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-noblank-spec - :triple/nform ts/normal-form-noblank-spec) - :kind vector?)) - -(def triples-novar-noblank-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-novar-noblank-spec - :triple/nform ts/normal-form-novar-noblank-spec) - :kind vector?)) - -(def quad-spec - (s/and (s/tuple #{:graph} - ax/iri-or-var-spec - (s/or :triple/quad-triples triples-spec)) - (s/conformer (fn [[_ iri t]] [iri t])))) - -(def quad-novar-spec - (s/and (s/tuple #{:graph} - ax/iri-or-var-spec - (s/or :triple/quad-triples triples-novar-spec)) - (s/conformer (fn [[_ iri t]] [iri t])))) - -(def quad-noblank-spec - (s/and (s/tuple #{:graph} - ax/iri-or-var-spec - (s/or :triple/quad-triples triples-noblank-spec)) - (s/conformer (fn [[_ iri t]] [iri t])))) - -(def quad-novar-noblank-spec - (s/and (s/tuple #{:graph} - ax/iri-or-var-spec - (s/or :triple/quad-triples triples-novar-noblank-spec)) - (s/conformer (fn [[_ iri t]] [iri t])))) - -(def triple-or-quads-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-nopath-spec - :triple/nform ts/normal-form-nopath-spec - :triple/quads quad-spec) - :kind vector?)) - -(def triple-or-quads-novar-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-novar-spec - :triple/nform ts/normal-form-novar-spec - :triple/quads quad-novar-spec) - :kind vector?)) - -(def triple-or-quads-noblank-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-noblank-spec - :triple/nform ts/normal-form-noblank-spec - :triple/quads quad-noblank-spec) - :kind vector?)) - -(def triple-or-quads-novar-noblank-spec - (s/coll-of (s/or :triple/vec ts/triple-vec-novar-noblank-spec - :triple/nform ts/normal-form-novar-noblank-spec - :triple/quads quad-novar-noblank-spec) - :kind vector?)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Graph Management specs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -221,7 +149,7 @@ ;; INSERT DATA -(s/def ::insert-data triple-or-quads-novar-spec) +(s/def ::insert-data ts/quad-coll-novar-spec) (def insert-data-update-spec (sparql-keys :req-un [::insert-data] @@ -230,7 +158,7 @@ ;; DELETE DATA -(s/def ::delete-data triple-or-quads-novar-noblank-spec) +(s/def ::delete-data ts/quad-coll-novar-noblank-spec) (def delete-data-update-spec (sparql-keys :req-un [::delete-data] @@ -239,7 +167,7 @@ ;; DELETE WHERE -(s/def ::delete-where triple-or-quads-noblank-spec) +(s/def ::delete-where ts/quad-coll-noblank-spec) (def delete-where-update-spec (sparql-keys :req-un [::delete-where] @@ -254,8 +182,8 @@ (s/or :update/iri ax/iri-or-prefixed-spec :update/named-iri (s/tuple #{:named} ax/iri-or-prefixed-spec))) -(s/def ::insert triple-or-quads-spec) -(s/def ::delete triple-or-quads-noblank-spec) +(s/def ::insert ts/quad-coll-nopath-spec) +(s/def ::delete ts/quad-coll-noblank-spec) (def modify-update-spec (sparql-keys :req-un [(or ::delete ::insert) From 5064279aad8129188a8e152337437702f76f592f Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Fri, 2 Feb 2024 19:09:37 -0500 Subject: [PATCH 05/34] Add :where/triple tag as a parallel to :where/special --- .../com/yetanalytics/flint/format/where.cljc | 3 + .../com/yetanalytics/flint/spec/where.cljc | 17 +++-- .../yetanalytics/flint/validate/variable.cljc | 3 + .../yetanalytics/flint/format/expr_test.cljc | 14 ++-- .../yetanalytics/flint/format/query_test.cljc | 49 ++++++------ .../flint/format/update_test.cljc | 20 ++--- .../yetanalytics/flint/format/where_test.cljc | 38 +++++----- .../yetanalytics/flint/spec/expr_test.cljc | 7 +- .../yetanalytics/flint/spec/query_test.cljc | 7 +- .../yetanalytics/flint/spec/where_test.cljc | 42 ++++++----- .../flint/validate/bnode_test.cljc | 52 ++++++------- .../flint/validate/prefix_test.cljc | 8 +- .../flint/validate/scope_test.cljc | 74 +++++++++++-------- 13 files changed, 191 insertions(+), 143 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/where.cljc b/src/main/com/yetanalytics/flint/format/where.cljc index 6113fec..c339a1d 100644 --- a/src/main/com/yetanalytics/flint/format/where.cljc +++ b/src/main/com/yetanalytics/flint/format/where.cljc @@ -58,5 +58,8 @@ (defmethod f/format-ast-node :where/special [_ [_ where-form]] where-form) +(defmethod f/format-ast-node :where/triple [_ [_ triples]] + triples) + (defmethod f/format-ast-node :where [_ [_ where]] (str "WHERE " where)) diff --git a/src/main/com/yetanalytics/flint/spec/where.cljc b/src/main/com/yetanalytics/flint/spec/where.cljc index cbf3103..10d0a3a 100644 --- a/src/main/com/yetanalytics/flint/spec/where.cljc +++ b/src/main/com/yetanalytics/flint/spec/where.cljc @@ -110,19 +110,24 @@ :v ::vs/values) (s/conformer (fn [{:keys [v]}] [:where/values v])))) +(defmethod where-special-form-mm :default [_] + (constantly false)) + (def where-special-form-spec "Specs for special WHERE forms/graph patterns, which should be of the form `[:keyword ...]`." - (s/and vector? (s/multi-spec where-special-form-mm first))) + (s/and vector? + #(keyword? (first %)) + (s/multi-spec where-special-form-mm first))) + +(def where-spec + (s/or :where/special where-special-form-spec + :where/triple ts/triple-spec)) (s/def ::where (s/or :where-sub/select ::select :where-sub/where - (s/coll-of (s/or :where/special where-special-form-spec - :triple/vec ts/triple-vec-spec - :triple/nform ts/normal-form-spec) - :min-count 1 - :kind vector?) + (s/coll-of where-spec :min-count 1 :kind vector?) :where-sub/empty (s/and vector? empty?))) diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 15b201a..4822fc5 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -147,6 +147,9 @@ ;; Group +(defmethod get-scope-vars :where/triple [[_ vs]] + (get-scope-vars vs)) + (defmethod get-scope-vars :where/special [[_ vs]] (get-scope-vars vs)) diff --git a/src/test/com/yetanalytics/flint/format/expr_test.cljc b/src/test/com/yetanalytics/flint/format/expr_test.cljc index 1486c83..ce61151 100644 --- a/src/test/com/yetanalytics/flint/format/expr_test.cljc +++ b/src/test/com/yetanalytics/flint/format/expr_test.cljc @@ -179,16 +179,18 @@ (is (= "EXISTS {\n ?x ?y ?z .\n}" (->> '[:expr/branch [[:expr/op exists] [:expr/args [[:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:where/triple + [[:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]]] format-ast))) (is (= "NOT EXISTS {\n ?x ?y ?z .\n}" (->> '[:expr/branch [[:expr/op not-exists] [:expr/args [[:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]]] format-ast))))) (deftest format-expr-as-var-test diff --git a/src/test/com/yetanalytics/flint/format/query_test.cljc b/src/test/com/yetanalytics/flint/format/query_test.cljc index 607fa28..b7191cc 100644 --- a/src/test/com/yetanalytics/flint/format/query_test.cljc +++ b/src/test/com/yetanalytics/flint/format/query_test.cljc @@ -23,9 +23,10 @@ [[:prefixes [[:prologue/prefix [[:ax/prefix :foo] [:ax/iri ""]]]]] [:select [:select/var-or-exprs [[:ax/var ?x]]]] [:from [:ax/iri ""]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:order-by [[:mod/asc-desc [[:mod/op asc] [:mod/asc-desc-expr [:expr/terminal [:ax/var ?y]]]]]]] @@ -46,9 +47,10 @@ [:ax/var ?y] [:ax/var ?z]]]]] [:from [:ax/iri ""]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["CONSTRUCT" "FROM " @@ -58,9 +60,10 @@ (->> '[:query/construct [[:construct []] [:from [:ax/iri ""]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["CONSTRUCT" "WHERE {" @@ -68,9 +71,10 @@ "}"]) (->> '[:query/construct [[:construct []] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast)))) (testing "Formatting DESCRIBE queries" (is (= (cstr/join "\n" ["DESCRIBE ?x ?y" @@ -83,9 +87,10 @@ [[:describe [:describe/vars-or-iris [[:ax/var ?x] [:ax/var ?y]]]] [:from-named [[:ax/iri ""] [:ax/iri ""]]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast)))) (testing "Formatting ASK queries" (is (= (cstr/join "\n" ["ASK" @@ -98,9 +103,10 @@ [[:ask []] [:from-named [[:ax/iri ""] [:ax/iri ""]]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["ASK" "WHERE {" @@ -108,7 +114,8 @@ "}"]) (->> '[:query/ask [[:ask []] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))))) diff --git a/src/test/com/yetanalytics/flint/format/update_test.cljc b/src/test/com/yetanalytics/flint/format/update_test.cljc index 0c46b38..4f21855 100644 --- a/src/test/com/yetanalytics/flint/format/update_test.cljc +++ b/src/test/com/yetanalytics/flint/format/update_test.cljc @@ -81,7 +81,8 @@ [:update/named-iri [:named [:ax/iri ""]]]] [:where [:where-sub/where - [[:triple/vec [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]]]]] + [[:where/triple + [:triple/vec [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["WITH " "DELETE {" @@ -101,14 +102,15 @@ [:insert [[:triple/vec [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]] [:using [:update/iri [:ax/iri ""]]] [:where [:where-sub/where - [[:triple/nform - [:triple/spo - [[[:ax/var ?x] - [:triple/po [[[:ax/var ?y] - [:triple/o [[:triple/object [:ax/var ?z]]]]]]]] - [[:ax/var ?a] - [:triple/po [[[:ax/var ?b] - [:triple/o [[:triple/object [:ax/var ?c]]]]]]]]]]]]]]]] + [[:where/triple + [:triple/nform + [:triple/spo + [[[:ax/var ?x] + [:triple/po [[[:ax/var ?y] + [:triple/o [[:triple/object [:ax/var ?z]]]]]]]] + [[:ax/var ?a] + [:triple/po [[[:ax/var ?b] + [:triple/o [[:triple/object [:ax/var ?c]]]]]]]]]]]]]]]]] format-ast)))) (testing "Formatting graph management updates" (testing "- LOAD" diff --git a/src/test/com/yetanalytics/flint/format/where_test.cljc b/src/test/com/yetanalytics/flint/format/where_test.cljc index 699a9cb..34dd39a 100644 --- a/src/test/com/yetanalytics/flint/format/where_test.cljc +++ b/src/test/com/yetanalytics/flint/format/where_test.cljc @@ -11,8 +11,8 @@ " ?s ?p ?o ." "}"]) (-> '[:where-sub/where - [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] - [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]] + [:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]] (f/format-ast {:pretty? true})))) (is (= (cstr/join "\n" ["{" " ?s1 ?p1 ?o1 ." @@ -51,47 +51,49 @@ " }" "}"]) (-> '[:where-sub/where - [[:triple/vec - [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]] - [:triple/nform - [:triple/spo [[[:ax/var ?s2] - [:triple/po [[[:ax/var ?p2] - [:triple/o [[:triple/object [:ax/var ?o2a]] - [:triple/object [:ax/var ?o2b]]]]]]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]]] + [:where/triple + [:triple/nform + [:triple/spo [[[:ax/var ?s2] + [:triple/po [[[:ax/var ?p2] + [:triple/o [[:triple/object [:ax/var ?o2a]] + [:triple/object [:ax/var ?o2b]]]]]]]]]]]] [:where/special [:where/recurse [:where-sub/where - [[:triple/vec [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]]] [:where/special [:where/union [[:where-sub/where - [[:triple/vec - [[:ax/var ?s4] [:ax/var ?p4] [:ax/var ?o4]]]]] + [[:where/triple [:triple/vec + [[:ax/var ?s4] [:ax/var ?p4] [:ax/var ?o4]]]]]] [:where-sub/where - [[:triple/vec [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]]] [:where/special [:where/optional [:where-sub/where - [[:triple/vec [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]]] [:where/special [:where/minus [:where-sub/where - [[:triple/vec [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]]] [:where/special [:where/graph [[:ax/prefix-iri :ns/my-graph] [:where-sub/where - [[:triple/vec [[:ax/var ?s8] [:ax/var ?p8] [:ax/var ?o8]]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s8] [:ax/var ?p8] [:ax/var ?o8]]]]]]]]] [:where/special [:where/service [[:ax/prefix-iri :ns/my-uri] [:where-sub/where - [[:triple/vec [[:ax/var ?s9] [:ax/var ?p9] [:ax/var ?o9]]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s9] [:ax/var ?p9] [:ax/var ?o9]]]]]]]]] [:where/special [:where/service-silent [[:ax/prefix-iri :ns/my-uri] [:where-sub/where - [[:triple/vec [[:ax/var ?s10] [:ax/var ?p10] [:ax/var ?o10]]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s10] [:ax/var ?p10] [:ax/var ?o10]]]]]]]]] [:where/special [:where/bind [:expr/as-var diff --git a/src/test/com/yetanalytics/flint/spec/expr_test.cljc b/src/test/com/yetanalytics/flint/spec/expr_test.cljc index 7814ddc..543e49d 100644 --- a/src/test/com/yetanalytics/flint/spec/expr_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/expr_test.cljc @@ -41,9 +41,10 @@ ;; (We can't `require` it due to circular dependencies.) (is (= [:expr/branch [[:expr/op 'exists] [:expr/args [[:where-sub/where - [[:triple/vec '[[:ax/var ?s] - [:ax/var ?p] - [:ax/var ?o]]]]]]]]] + [[:where/triple + [:triple/vec '[[:ax/var ?s] + [:ax/var ?p] + [:ax/var ?o]]]]]]]]]] (s/conform ::es/expr '(exists [[?s ?p ?o]])))) (is (= [:expr/branch [[:expr/op 'contains] [:expr/args [[:expr/terminal [:ax/literal "foo"]] diff --git a/src/test/com/yetanalytics/flint/spec/query_test.cljc b/src/test/com/yetanalytics/flint/spec/query_test.cljc index 19ba375..791289d 100644 --- a/src/test/com/yetanalytics/flint/spec/query_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/query_test.cljc @@ -18,9 +18,10 @@ [[:prefixes [[:prologue/prefix [[:ax/prefix :foo] [:ax/iri ""]]]]] [:select [:select/var-or-exprs [[:ax/var ?x]]]] [:from [:ax/iri ""]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:order-by [[:mod/asc-desc [[:mod/op asc] [:mod/asc-desc-expr [:expr/terminal [:ax/var ?y]]]]]]] diff --git a/src/test/com/yetanalytics/flint/spec/where_test.cljc b/src/test/com/yetanalytics/flint/spec/where_test.cljc index 3e61951..4abe7fc 100644 --- a/src/test/com/yetanalytics/flint/spec/where_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/where_test.cljc @@ -7,16 +7,18 @@ (testing "Conforming WHERE clauses" (is (= '[:where-sub/select [[:select [:select/var-or-exprs [[:ax/var ?s]]]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?s] - [:ax/var ?p] - [:ax/var ?o]]]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?s] + [:ax/var ?p] + [:ax/var ?o]]]]]]]]] (s/conform ::ws/where '{:where [[?s ?p ?o]] :select [?s]}))) (is (= '[:where-sub/select [[:select [:select/var-or-exprs [[:ax/var ?s]]]] - [:where [:where-sub/where [[:triple/vec [[:ax/var ?s] - [:ax/var ?p] - [:ax/var ?o]]]]]] + [:where [:where-sub/where [[:where/triple + [:triple/vec [[:ax/var ?s] + [:ax/var ?p] + [:ax/var ?o]]]]]]] [:group-by [[:mod/expr-as-var [:expr/as-var [[:expr/branch @@ -31,37 +33,43 @@ [[:where/special [:where/union [[:where-sub/where - [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] - [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]] - [:where-sub/where [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]] + [:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]] + [:where-sub/where + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where '[[:union [[?s ?p ?o] [?s ?p ?o]] [[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/optional - [:where-sub/where [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]] + [:where-sub/where + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] (s/conform ::ws/where [[:optional '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/minus - [:where-sub/where [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]] + [:where-sub/where + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] (s/conform ::ws/where [[:minus '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/graph [[:ax/prefix-iri :foo/my-graph] - [:where-sub/where [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] + [:where-sub/where + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where [[:graph :foo/my-graph '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/service [[:ax/prefix-iri :foo/my-uri] - [:where-sub/where [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] + [:where-sub/where + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where [[:service :foo/my-uri '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/service-silent [[:ax/prefix-iri :foo/my-uri] - [:where-sub/where [[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] + [:where-sub/where + [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where [[:service-silent :foo/my-uri '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special @@ -92,9 +100,9 @@ ;; This is not a special form since it does not conform to the UNION ;; spec (or any other special form spec really) (is (= '[:where-sub/where - [[:triple/vec [[:ax/prefix-iri :union] - [:ax/prefix-iri :foo/bar] - [:ax/prefix-iri :baz/qux]]]]] + [[:where/triple [:triple/vec [[:ax/prefix-iri :union] + [:ax/prefix-iri :foo/bar] + [:ax/prefix-iri :baz/qux]]]]]] (s/conform ::ws/where '[[:union :foo/bar :baz/qux]]))))) (deftest invalid-where-test diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index 43fe0d7..11c6f5a 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -53,9 +53,9 @@ (testing "invalid blank nodes" (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]] [:where [[?y :baz/qux _1]]]]} @@ -64,13 +64,13 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[:where [{?x {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -81,17 +81,17 @@ vb/validate-bnodes))) (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_2 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_2 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]} + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[:where [{_2 {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -102,9 +102,9 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?y :baz/qux _1]]]]} @@ -113,11 +113,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 2 :where/special :where/optional :where-sub/where 0]} + :path [:query/select :where :where-sub/where 2 :where/special :where/optional :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0]} + :path [:query/select :where :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [?y :baz/qux _1] @@ -127,11 +127,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1]} + :path [:query/select :where :where-sub/where 1 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?z :far/lands _1]]] @@ -141,11 +141,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0]} + :path [:query/select :where :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/filter :expr/branch :expr/args :where-sub/where 0]} + :path [:query/select :where :where-sub/where 1 :where/special :where/filter :expr/branch :expr/args :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0]}]}] + :path [:query/select :where :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:filter (not-exists [[?z :far/lands _1]])] @@ -155,7 +155,7 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-update :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]}] + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}] :prev-bnodes #{'_1}}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]]]} @@ -164,7 +164,7 @@ (vb/validate-bnodes #{'_1})))) (is (= [[#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]} + :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 :path [:update/modify :insert]}]}]] (->> '[{:insert [[?x :foo/bar _1]] @@ -188,7 +188,7 @@ [{:bnode '_1 :path [:update/modify :insert]} {:bnode '_2 - :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0]}] + :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}] :prev-bnodes #{'_1 '_2}}] (->> '[{:insert [[?x :foo/bar _1]] diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index f2b1c76..7a18e07 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -26,7 +26,7 @@ (is (= [{:iri :bar :prefix :$ :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :triple/vec :ax/prefix-iri]}] + :path [:query/select :where :where-sub/where :where/triple :triple/vec :ax/prefix-iri]}] (->> (assoc query :where '[[:bar :a ?y]]) (s/conform qs/query-spec) v/collect-nodes @@ -34,15 +34,15 @@ (is (= [{:iri :fee/bar :prefix :fee :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :triple/vec :ax/prefix-iri]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec :ax/prefix-iri]} {:iri :fii/bar :prefix :fii :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :triple/vec :ax/prefix-iri]} + :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :where/triple :triple/vec :ax/prefix-iri]} {:iri :fum/bar :prefix :fum :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :triple/vec :ax/prefix-iri]}] + :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :where/triple :triple/vec :ax/prefix-iri]}] (->> query (s/conform qs/query-spec) v/collect-nodes diff --git a/src/test/com/yetanalytics/flint/validate/scope_test.cljc b/src/test/com/yetanalytics/flint/validate/scope_test.cljc index d406caa..d2f6438 100644 --- a/src/test/com/yetanalytics/flint/validate/scope_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/scope_test.cljc @@ -49,15 +49,17 @@ (is (= '[?x ?y ?z] (vv/get-scope-vars '[:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]))) + [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]))) (is (= '[?x ?y ?z] (vv/get-scope-vars '[:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]))) + [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]))) (is (= '[?x ?ya ?yb ?z] (vv/get-scope-vars '[:triple/vec @@ -74,9 +76,10 @@ '[:where-sub/select [[:select [:ax/wildcard '*]] [:where [:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]))) + [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]]))) ;; This is an illegal sub-SELECT since it has both a wildcard and ;; GROUP BY, but we want to cover all of our bases. (is (= '[?x ?y ?z ?w] @@ -84,9 +87,10 @@ '[:where-sub/select [[:select [:ax/wildcard '*]] [:where [:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]] + [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:group-by [[:ax/var ?w]]]]]))) (is (= '[?a ?b ?c] (vv/get-scope-vars @@ -98,9 +102,10 @@ [:expr/as-var [[:expr/terminal [:ax/num-lit 2]] [:ax/var ?c]]]]]]] [:where [:where-sub/where - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]] + [[:where/triple + [:triple/vec [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:group-by [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]])))) @@ -117,33 +122,41 @@ '[:where-sub/where [[:where/recurse [:where-sub/where - [[:triple/vec [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]]]]]] [:where/union [[:where-sub/where - [[:triple/vec - [[:ax/var ?s2] [:ax/var ?p2] [:ax/var ?o2]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s2] [:ax/var ?p2] [:ax/var ?o2]]]]]] [:where-sub/where - [[:triple/vec - [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]]] [:where/optional [:where-sub/where - [[:triple/vec - [[:ax/var ?s4] [:ax/var ?p4] [:ax/var ?o4]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s4] [:ax/var ?p4] [:ax/var ?o4]]]]]]] [:where/graph [[:ax/var ?graphTerm] [:where-sub/where - [[:triple/vec - [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]] [:where/service [[:ax/var ?serviceTerm] [:where-sub/where - [[:triple/vec - [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]]] [:where/service-silent [[:ax/var ?serviceSilentTerm] [:where-sub/where - [[:triple/vec - [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]] + [[:where/triple + [:triple/vec + [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]]] [:where/bind [:expr/as-var [[:expr/branch @@ -163,8 +176,9 @@ [:expr/terminal [:ax/var ?bar]])]]]] [:where/minus [:where-sub/where - [[:triple/vec - [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]]))))) + [[:where/triple + [:triple/vec + [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]]]))))) (deftest scope-validation-test From 7386127f549edd2d9798b3a7d1f17e5ef7a68a64 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Mon, 5 Feb 2024 17:09:06 -0500 Subject: [PATCH 06/34] Rework blank node validation --- src/dev/com/yetanalytics/flint/sparql.clj | 25 ++++++++ src/main/com/yetanalytics/flint/validate.cljc | 57 ++++++++++++++---- .../flint/validate/aggregate.cljc | 2 +- .../yetanalytics/flint/validate/bnode.cljc | 59 +++++-------------- .../flint/validate/bnode_test.cljc | 54 ++++++++++------- 5 files changed, 120 insertions(+), 77 deletions(-) diff --git a/src/dev/com/yetanalytics/flint/sparql.clj b/src/dev/com/yetanalytics/flint/sparql.clj index 9636073..369afde 100644 --- a/src/dev/com/yetanalytics/flint/sparql.clj +++ b/src/dev/com/yetanalytics/flint/sparql.clj @@ -38,6 +38,31 @@ ;; Query/Update writing sandbox +(comment + (QueryFactory/create + "CONSTRUCT { _:b0 ?pred _:b0 } + WHERE { _:b0 ?pred _:b0 . + OPTIONAL { + ?y ?pred2 _:b1 + } + _:b0 ?question _:b0 . }") + + (QueryFactory/create + "SELECT ?x + WHERE { + { ?x _:1 . } + { ?y _:1 . } + }") + + (QueryFactory/create + "PREFIX foo: + SELECT ?x WHERE { + ?x foo:bar _:1 . + FILTER NOT EXISTS { ?z foo:baz ?w . } + ?y foo:qux _:1 . + }") + ) + (comment (QueryFactory/create "SELECT ((AVG(MAX(?x)) + 1) AS ?avg) diff --git a/src/main/com/yetanalytics/flint/validate.cljc b/src/main/com/yetanalytics/flint/validate.cljc index fc56c89..0951f6c 100644 --- a/src/main/com/yetanalytics/flint/validate.cljc +++ b/src/main/com/yetanalytics/flint/validate.cljc @@ -3,6 +3,24 @@ [com.yetanalytics.flint.spec.expr :as es] [com.yetanalytics.flint.util :as u])) +(defn- bgp-divider? + "Is `ast-node` a divider between BGPs?" + [loc] + (let [?left-node (some-> loc zip/left zip/node) + ?curr-node (some-> loc zip/node)] + (or + ;; BGPs are separated by special clauses, with the exception of FILTER... + (and (some-> ?left-node (get-in [0]) (= :where/special)) + (some-> ?left-node (get-in [1 0]) (not= :where/filter))) + ;; BGPs are also separated via nesting (which also separates BGPs at the + ;; top level) + (some-> ?curr-node (get-in [0]) (= :where-sub/where)) + ;; ...including the case of FILTER (NOT) EXISTS, which has its own BGP + ;; as a subquery (c.f. MINUS) + (and (some-> ?curr-node (get-in [0]) (= :expr/branch)) + (or (some-> ?curr-node (get-in [1 0]) (= [:expr/op 'exists])) + (some-> ?curr-node (get-in [1 0]) (= [:expr/op 'not-exists]))))))) + (def axiom-keys #{:ax/iri :ax/prefix-iri :ax/var :ax/bnode :ax/wildcard :ax/rdf-type :ax/str-lit :ax/lmap-list :ax/num-lit :ax/bool-lit :ax/dt-lit @@ -65,22 +83,37 @@ (defn collect-nodes [ast] - (loop [loc (ast-zipper ast) - node-m {}] + (loop [loc (ast-zipper ast) + node-m {} + bgp-idx 0] (if-not (zip/end? loc) - (let [ast-node (zip/node loc)] + (let [ast-node (zip/node loc) + bgp-idx* (cond-> bgp-idx (bgp-divider? loc) inc)] (if-some [k (u/get-keyword ast-node)] (cond - ;; Prefixes, blank nodes, and BIND clauses - (node-keys k) - (recur (zip/next loc) - (update-in node-m [k (second ast-node)] conj loc)) + ;; Prefixes, BIND (expr AS var), and SELECT ... (expr AS var) ... + (#{:ax/prefix-iri :where/bind :select/expr-as-var} k) + (let [v (second ast-node)] + (recur (zip/next loc) + (update-in node-m [k v] conj loc) + bgp-idx*)) + ;; Blank nodes + (#{:ax/bnode} k) + (let [bnode (second ast-node) + top-level (-> loc zip/path second first) + bgp-path (cond-> [top-level] + (= :where top-level) + (conj bgp-idx*))] + (recur (zip/next loc) + (update-in node-m [k bnode bgp-path] conj loc) + bgp-idx*)) ;; SELECT with GROUP BY (#{:group-by} k) (let [select-loc (zip/up loc) select (zip/node select-loc)] (recur (zip/next loc) - (update node-m :agg/select assoc select select-loc))) + (update node-m :agg/select assoc select select-loc) + bgp-idx*)) ;; SELECT with an aggregate expression (#{:expr/branch} k) (let [op (-> ast-node ; [:expr/branch ...] @@ -97,9 +130,9 @@ assoc select select-loc)] - (recur (zip/next loc) node-m*)) - (recur (zip/next loc) node-m))) + (recur (zip/next loc) node-m* bgp-idx*)) + (recur (zip/next loc) node-m bgp-idx*))) :else - (recur (zip/next loc) node-m)) - (recur (zip/next loc) node-m))) + (recur (zip/next loc) node-m bgp-idx*)) + (recur (zip/next loc) node-m bgp-idx*))) node-m))) diff --git a/src/main/com/yetanalytics/flint/validate/aggregate.cljc b/src/main/com/yetanalytics/flint/validate/aggregate.cljc index c8eca8f..f1efdb7 100644 --- a/src/main/com/yetanalytics/flint/validate/aggregate.cljc +++ b/src/main/com/yetanalytics/flint/validate/aggregate.cljc @@ -9,7 +9,7 @@ ;; just a variable, those variables may be projected from the level. ;; GOOD: -;; SELECT (2 AS ?two) WHER { ?x ?y ?z } +;; SELECT (2 AS ?two) WHERE { ?x ?y ?z } ;; SELECT (SUM(?x) AS ?sum) WHERE { ?x ?y ?z } ;; SELECT ?x WHERE { ?x ?y ?z } GROUP BY ?x diff --git a/src/main/com/yetanalytics/flint/validate/bnode.cljc b/src/main/com/yetanalytics/flint/validate/bnode.cljc index cdf4dc5..0c6d288 100644 --- a/src/main/com/yetanalytics/flint/validate/bnode.cljc +++ b/src/main/com/yetanalytics/flint/validate/bnode.cljc @@ -96,46 +96,16 @@ :else res-path))))) -(defn- valid-bnode-locs? - "Given `locs`, return `false` if `bnode` is duplicated across multiple - BGPs, `true` otherwise." - [[bnode locs]] - (if (<= (count locs) 1) - true ; Can't have dupe bnodes if there's only one instance :p - (let [loc-paths (map (fn [loc] (mapv first (zip/path loc))) locs) - [wh non-wh] (split-with #(some #{:where-sub/where} %) loc-paths) - ?wheres (not-empty wh) - ?non-wheres (not-empty non-wh)] - (cond - ;; Blank nodes only exist in a non-WHERE clause (e.g. CONSTRUCT, - ;; INSERT DATA, or INSERT). Since only one such clause may exist - ;; in a Query or Update, and since each counts as a single BGP, - ;; we are done. - (and (not ?wheres) - ?non-wheres) - true - ;; Blank nodes exist in both a WHERE and non-WHERE clause. Since - ;; those automatically count as two different BGPs, we are done. - (and ?wheres - ?non-wheres) - false - ;; Blank nodes only exist in WHERE clauses. They may all be in one - ;; or more BGP, so we need to investigate further. - (and ?wheres - (not ?non-wheres)) - (let [bgp-paths (map annotated-path locs)] - (apply = bgp-paths)) - :else - (throw (ex-info "Blank nodes located in invalid locations!" - {:kind ::invalid-bnode-loc - :bnode bnode - :zip-locs locs})))))) +(defn- invalid-bnode? + "Is the blank node that is associated with `bgp-loc-m` invalid? It is + if the map has more than one entry, indicating that the blank node is + located across multiple BGPs." + [bgp-loc-m] + (< 1 (count bgp-loc-m))) (defn- bnode-err-map [bnode loc] {:bnode bnode - ;; Rather wasteful to call `annotated-path` twice, but this only - ;; occurs during exn throwing so performance isn't a priority. :path (annotated-path loc)}) (defn- bnode-locs->err-map @@ -155,19 +125,22 @@ ([node-m] (validate-bnodes #{} node-m)) ([prev-bnodes node-m] - (let [bnode-locs (->> (:ax/bnode node-m) - (filter (fn [[bnode _]] (not= '_ bnode)))) - new-bnodes (set (keys bnode-locs)) + (let [bnode-bgp-m (-> (:ax/bnode node-m) (dissoc '_)) + new-bnodes (set (keys bnode-bgp-m)) bnode-union (cset/union prev-bnodes new-bnodes)] - (if-some [bad-bnode-locs (->> bnode-locs - (filter (comp prev-bnodes first)) + (if-some [bad-bnode-locs (->> bnode-bgp-m + (keep (fn [[bnode bgp-loc-m]] + (when (contains? prev-bnodes bnode) + [bnode (apply concat (vals bgp-loc-m))]))) not-empty)] [bnode-union {:kind ::dupe-bnodes-update :errors (bnode-locs->err-map bad-bnode-locs) :prev-bnodes prev-bnodes}] - (if-some [bad-bnode-locs (->> bnode-locs - (filter (comp not valid-bnode-locs?)) + (if-some [bad-bnode-locs (->> bnode-bgp-m + (keep (fn [[bnode bgp-loc-m]] + (when (invalid-bnode? bgp-loc-m) + [bnode (apply concat (vals bgp-loc-m))]))) not-empty)] [bnode-union {:kind ::dupe-bnodes-bgp diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index 11c6f5a..e43d508 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -53,9 +53,9 @@ (testing "invalid blank nodes" (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]] [:where [[?y :baz/qux _1]]]]} @@ -64,13 +64,13 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} - {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + {:bnode '_1 + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[:where [{?x {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -81,17 +81,17 @@ vb/validate-bnodes))) (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_2 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} - {:bnode '_2 :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} - {:bnode '_1 + {:bnode '_2 :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + {:bnode '_1 + :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[:where [{_2 {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -102,9 +102,9 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?y :baz/qux _1]]]]} @@ -113,11 +113,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 2 :where/special :where/optional :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where 1 :where/triple]} {:bnode '_1 :path [:query/select :where :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 2 :where/special :where/optional :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [?y :baz/qux _1] @@ -127,11 +127,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/triple]} + :path [:query/select :where :where-sub/where 0 :where/triple]} {:bnode '_1 :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 2 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?z :far/lands _1]]] @@ -139,13 +139,25 @@ (s/conform qs/query-spec) v/collect-nodes vb/validate-bnodes))) + (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp + :errors [{:bnode '_2 + :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} + {:bnode '_2 + :path [:query/select :where :where-sub/where 2 :where/triple]}]}] + (->> '{:select [?x] + :where [[?x :foo/bar _1] + [:optional [[?z :far/lands _2]]] + [?y :baz/qux _2]]} + (s/conform qs/query-spec) + v/collect-nodes + vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 :path [:query/select :where :where-sub/where 0 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/filter :expr/branch :expr/args :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where 2 :where/triple]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where 1 :where/special :where/filter :expr/branch :expr/args :where-sub/where 0 :where/triple]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:filter (not-exists [[?z :far/lands _1]])] @@ -164,9 +176,9 @@ (vb/validate-bnodes #{'_1})))) (is (= [[#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:update/modify :insert]} {:bnode '_1 - :path [:update/modify :insert]}]}]] + :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}]] (->> '[{:insert [[?x :foo/bar _1]] :where [[:where [[?x :foo/bar _1]]]]}] (map (partial s/conform us/update-spec)) From ad5b86f03dfe6b32eda28bb28e7a70919e9f125d Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Mon, 5 Feb 2024 17:41:26 -0500 Subject: [PATCH 07/34] Extract out utility function and simplify bnode path construction --- src/main/com/yetanalytics/flint/validate.cljc | 16 ++- .../flint/validate/aggregate.cljc | 10 +- .../yetanalytics/flint/validate/bnode.cljc | 98 +------------------ .../yetanalytics/flint/validate/prefix.cljc | 4 +- .../yetanalytics/flint/validate/scope.cljc | 5 +- .../com/yetanalytics/flint/validate/util.cljc | 7 ++ .../flint/validate/bnode_test.cljc | 60 ++++++------ 7 files changed, 64 insertions(+), 136 deletions(-) create mode 100644 src/main/com/yetanalytics/flint/validate/util.cljc diff --git a/src/main/com/yetanalytics/flint/validate.cljc b/src/main/com/yetanalytics/flint/validate.cljc index 0951f6c..c3d6fc0 100644 --- a/src/main/com/yetanalytics/flint/validate.cljc +++ b/src/main/com/yetanalytics/flint/validate.cljc @@ -4,7 +4,21 @@ [com.yetanalytics.flint.util :as u])) (defn- bgp-divider? - "Is `ast-node` a divider between BGPs?" + "Is `ast-node` a divider between BGPs? BGPs are divided by `:where/special` + clauses, with the exception of filters (unless they themselves have a + subquery): + + [:where/triple + [:triple/vec ...]] => 0 + [:where/triple + [:triple/nform ...]] => 0 + [:where/special + [:where/filter ...]] => 0 ; FILTERs don't divide BGPs + [:where/special + [:where/optional ...]] => X ; BGP divider + [:where/triple + [:triple/nform ...]] => 1 + " [loc] (let [?left-node (some-> loc zip/left zip/node) ?curr-node (some-> loc zip/node)] diff --git a/src/main/com/yetanalytics/flint/validate/aggregate.cljc b/src/main/com/yetanalytics/flint/validate/aggregate.cljc index f1efdb7..5be545f 100644 --- a/src/main/com/yetanalytics/flint/validate/aggregate.cljc +++ b/src/main/com/yetanalytics/flint/validate/aggregate.cljc @@ -1,7 +1,7 @@ (ns com.yetanalytics.flint.validate.aggregate - (:require [clojure.zip :as zip] - [com.yetanalytics.flint.validate.variable :as vv] - [com.yetanalytics.flint.util :as u])) + (:require [com.yetanalytics.flint.validate.variable :as vv] + [com.yetanalytics.flint.util :as u] + [com.yetanalytics.flint.validate.util :as vu])) ;; In a query level which uses aggregates, only expressions consisting of ;; aggregates and constants may be projected, with one exception. @@ -57,12 +57,12 @@ (case sel-k :ax/wildcard {:kind ::wildcard-group-by - :path (->> loc zip/path (mapv first))} + :path (vu/zip-path loc)} :select/var-or-exprs (when-some [bad-vars (validate-agg-select-clause group-by-vs sel-v)] {:kind ::invalid-aggregate-var :variables bad-vars - :path (->> loc zip/path (mapv first))}) + :path (vu/zip-path loc)}) ;; else - perhaps it is a CONSTRUCT, DESCRIBE, or ASK query instead nil))) diff --git a/src/main/com/yetanalytics/flint/validate/bnode.cljc b/src/main/com/yetanalytics/flint/validate/bnode.cljc index 0c6d288..b99edbd 100644 --- a/src/main/com/yetanalytics/flint/validate/bnode.cljc +++ b/src/main/com/yetanalytics/flint/validate/bnode.cljc @@ -1,100 +1,6 @@ (ns com.yetanalytics.flint.validate.bnode (:require [clojure.set :as cset] - [clojure.zip :as zip])) - -(defn- get-parent-loc - "Given a bnode's loc, return its parent (either a `:triple/vec` - or `:triple/nform` node)." - [loc] - (let [penultimate (-> loc zip/path last first)] - (case penultimate - :triple/vec - (-> loc ; [:ax/bnode ...] - zip/up ; [:triple/vec ...] - ) - :triple/list - (-> loc ; [:ax/bnode ...] - zip/up ; [:triple/list ...] - zip/up ; [:triple/o ...] - zip/up ; [:triple/po ...] - zip/up ; [:triple/spo ...] - zip/up ; [:triple/nform ...] - ) - :triple/object - (-> loc ; [:ax/bnode ...] - zip/up ; [:triple/object ...] - zip/up ; [:triple/o ...] - zip/up ; [:triple/po ...] - zip/up ; [:triple/spo ...] - zip/up ; [:triple/nform ...] - ) - :triple/spo - (-> loc ; [:ax/bnode ...] - zip/up ; [:triple/spo ...] - zip/up ; [:triple/nform ...] - ) - :triple/spo-list - (-> loc ; [:ax/bnode ...] - zip/up ; [:triple/spo-list ...] - zip/up ; [:triple/nform ...] - ) - ))) - -(defn- bgp-divider? - [ast-node] - (and (-> ast-node (get-in [0]) (= :where/special)) - (-> ast-node (get-in [1 0]) (not= :where/filter)))) - -(defn- get-bgp-index - "The BGP path is the regular zip loc path appended with an index that - corresponds to that of the BGP in the WHERE vector. For example: - - [:triple/vec ...] => 0 - [:triple/nform ...] => 0 - [:where/special - [:where/filter ...]] => 0 ; FILTERs don't divide BGPs - [:where/special - [:where/optional ...]] => X ; BGP divider - [:triple/nform ...] => 1 - - Note that this only works with locs that are immediate children - of `:where-sub/where` nodes. - " - [loc] - (let [lefts (zip/lefts loc)] - (count (filter bgp-divider? lefts)))) - -(defn- get-where-index - [pnode nnode] - (let [indexed (map-indexed (fn [i x] [x i]) (second pnode))] - (some (fn [[x i]] (when (= x nnode) i)) indexed))) - -(defn- annotated-path - "Create a coll of AST keywords where all `:where-sub/where`s are - followed by indices, either the index in the WHERE vector or the - index of the BGP (for the very last one)." - [loc] - (let [parent-loc (get-parent-loc loc)] - (loop [zip-path (zip/path parent-loc) - res-path []] - (let [?pnode (first zip-path) - ?nnode (second zip-path)] - (cond - (and ?pnode - ?nnode - (= :where-sub/where (first ?pnode))) - (recur (rest zip-path) - (conj res-path (first ?pnode) (get-where-index ?pnode ?nnode))) - (and ?pnode - (not ?nnode) - (= :where-sub/where (first ?pnode))) - (recur (rest zip-path) - (conj res-path (first ?pnode) (get-bgp-index parent-loc))) - ?pnode - (recur (rest zip-path) - (conj res-path (first ?pnode))) - :else - res-path))))) + [com.yetanalytics.flint.validate.util :as vu])) (defn- invalid-bnode? "Is the blank node that is associated with `bgp-loc-m` invalid? It is @@ -106,7 +12,7 @@ (defn- bnode-err-map [bnode loc] {:bnode bnode - :path (annotated-path loc)}) + :path (vu/zip-path loc)}) (defn- bnode-locs->err-map [bnode-locs] diff --git a/src/main/com/yetanalytics/flint/validate/prefix.cljc b/src/main/com/yetanalytics/flint/validate/prefix.cljc index b4f9353..9207d18 100644 --- a/src/main/com/yetanalytics/flint/validate/prefix.cljc +++ b/src/main/com/yetanalytics/flint/validate/prefix.cljc @@ -1,5 +1,5 @@ (ns com.yetanalytics.flint.validate.prefix - (:require [clojure.zip :as zip])) + (:require [com.yetanalytics.flint.validate.util :as vu])) (defn- invalid-prefix? "Does the prefix of `prefix-iri` exist in the `prefixes` map/set? @@ -14,7 +14,7 @@ {:prefixes prefixes :iri prefix-iri :prefix (or (some->> prefix-iri namespace keyword) :$) - :path (conj (->> loc zip/path (mapv first)) :ax/prefix-iri)}) + :path (conj (vu/zip-path loc) :ax/prefix-iri)}) (defn validate-prefixes "Given `node-m` a map from nodes to zipper locs, check that each prefix diff --git a/src/main/com/yetanalytics/flint/validate/scope.cljc b/src/main/com/yetanalytics/flint/validate/scope.cljc index 42ab598..f786ad6 100644 --- a/src/main/com/yetanalytics/flint/validate/scope.cljc +++ b/src/main/com/yetanalytics/flint/validate/scope.cljc @@ -1,6 +1,7 @@ (ns com.yetanalytics.flint.validate.scope (:require [clojure.zip :as zip] [com.yetanalytics.flint.validate.variable :as vv] + [com.yetanalytics.flint.validate.util :as vu] [com.yetanalytics.flint.util :as u])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -12,14 +13,14 @@ {:kind ::var-in-scope :variable var :scope-vars scope-vars - :path (conj (->> zip-loc zip/path (mapv first)) k)}) + :path (conj (vu/zip-path zip-loc) k)}) (defn- not-in-scope-err-map [vars scope-vars zip-loc k] {:kind ::var-not-in-scope :variables vars :scope-vars scope-vars - :path (conj (->> zip-loc zip/path (mapv first)) k)}) + :path (conj (vu/zip-path zip-loc) k)}) (defn- validate-bind "Validate `BIND (expr AS var)` in WHERE clauses." diff --git a/src/main/com/yetanalytics/flint/validate/util.cljc b/src/main/com/yetanalytics/flint/validate/util.cljc new file mode 100644 index 0000000..1b639eb --- /dev/null +++ b/src/main/com/yetanalytics/flint/validate/util.cljc @@ -0,0 +1,7 @@ +(ns com.yetanalytics.flint.validate.util + (:require [clojure.zip :as zip])) + +(defn zip-path + "Return the path vector (excluding array indices) that leads up to `loc`." + [loc] + (->> loc zip/path (mapv first))) diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index e43d508..b654775 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -53,9 +53,9 @@ (testing "invalid blank nodes" (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}]}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]] [:where [[?y :baz/qux _1]]]]} @@ -64,13 +64,13 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]}]}] (->> '{:select [?x] :where [[:where [{?x {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -81,17 +81,17 @@ vb/validate-bnodes))) (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_2 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo]} {:bnode '_2 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]}]}] (->> '{:select [?x] :where [[:where [{_2 {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -102,9 +102,9 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?y :baz/qux _1]]]]} @@ -113,11 +113,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/triple]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 2 :where/special :where/optional :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [?y :baz/qux _1] @@ -127,11 +127,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 2 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/triple :triple/vec]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?z :far/lands _1]]] @@ -141,9 +141,9 @@ vb/validate-bnodes))) (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_2 - :path [:query/select :where :where-sub/where 1 :where/special :where/optional :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]} {:bnode '_2 - :path [:query/select :where :where-sub/where 2 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/triple :triple/vec]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?z :far/lands _2]]] @@ -153,11 +153,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/triple]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 2 :where/triple]} + :path [:query/select :where :where-sub/where :where/triple :triple/vec]} {:bnode '_1 - :path [:query/select :where :where-sub/where 1 :where/special :where/filter :expr/branch :expr/args :where-sub/where 0 :where/triple]}]}] + :path [:query/select :where :where-sub/where :where/special :where/filter :expr/branch :expr/args :where-sub/where :where/triple :triple/vec]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:filter (not-exists [[?z :far/lands _1]])] @@ -167,7 +167,7 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-update :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}] :prev-bnodes #{'_1}}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]]]} @@ -176,9 +176,9 @@ (vb/validate-bnodes #{'_1})))) (is (= [[#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:update/modify :insert]} + :path [:update/modify :insert :triple/vec]} {:bnode '_1 - :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}]}]] + :path [:update/modify :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}]}]] (->> '[{:insert [[?x :foo/bar _1]] :where [[:where [[?x :foo/bar _1]]]]}] (map (partial s/conform us/update-spec)) @@ -198,9 +198,9 @@ ::vb/dupe-bnodes-update :errors [{:bnode '_1 - :path [:update/modify :insert]} + :path [:update/modify :insert :triple/vec]} {:bnode '_2 - :path [:update/modify :where :where-sub/where 0 :where/special :where/recurse :where-sub/where 0 :where/triple]}] + :path [:update/modify :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}] :prev-bnodes #{'_1 '_2}}] (->> '[{:insert [[?x :foo/bar _1]] From 2ef7aafcbb79437dcac5e489a415843e49eeed81 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 10:13:49 -0500 Subject: [PATCH 08/34] Add nform-list spec --- .../com/yetanalytics/flint/spec/triple.cljc | 71 +++++++++++-------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 22dbc32..0e79db6 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -127,8 +127,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; NOTE: Subjects can be non-IRIs in SPARQL, but not in RDF -;; NOTE: RDF collections not supported (yet?) - ;; single-branch `s/or`s are used to conform values ;; Object @@ -187,27 +185,19 @@ ;; Subject Predicate Object #?(:clj - (defmacro make-nform-spec - ([subj-spec pred-objs-spec] - `(s/or :triple/spo - (s/map-of ~subj-spec (s/and ~pred-objs-spec not-empty) - :conform-keys true :into []))) - ([subj-spec subj-list-spec pred-objs-spec] - `(s/or :triple/spo - (s/map-of ~subj-spec (s/and ~pred-objs-spec not-empty) - :conform-keys true :into []) - :triple/spo-list - (s/map-of ~subj-list-spec ~pred-objs-spec - :conform-keys true :into []))))) + (defmacro make-nform-spec [subj-spec pred-objs-spec] + `(s/or :triple/spo + (s/map-of ~subj-spec (s/and ~pred-objs-spec not-empty) + :conform-keys true :into [])))) (def normal-form-spec - (make-nform-spec subj-spec list-spec pred-objs-spec)) + (make-nform-spec subj-spec pred-objs-spec)) (def normal-form-nopath-spec - (make-nform-spec subj-spec list-spec pred-objs-nopath-spec)) + (make-nform-spec subj-spec pred-objs-nopath-spec)) (def normal-form-novar-spec - (make-nform-spec subj-novar-spec list-novar-spec pred-objs-novar-spec)) + (make-nform-spec subj-novar-spec pred-objs-novar-spec)) (def normal-form-noblank-spec (make-nform-spec subj-noblank-spec pred-objs-noblank-spec)) @@ -215,6 +205,24 @@ (def normal-form-novar-noblank-spec (make-nform-spec subj-novar-noblank-spec pred-objs-novar-noblank-spec)) +;; Subject Predicate Object (List) + +#?(:clj + (defmacro make-nform-list-spec + [subj-list-spec pred-objs-spec] + `(s/or :triple/spo-list + (s/map-of ~subj-list-spec ~pred-objs-spec + :conform-keys true :into [])))) + +(def normal-form-list-spec + (make-nform-list-spec list-spec pred-objs-spec)) + +(def normal-form-list-nopath-spec + (make-nform-list-spec list-spec pred-objs-nopath-spec)) + +(def normal-form-list-novar-spec + (make-nform-list-spec list-spec pred-objs-novar-spec)) + ;; Triple Vectors (def triple-vec-spec @@ -235,16 +243,19 @@ ;; Triples (def triple-spec - (s/or :triple/vec triple-vec-spec - :triple/nform normal-form-spec)) + (s/or :triple/vec triple-vec-spec + :triple/nform normal-form-spec + :triple/nform-list normal-form-list-spec)) (def triple-nopath-spec - (s/or :triple/vec triple-vec-nopath-spec - :triple/nform normal-form-nopath-spec)) + (s/or :triple/vec triple-vec-nopath-spec + :triple/nform normal-form-nopath-spec + :triple/nform-list normal-form-list-nopath-spec)) (def triple-novar-spec - (s/or :triple/vec triple-vec-novar-spec - :triple/nform normal-form-novar-spec)) + (s/or :triple/vec triple-vec-novar-spec + :triple/nform normal-form-novar-spec + :triple/nform-list normal-form-list-nopath-spec)) (def triple-noblank-spec (s/or :triple/vec triple-vec-noblank-spec @@ -300,15 +311,17 @@ ;; Collection of Quads (for UPDATE) (def quad-coll-nopath-spec - (s/coll-of (s/or :triple/vec triple-vec-nopath-spec - :triple/nform normal-form-nopath-spec - :triple/quads quad-nopath-spec) + (s/coll-of (s/or :triple/vec triple-vec-nopath-spec + :triple/nform normal-form-nopath-spec + :triple/nform-list normal-form-list-nopath-spec + :triple/quads quad-nopath-spec) :kind vector?)) (def quad-coll-novar-spec - (s/coll-of (s/or :triple/vec triple-vec-novar-spec - :triple/nform normal-form-novar-spec - :triple/quads quad-novar-spec) + (s/coll-of (s/or :triple/vec triple-vec-novar-spec + :triple/nform normal-form-novar-spec + :triple/nform-list normal-form-list-novar-spec + :triple/quads quad-novar-spec) :kind vector?)) (def quad-coll-noblank-spec From 0b5b78f7e7b2dedff1454b4560f0cc83ecc1b95d Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 11:30:01 -0500 Subject: [PATCH 09/34] Fix nform specs and remove :triple/object --- .../com/yetanalytics/flint/spec/triple.cljc | 103 +++++++++--------- .../yetanalytics/flint/spec/triple_test.cljc | 20 ++-- .../flint/validate/bnode_test.cljc | 16 +-- .../flint/validate/prefix_test.cljc | 2 +- 4 files changed, 70 insertions(+), 71 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 0e79db6..9013340 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -23,6 +23,37 @@ ;; - DELETE DATA ;; - DELETE +;; Lists + +;; List entries have the same spec as objects + `:triple/list` + +;; Since lists are constructed out of blank nodes, we do not allow list +;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. + +(declare list-spec) +(declare list-novar-spec) + +(def list-entry-spec + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-spec)) + +(def list-entry-novar-spec + (s/or :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-novar-spec)) + +(def list-spec + (s/coll-of list-entry-spec :kind list?)) + +(def list-novar-spec + (s/coll-of list-entry-novar-spec :kind list?)) + ;; Subjects (def subj-spec @@ -31,11 +62,17 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec)) +(def subj-list-spec + (s/or :triple/list list-spec)) + (def subj-novar-spec (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec)) +(def subj-list-novar-spec + (s/or :triple/list list-novar-spec)) + (def subj-noblank-spec (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec @@ -72,13 +109,15 @@ :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec)) + :ax/literal ax/literal-spec + :triple/list list-spec)) (def obj-novar-spec (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec)) + :ax/literal ax/literal-spec + :triple/list list-novar-spec)) (def obj-noblank-spec (s/or :ax/var ax/variable-spec @@ -91,37 +130,6 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/literal ax/literal-spec)) -;; Lists - -;; List entries have the same spec as objects + `:triple/list` - -;; Since lists are constructed out of blank nodes, we do not allow list -;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. - -(declare list-spec) -(declare list-novar-spec) - -(def list-entry-spec - (s/or :ax/var ax/variable-spec - :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-spec)) - -(def list-entry-novar-spec - (s/or :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-novar-spec)) - -(def list-spec - (s/coll-of list-entry-spec :kind list?)) - -(def list-novar-spec - (s/coll-of list-entry-novar-spec :kind list?)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Combo Specs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -134,24 +142,16 @@ #?(:clj (defmacro make-obj-spec ([obj-spec] - `(s/or :triple/o - (s/coll-of (s/or :triple/object ~obj-spec) - :min-count 1 - :kind set? - :into []))) - ([obj-spec obj-list-spec] - `(s/or :triple/o - (s/coll-of (s/or :triple/object ~obj-spec - :triple/list ~obj-list-spec) - :min-count 1 - :kind set? - :into []))))) + `(s/or :triple/o (s/coll-of ~obj-spec + :min-count 1 + :kind set? + :into []))))) (def obj-set-spec - (make-obj-spec obj-spec list-spec)) + (make-obj-spec obj-spec)) (def obj-set-novar-spec - (make-obj-spec obj-novar-spec list-novar-spec)) + (make-obj-spec obj-novar-spec)) (def obj-set-noblank-spec (make-obj-spec obj-noblank-spec)) @@ -208,20 +208,19 @@ ;; Subject Predicate Object (List) #?(:clj - (defmacro make-nform-list-spec - [subj-list-spec pred-objs-spec] + (defmacro make-nform-list-spec [subj-list-spec pred-objs-spec] `(s/or :triple/spo-list (s/map-of ~subj-list-spec ~pred-objs-spec :conform-keys true :into [])))) (def normal-form-list-spec - (make-nform-list-spec list-spec pred-objs-spec)) + (make-nform-list-spec subj-list-spec pred-objs-spec)) (def normal-form-list-nopath-spec - (make-nform-list-spec list-spec pred-objs-nopath-spec)) + (make-nform-list-spec subj-list-spec pred-objs-nopath-spec)) (def normal-form-list-novar-spec - (make-nform-list-spec list-spec pred-objs-novar-spec)) + (make-nform-list-spec subj-list-novar-spec pred-objs-novar-spec)) ;; Triple Vectors diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index b7b37c2..930c7d2 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -8,23 +8,23 @@ (is (= '[:triple/spo [[[:ax/var ?s] [:triple/po [[[:ax/var ?p] - [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]] + [:triple/o [[:ax/var ?o]]]]]]]]] (s/conform ts/normal-form-spec '{?s {?p #{?o}}}))) (is (= '[:triple/spo [[[:ax/var ?s1] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]] [[:ax/var ?p2] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]] [[:ax/var ?s2] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]] [[:ax/var ?p2] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]]]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]]]] (s/conform ts/normal-form-spec '{?s1 {?p1 #{?o1 ?o2} ?p2 #{?o1 ?o2}} ?s2 {?p1 #{?o1 ?o2} @@ -40,7 +40,7 @@ [:path/paths [[:path/terminal [:ax/prefix-iri :x/one]] [:path/terminal [:ax/prefix-iri :x/two]]]]]]] - [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]] + [:triple/o [[:ax/var ?o]]]]]]]]] (s/conform ts/normal-form-spec '{?s {(cat :x/one :x/two) #{?o}}}))) (is (= '[[:ax/var ?s] diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index b654775..e0f3077 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -64,13 +64,13 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]}]}] (->> '{:select [?x] :where [[:where [{?x {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -85,13 +85,13 @@ {:bnode '_2 :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o :triple/object]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]}]}] (->> '{:select [?x] :where [[:where [{_2 {:foo/bar #{_1} :baz/qux #{_1}}}]] diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index 7a18e07..e55ded1 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -50,7 +50,7 @@ (is (= [{:iri :baz/Qux :prefix :baz :prefixes {:rdf ""} - :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/nform :triple/spo :triple/po :triple/o :triple/object :ax/prefix-iri]} + :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/nform :triple/spo :triple/po :triple/o :ax/prefix-iri]} {:iri :baz/Quu :prefix :baz :prefixes {:rdf ""} From 8604bccfed86faca88d2be598498296ce7a08b25 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 12:15:10 -0500 Subject: [PATCH 10/34] Remove :triple/object from format.triple tests --- .../yetanalytics/flint/format/triple_test.cljc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index 0cefb51..bdfd798 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -17,19 +17,19 @@ [:triple/spo [[[:ax/iri ""] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]] [[:ax/var ?p2] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]] [[:ax/var ?s2] [:triple/po [[[:ax/var ?p1] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]] [[:ax/var ?p2] - [:triple/o [[:triple/object [:ax/var ?o1]] - [:triple/object [:ax/var ?o2]]]]]]]]]]] + [:triple/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]]]]] {:pretty? true}))) (is (= "?s ?p ?o ." (f/format-ast From f96cc07b068ca34cf8c64521ad08b38b74b74c95 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 12:15:27 -0500 Subject: [PATCH 11/34] Implement triple-vec-no-po and nform-no-po specs --- .../com/yetanalytics/flint/format/triple.cljc | 9 +- .../com/yetanalytics/flint/spec/triple.cljc | 86 ++++++++++++------- 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index f1df48d..2f255ff 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -16,9 +16,15 @@ (defmethod f/format-ast-node :triple/vec [_ [_ [s p o]]] (str s " " p " " o " .")) +(defmethod f/format-ast-node :triple/vec-no-po [_ [_ [s]]] + (str s " .")) + (defmethod f/format-ast-node :triple/nform [_ [_ nform]] nform) +(defmethod f/format-ast-node :triple/nform-no-po [_ [_ nform]] + nform) + (defn- format-spo-map [spo pretty?] (if pretty? (str (->> spo @@ -37,9 +43,6 @@ (defmethod f/format-ast-node :triple/spo [{:keys [pretty?]} [_ spo]] (format-spo-map spo pretty?)) -(defmethod f/format-ast-node :triple/spo-list [{:keys [pretty?]} [_ spo]] - (format-spo-map spo pretty?)) - (defmethod f/format-ast-node :triple/po [{:keys [pretty?]} [_ po]] (let [join-sep (if pretty? " ;\n" " ; ")] (->> po diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 9013340..0a80134 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -60,18 +60,20 @@ (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec)) + :ax/bnode ax/bnode-spec + :triple/list list-spec)) (def subj-list-spec - (s/or :triple/list list-spec)) + (s/or :triple/list list-spec)) (def subj-novar-spec (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec)) + :ax/bnode ax/bnode-spec + :triple/list list-spec)) (def subj-list-novar-spec - (s/or :triple/list list-novar-spec)) + (s/or :triple/list list-novar-spec)) (def subj-noblank-spec (s/or :ax/var ax/variable-spec @@ -102,7 +104,7 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/rdf-type ax/rdf-type-spec)) -;; Objects +;; Objects (includes Lists) (def obj-spec (s/or :ax/var ax/variable-spec @@ -165,7 +167,8 @@ (defmacro make-pred-objs-spec [pred-spec objs-spec] `(s/or :triple/po (s/map-of ~pred-spec ~objs-spec - :into [])))) + :into [] + :min-count 1)))) (def pred-objs-spec (make-pred-objs-spec pred-spec obj-set-spec)) @@ -187,7 +190,7 @@ #?(:clj (defmacro make-nform-spec [subj-spec pred-objs-spec] `(s/or :triple/spo - (s/map-of ~subj-spec (s/and ~pred-objs-spec not-empty) + (s/map-of ~subj-spec ~pred-objs-spec :conform-keys true :into [])))) (def normal-form-spec @@ -207,20 +210,27 @@ ;; Subject Predicate Object (List) +(def empty-map-spec + (s/map-of any? any? :max-count 0 :conform-keys true :into [])) + #?(:clj - (defmacro make-nform-list-spec [subj-list-spec pred-objs-spec] - `(s/or :triple/spo-list - (s/map-of ~subj-list-spec ~pred-objs-spec + (defmacro make-nform-no-po-spec [subj-list-spec] + `(s/or :triple/spo + (s/map-of ~subj-list-spec empty-map-spec :conform-keys true :into [])))) -(def normal-form-list-spec - (make-nform-list-spec subj-list-spec pred-objs-spec)) +(def normal-form-no-po-spec + (make-nform-no-po-spec subj-list-spec)) -(def normal-form-list-nopath-spec - (make-nform-list-spec subj-list-spec pred-objs-nopath-spec)) +(def normal-form-no-po-nopath-spec + (make-nform-no-po-spec subj-list-spec)) -(def normal-form-list-novar-spec - (make-nform-list-spec subj-list-novar-spec pred-objs-novar-spec)) +(def normal-form-no-po-novar-spec + (make-nform-no-po-spec subj-list-novar-spec)) + +(comment + (s/conform normal-form-no-po-spec + {'(?x ?y ?z) {}})) ;; Triple Vectors @@ -239,22 +249,36 @@ (def triple-vec-novar-noblank-spec (s/tuple subj-novar-noblank-spec pred-novar-spec obj-novar-noblank-spec)) +;; Triple Vectors (List, no predicates + objects) + +(def triple-vec-no-po-spec + (s/tuple subj-list-spec)) + +(def triple-vec-no-po-nopath-spec + (s/tuple subj-list-spec)) + +(def triple-vec-no-po-novar-spec + (s/tuple subj-list-novar-spec)) + ;; Triples (def triple-spec - (s/or :triple/vec triple-vec-spec - :triple/nform normal-form-spec - :triple/nform-list normal-form-list-spec)) + (s/or :triple/vec triple-vec-spec + :triple/vec-no-po triple-vec-no-po-spec + :triple/nform normal-form-spec + :triple/nform-no-po normal-form-no-po-spec)) (def triple-nopath-spec - (s/or :triple/vec triple-vec-nopath-spec - :triple/nform normal-form-nopath-spec - :triple/nform-list normal-form-list-nopath-spec)) + (s/or :triple/vec triple-vec-nopath-spec + :triple/vec-no-po triple-vec-no-po-nopath-spec + :triple/nform normal-form-nopath-spec + :triple/nform-no-po normal-form-no-po-nopath-spec)) (def triple-novar-spec - (s/or :triple/vec triple-vec-novar-spec - :triple/nform normal-form-novar-spec - :triple/nform-list normal-form-list-nopath-spec)) + (s/or :triple/vec triple-vec-novar-spec + :triple/vec-no-po triple-vec-no-po-novar-spec + :triple/nform normal-form-novar-spec + :triple/nform-no-po normal-form-no-po-nopath-spec)) (def triple-noblank-spec (s/or :triple/vec triple-vec-noblank-spec @@ -310,16 +334,18 @@ ;; Collection of Quads (for UPDATE) (def quad-coll-nopath-spec - (s/coll-of (s/or :triple/vec triple-vec-nopath-spec - :triple/nform normal-form-nopath-spec - :triple/nform-list normal-form-list-nopath-spec - :triple/quads quad-nopath-spec) + (s/coll-of (s/or :triple/vec triple-vec-nopath-spec + :triple/vec-no-po triple-vec-no-po-nopath-spec + :triple/nform normal-form-nopath-spec + :triple/nform-no-po normal-form-no-po-nopath-spec + :triple/quads quad-nopath-spec) :kind vector?)) (def quad-coll-novar-spec (s/coll-of (s/or :triple/vec triple-vec-novar-spec + :triple/vec-no-po triple-vec-no-po-novar-spec :triple/nform normal-form-novar-spec - :triple/nform-list normal-form-list-novar-spec + :triple/nform-list normal-form-no-po-novar-spec :triple/quads quad-novar-spec) :kind vector?)) From d88c5a59b1f87f633f113ce89c6b36c63926c13e Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 14:05:29 -0500 Subject: [PATCH 12/34] Remove :triple/object multimethod calls --- src/main/com/yetanalytics/flint/format/triple.cljc | 3 --- src/main/com/yetanalytics/flint/validate/variable.cljc | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 2f255ff..45a452e 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -4,9 +4,6 @@ [com.yetanalytics.flint.format.axiom] [com.yetanalytics.flint.format.path])) -(defmethod f/format-ast-node :triple/object [_ [_ object]] - object) - (defmethod f/format-ast-node :triple/list [_ [_ list]] (str "( " (cstr/join " " list) " )")) diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 4822fc5..27f8ecd 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -95,9 +95,6 @@ ;; Basic Graph Pattern -(defmethod get-scope-vars :triple/object [[_ object]] - (get-scope-vars object)) - (defmethod get-scope-vars :triple/list [[_ list]] (mapcat get-scope-vars list)) From db6c170fbaa112d15395f3c8a7687d38367e0102 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 14:05:46 -0500 Subject: [PATCH 13/34] Remove redundant :triple/nform kword --- .../com/yetanalytics/flint/format/triple.cljc | 15 ++-- .../com/yetanalytics/flint/spec/triple.cljc | 71 ++++++++-------- src/main/com/yetanalytics/flint/validate.cljc | 6 +- .../yetanalytics/flint/validate/variable.cljc | 18 ++--- .../flint/format/triple_test.cljc | 34 ++++---- .../flint/format/update_test.cljc | 33 ++++---- .../yetanalytics/flint/format/where_test.cljc | 11 +-- .../yetanalytics/flint/spec/triple_test.cljc | 80 ++++++++++--------- .../flint/validate/bnode_test.cljc | 20 ++--- .../flint/validate/prefix_test.cljc | 17 ++-- .../flint/validate/scope_test.cljc | 10 +-- 11 files changed, 153 insertions(+), 162 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 45a452e..66b92e9 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -16,12 +16,6 @@ (defmethod f/format-ast-node :triple/vec-no-po [_ [_ [s]]] (str s " .")) -(defmethod f/format-ast-node :triple/nform [_ [_ nform]] - nform) - -(defmethod f/format-ast-node :triple/nform-no-po [_ [_ nform]] - nform) - (defn- format-spo-map [spo pretty?] (if pretty? (str (->> spo @@ -37,16 +31,19 @@ (cstr/join " . ")) " ."))) -(defmethod f/format-ast-node :triple/spo [{:keys [pretty?]} [_ spo]] +(defmethod f/format-ast-node :triple.nform/spo [{:keys [pretty?]} [_ spo]] + (format-spo-map spo pretty?)) + +(defmethod f/format-ast-node :triple.nform/s [{:keys [pretty?]} [_ spo]] (format-spo-map spo pretty?)) -(defmethod f/format-ast-node :triple/po [{:keys [pretty?]} [_ po]] +(defmethod f/format-ast-node :triple.nform/po [{:keys [pretty?]} [_ po]] (let [join-sep (if pretty? " ;\n" " ; ")] (->> po (map (fn [[p o]] (str p " " o))) (cstr/join join-sep)))) -(defmethod f/format-ast-node :triple/o [_ [_ o]] +(defmethod f/format-ast-node :triple.nform/o [_ [_ o]] (->> o (cstr/join " , "))) (defn format-quads [quads pretty?] diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 0a80134..110cd5d 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -144,10 +144,7 @@ #?(:clj (defmacro make-obj-spec ([obj-spec] - `(s/or :triple/o (s/coll-of ~obj-spec - :min-count 1 - :kind set? - :into []))))) + `(s/coll-of ~obj-spec :min-count 1 :kind set? :into [])))) (def obj-set-spec (make-obj-spec obj-spec)) @@ -166,9 +163,9 @@ #?(:clj (defmacro make-pred-objs-spec [pred-spec objs-spec] - `(s/or :triple/po (s/map-of ~pred-spec ~objs-spec - :into [] - :min-count 1)))) + `(s/map-of ~pred-spec (s/or :triple.nform/o ~objs-spec) + :into [] + :min-count 1))) (def pred-objs-spec (make-pred-objs-spec pred-spec obj-set-spec)) @@ -189,9 +186,8 @@ #?(:clj (defmacro make-nform-spec [subj-spec pred-objs-spec] - `(s/or :triple/spo - (s/map-of ~subj-spec ~pred-objs-spec - :conform-keys true :into [])))) + `(s/map-of ~subj-spec (s/or :triple.nform/po ~pred-objs-spec) + :conform-keys true :into []))) (def normal-form-spec (make-nform-spec subj-spec pred-objs-spec)) @@ -215,9 +211,8 @@ #?(:clj (defmacro make-nform-no-po-spec [subj-list-spec] - `(s/or :triple/spo - (s/map-of ~subj-list-spec empty-map-spec - :conform-keys true :into [])))) + `(s/map-of ~subj-list-spec empty-map-spec + :conform-keys true :into []))) (def normal-form-no-po-spec (make-nform-no-po-spec subj-list-spec)) @@ -263,30 +258,30 @@ ;; Triples (def triple-spec - (s/or :triple/vec triple-vec-spec - :triple/vec-no-po triple-vec-no-po-spec - :triple/nform normal-form-spec - :triple/nform-no-po normal-form-no-po-spec)) + (s/or :triple/vec triple-vec-spec + :triple/vec-no-po triple-vec-no-po-spec + :triple.nform/spo normal-form-spec + :triple.nform/s normal-form-no-po-spec)) (def triple-nopath-spec - (s/or :triple/vec triple-vec-nopath-spec - :triple/vec-no-po triple-vec-no-po-nopath-spec - :triple/nform normal-form-nopath-spec - :triple/nform-no-po normal-form-no-po-nopath-spec)) + (s/or :triple/vec triple-vec-nopath-spec + :triple/vec-no-po triple-vec-no-po-nopath-spec + :triple.nform/spo normal-form-nopath-spec + :triple.nform/s normal-form-no-po-nopath-spec)) (def triple-novar-spec - (s/or :triple/vec triple-vec-novar-spec - :triple/vec-no-po triple-vec-no-po-novar-spec - :triple/nform normal-form-novar-spec - :triple/nform-no-po normal-form-no-po-nopath-spec)) + (s/or :triple/vec triple-vec-novar-spec + :triple/vec-no-po triple-vec-no-po-novar-spec + :triple.nform/spo normal-form-novar-spec + :triple.nform/s normal-form-no-po-nopath-spec)) (def triple-noblank-spec - (s/or :triple/vec triple-vec-noblank-spec - :triple/nform normal-form-noblank-spec)) + (s/or :triple/vec triple-vec-noblank-spec + :triple.nform/spo normal-form-noblank-spec)) (def triple-novar-noblank-spec - (s/or :triple/vec triple-vec-novar-noblank-spec - :triple/nform normal-form-novar-noblank-spec)) + (s/or :triple/vec triple-vec-novar-noblank-spec + :triple.nform/spo normal-form-novar-noblank-spec)) ;; Collection of Triples @@ -334,29 +329,29 @@ ;; Collection of Quads (for UPDATE) (def quad-coll-nopath-spec - (s/coll-of (s/or :triple/vec triple-vec-nopath-spec - :triple/vec-no-po triple-vec-no-po-nopath-spec - :triple/nform normal-form-nopath-spec - :triple/nform-no-po normal-form-no-po-nopath-spec - :triple/quads quad-nopath-spec) + (s/coll-of (s/or :triple/vec triple-vec-nopath-spec + :triple/vec-no-po triple-vec-no-po-nopath-spec + :triple.nform/spo normal-form-nopath-spec + :triple.nform/s normal-form-no-po-nopath-spec + :triple/quads quad-nopath-spec) :kind vector?)) (def quad-coll-novar-spec (s/coll-of (s/or :triple/vec triple-vec-novar-spec :triple/vec-no-po triple-vec-no-po-novar-spec - :triple/nform normal-form-novar-spec - :triple/nform-list normal-form-no-po-novar-spec + :triple.nform/spo normal-form-novar-spec + :triple.nform/s normal-form-no-po-novar-spec :triple/quads quad-novar-spec) :kind vector?)) (def quad-coll-noblank-spec (s/coll-of (s/or :triple/vec triple-vec-noblank-spec - :triple/nform normal-form-noblank-spec + :triple.nform/spo normal-form-noblank-spec :triple/quads quad-noblank-spec) :kind vector?)) (def quad-coll-novar-noblank-spec (s/coll-of (s/or :triple/vec triple-vec-novar-noblank-spec - :triple/nform normal-form-novar-noblank-spec + :triple.nform/spo normal-form-novar-noblank-spec :triple/quads quad-novar-noblank-spec) :kind vector?)) diff --git a/src/main/com/yetanalytics/flint/validate.cljc b/src/main/com/yetanalytics/flint/validate.cljc index c3d6fc0..c58ee90 100644 --- a/src/main/com/yetanalytics/flint/validate.cljc +++ b/src/main/com/yetanalytics/flint/validate.cljc @@ -11,13 +11,13 @@ [:where/triple [:triple/vec ...]] => 0 [:where/triple - [:triple/nform ...]] => 0 + [:triple.nform/spo ...]] => 0 [:where/special [:where/filter ...]] => 0 ; FILTERs don't divide BGPs [:where/special [:where/optional ...]] => X ; BGP divider [:where/triple - [:triple/nform ...]] => 1 + [:triple.nform/spo ...]] => 1 " [loc] (let [?left-node (some-> loc zip/left zip/node) @@ -49,7 +49,7 @@ (defn- ast-children [[k children]] (cond - (#{:triple/spo :triple/po} k) + (#{:triple.nform/spo :triple.nform/po} k) (apply concat children) (or (and (vector? children) (keyword? (first children))) diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 27f8ecd..aa38ddc 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -101,10 +101,10 @@ (defmethod get-scope-vars :triple/vec [[_ spo]] (mapcat get-scope-vars spo)) -(defmethod get-scope-vars :triple/o [[_ o]] +(defmethod get-scope-vars :triple.nform/o [[_ o]] (mapcat get-scope-vars o)) -(defmethod get-scope-vars :triple/po [[_ po]] +(defmethod get-scope-vars :triple.nform/po [[_ po]] (reduce-kv (fn [acc p o] (apply concat acc (get-scope-vars p) @@ -112,7 +112,7 @@ [] po)) -(defmethod get-scope-vars :triple/spo [[_ spo]] +(defmethod get-scope-vars :triple.nform/spo [[_ spo]] (reduce-kv (fn [acc s po] (apply concat acc (get-scope-vars s) @@ -120,16 +120,8 @@ [] spo)) -(defmethod get-scope-vars :triple/spo-list [[_ spo]] - (reduce-kv (fn [acc s po] (apply concat - acc - (mapcat get-scope-vars s) - (map get-scope-vars po))) - [] - spo)) - -(defmethod get-scope-vars :triple/nform [[_ nform]] - (get-scope-vars nform)) +(defmethod get-scope-vars :triple.nform/s [[_ s]] + (get-scope-vars s)) ;; Path diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index bdfd798..af71e1c 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -13,23 +13,23 @@ "?s2 ?p1 ?o1 , ?o2 ;" " ?p2 ?o1 , ?o2 ."]) (f/format-ast - '[:triple/nform - [:triple/spo [[[:ax/iri ""] - [:triple/po - [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]] - [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]]]]] - [[:ax/var ?s2] - [:triple/po - [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]] - [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]]]]]]]] + '[:triple.nform/spo + [[[:ax/iri ""] + [:triple.nform/po + [[[:ax/var ?p1] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]] + [[:ax/var ?p2] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]] + [[:ax/var ?s2] + [:triple.nform/po + [[[:ax/var ?p1] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]] + [[:ax/var ?p2] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]]]] {:pretty? true}))) (is (= "?s ?p ?o ." (f/format-ast diff --git a/src/test/com/yetanalytics/flint/format/update_test.cljc b/src/test/com/yetanalytics/flint/format/update_test.cljc index 4f21855..e5ccf89 100644 --- a/src/test/com/yetanalytics/flint/format/update_test.cljc +++ b/src/test/com/yetanalytics/flint/format/update_test.cljc @@ -54,13 +54,15 @@ [[:delete-where [[:triple/vec [[:ax/var ?x] [:ax/var ?y] [:ax/var ?z]]] - [:triple/nform - [:triple/spo [[[:ax/var ?i] - [:triple/po [[[:ax/var ?j] - [:triple/o [[:triple/object [:ax/var ?k]]]]]]]] - [[:ax/var ?s] - [:triple/po [[[:ax/var ?p] - [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]]] + [:triple.nform/spo + [[[:ax/var ?i] + [:triple.nform/po + [[[:ax/var ?j] + [:triple.nform/o [[:ax/var ?k]]]]]]] + [[:ax/var ?s] + [:triple.nform/po + [[[:ax/var ?p] + [:triple.nform/o [[:ax/var ?o]]]]]]]]] [:triple/quads [[:ax/iri ""] [:triple/quad-triples @@ -103,14 +105,15 @@ [:using [:update/iri [:ax/iri ""]]] [:where [:where-sub/where [[:where/triple - [:triple/nform - [:triple/spo - [[[:ax/var ?x] - [:triple/po [[[:ax/var ?y] - [:triple/o [[:triple/object [:ax/var ?z]]]]]]]] - [[:ax/var ?a] - [:triple/po [[[:ax/var ?b] - [:triple/o [[:triple/object [:ax/var ?c]]]]]]]]]]]]]]]]] + [:triple.nform/spo + [[[:ax/var ?x] + [:triple.nform/po + [[[:ax/var ?y] + [:triple.nform/o [[:ax/var ?z]]]]]]] + [[:ax/var ?a] + [:triple.nform/po + [[[:ax/var ?b] + [:triple.nform/o [[:ax/var ?c]]]]]]]]]]]]]]] format-ast)))) (testing "Formatting graph management updates" (testing "- LOAD" diff --git a/src/test/com/yetanalytics/flint/format/where_test.cljc b/src/test/com/yetanalytics/flint/format/where_test.cljc index 34dd39a..8d16773 100644 --- a/src/test/com/yetanalytics/flint/format/where_test.cljc +++ b/src/test/com/yetanalytics/flint/format/where_test.cljc @@ -55,11 +55,12 @@ [:triple/vec [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]]] [:where/triple - [:triple/nform - [:triple/spo [[[:ax/var ?s2] - [:triple/po [[[:ax/var ?p2] - [:triple/o [[:triple/object [:ax/var ?o2a]] - [:triple/object [:ax/var ?o2b]]]]]]]]]]]] + [:triple.nform/spo + [[[:ax/var ?s2] + [:triple.nform/po + [[[:ax/var ?p2] + [:triple.nform/o [[:ax/var ?o2a] + [:ax/var ?o2b]]]]]]]]]] [:where/special [:where/recurse [:where-sub/where diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index 930c7d2..96254a8 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -5,58 +5,62 @@ (deftest conform-triple-test (testing "Conforming triples" - (is (= '[:triple/spo + (is (= '[:triple.nform/spo [[[:ax/var ?s] - [:triple/po [[[:ax/var ?p] - [:triple/o [[:ax/var ?o]]]]]]]]] - (s/conform ts/normal-form-spec '{?s {?p #{?o}}}))) - (is (= '[:triple/spo + [:triple.nform/po + [[[:ax/var ?p] + [:triple.nform/o [[:ax/var ?o]]]]]]]]] + (s/conform ts/triple-spec '{?s {?p #{?o}}}))) + (is (= '[:triple.nform/spo [[[:ax/var ?s1] - [:triple/po [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]] - [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]]]]] + [:triple.nform/po + [[[:ax/var ?p1] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]] + [[:ax/var ?p2] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]] [[:ax/var ?s2] - [:triple/po [[[:ax/var ?p1] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]] - [[:ax/var ?p2] - [:triple/o [[:ax/var ?o1] - [:ax/var ?o2]]]]]]]]] - (s/conform ts/normal-form-spec '{?s1 {?p1 #{?o1 ?o2} - ?p2 #{?o1 ?o2}} - ?s2 {?p1 #{?o1 ?o2} - ?p2 #{?o1 ?o2}}}))) - (is (= '[[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]] - (s/conform ts/triple-vec-spec '[?s ?p ?o]))) + [:triple.nform/po + [[[:ax/var ?p1] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]] + [[:ax/var ?p2] + [:triple.nform/o [[:ax/var ?o1] + [:ax/var ?o2]]]]]]]]] + (s/conform ts/triple-spec '{?s1 {?p1 #{?o1 ?o2} + ?p2 #{?o1 ?o2}} + ?s2 {?p1 #{?o1 ?o2} + ?p2 #{?o1 ?o2}}}))) + (is (= '[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] + (s/conform ts/triple-spec '[?s ?p ?o]))) (testing "with and without paths" - (is (= '[:triple/spo + (is (= '[:triple.nform/spo [[[:ax/var ?s] - [:triple/po + [:triple.nform/po [[[:triple/path [:path/branch [[:path/op cat] [:path/paths [[:path/terminal [:ax/prefix-iri :x/one]] [:path/terminal [:ax/prefix-iri :x/two]]]]]]] - [:triple/o [[:ax/var ?o]]]]]]]]] - (s/conform ts/normal-form-spec + [:triple.nform/o [[:ax/var ?o]]]]]]]]] + (s/conform ts/triple-spec '{?s {(cat :x/one :x/two) #{?o}}}))) - (is (= '[[:ax/var ?s] - [:triple/path - [:path/branch [[:path/op cat] - [:path/paths - [[:path/terminal [:ax/prefix-iri :x/one]] - [:path/terminal [:ax/prefix-iri :x/two]]]]]]] - [:ax/var ?o]] - (s/conform ts/triple-vec-spec + (is (= '[:triple/vec + [[:ax/var ?s] + [:triple/path + [:path/branch [[:path/op cat] + [:path/paths + [[:path/terminal [:ax/prefix-iri :x/one]] + [:path/terminal [:ax/prefix-iri :x/two]]]]]]] + [:ax/var ?o]]] + (s/conform ts/triple-spec '[?s (cat :x/one :x/two) ?o]))) - (is (not (s/valid? ts/normal-form-nopath-spec + (is (not (s/valid? ts/triple-nopath-spec '{?s {(cat :x/one :x/two) #{?o}}}))) (is (->> '{?s {(cat :x/one :x/two) #{?o}}} - (s/explain-data ts/normal-form-nopath-spec) + (s/explain-data ts/triple-nopath-spec) ::s/problems - (filter #(-> % :path first (= :triple/spo))) + (filter #(-> % :path first (= :triple.nform/spo))) (map :val) (every? (partial = '(cat :x/one :x/two)))))))) diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index e0f3077..59ee0f5 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -64,13 +64,13 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]}]}] (->> '{:select [?x] :where [[:where [{?x {:foo/bar #{_1} :baz/qux #{_1}}}]] @@ -81,17 +81,17 @@ vb/validate-bnodes))) (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_2 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo]} {:bnode '_2 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/nform :triple/spo :triple/po :triple/o]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.nform/spo :triple.nform/po :triple.nform/o]}]}] (->> '{:select [?x] :where [[:where [{_2 {:foo/bar #{_1} :baz/qux #{_1}}}]] diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index e55ded1..f885277 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -50,16 +50,15 @@ (is (= [{:iri :baz/Qux :prefix :baz :prefixes {:rdf ""} - :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/nform :triple/spo :triple/po :triple/o :ax/prefix-iri]} + :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple.nform/spo :triple.nform/po :triple.nform/o :ax/prefix-iri]} {:iri :baz/Quu :prefix :baz :prefixes {:rdf ""} :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/vec :ax/prefix-iri]}] - (->> - {:prefixes {:rdf ""} - :insert-data [[:graph "" - [{"" {:rdf/type #{:baz/Qux}}} - ["" :rdf/type :baz/Quu]]]]} - (s/conform us/update-spec) - v/collect-nodes - (vp/validate-prefixes {:rdf ""})))))) + (->> {:prefixes {:rdf ""} + :insert-data [[:graph "" + [{"" {:rdf/type #{:baz/Qux}}} + ["" :rdf/type :baz/Quu]]]]} + (s/conform us/update-spec) + v/collect-nodes + (vp/validate-prefixes {:rdf ""})))))) diff --git a/src/test/com/yetanalytics/flint/validate/scope_test.cljc b/src/test/com/yetanalytics/flint/validate/scope_test.cljc index d2f6438..80503a2 100644 --- a/src/test/com/yetanalytics/flint/validate/scope_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/scope_test.cljc @@ -41,11 +41,11 @@ [:ax/var ?z]]]))) (is (= '[?s ?p ?o] (vv/get-scope-vars - '[:triple/nform - [:triple/spo - [[[:ax/var ?s] - [:triple/po [[[:ax/var ?p] - [:triple/o [[:triple/object [:ax/var ?o]]]]]]]]]]]))) + '[:triple.nform/spo + [[[:ax/var ?s] + [:triple.nform/po + [[[:ax/var ?p] + [:triple.nform/o [[:ax/var ?o]]]]]]]]]))) (is (= '[?x ?y ?z] (vv/get-scope-vars '[:where-sub/where From d1c35b2164a8fdf2b64cd9ae1ba3fb79b88ec841 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 14:14:30 -0500 Subject: [PATCH 14/34] Replace :triple/vec with :triple.vec/spo --- .../com/yetanalytics/flint/format/triple.cljc | 4 +- .../com/yetanalytics/flint/spec/triple.cljc | 42 +++++++-------- src/main/com/yetanalytics/flint/validate.cljc | 2 +- .../yetanalytics/flint/validate/variable.cljc | 5 +- .../yetanalytics/flint/format/expr_test.cljc | 12 ++--- .../yetanalytics/flint/format/query_test.cljc | 48 ++++++++--------- .../flint/format/triple_test.cljc | 2 +- .../flint/format/update_test.cljc | 28 +++++----- .../yetanalytics/flint/format/where_test.cljc | 22 ++++---- .../yetanalytics/flint/spec/expr_test.cljc | 6 +-- .../yetanalytics/flint/spec/query_test.cljc | 6 +-- .../yetanalytics/flint/spec/triple_test.cljc | 4 +- .../yetanalytics/flint/spec/update_test.cljc | 24 ++++----- .../yetanalytics/flint/spec/where_test.cljc | 34 ++++++------ .../flint/validate/bnode_test.cljc | 40 +++++++------- .../flint/validate/prefix_test.cljc | 10 ++-- .../flint/validate/scope_test.cljc | 54 +++++++++---------- 17 files changed, 171 insertions(+), 172 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 66b92e9..196edc4 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -10,10 +10,10 @@ (defmethod f/format-ast-node :triple/path [_ [_ path]] path) -(defmethod f/format-ast-node :triple/vec [_ [_ [s p o]]] +(defmethod f/format-ast-node :triple.vec/spo [_ [_ [s p o]]] (str s " " p " " o " .")) -(defmethod f/format-ast-node :triple/vec-no-po [_ [_ [s]]] +(defmethod f/format-ast-node :triple.vec/s [_ [_ [s]]] (str s " .")) (defn- format-spo-map [spo pretty?] diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 110cd5d..c83821f 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -223,10 +223,6 @@ (def normal-form-no-po-novar-spec (make-nform-no-po-spec subj-list-novar-spec)) -(comment - (s/conform normal-form-no-po-spec - {'(?x ?y ?z) {}})) - ;; Triple Vectors (def triple-vec-spec @@ -258,29 +254,29 @@ ;; Triples (def triple-spec - (s/or :triple/vec triple-vec-spec - :triple/vec-no-po triple-vec-no-po-spec + (s/or :triple.vec/spo triple-vec-spec + :triple.vec/s triple-vec-no-po-spec :triple.nform/spo normal-form-spec :triple.nform/s normal-form-no-po-spec)) (def triple-nopath-spec - (s/or :triple/vec triple-vec-nopath-spec - :triple/vec-no-po triple-vec-no-po-nopath-spec + (s/or :triple.vec/spo triple-vec-nopath-spec + :triple.vec/s triple-vec-no-po-nopath-spec :triple.nform/spo normal-form-nopath-spec :triple.nform/s normal-form-no-po-nopath-spec)) (def triple-novar-spec - (s/or :triple/vec triple-vec-novar-spec - :triple/vec-no-po triple-vec-no-po-novar-spec + (s/or :triple.vec/spo triple-vec-novar-spec + :triple.vec/s triple-vec-no-po-novar-spec :triple.nform/spo normal-form-novar-spec :triple.nform/s normal-form-no-po-nopath-spec)) (def triple-noblank-spec - (s/or :triple/vec triple-vec-noblank-spec + (s/or :triple.vec/spo triple-vec-noblank-spec :triple.nform/spo normal-form-noblank-spec)) (def triple-novar-noblank-spec - (s/or :triple/vec triple-vec-novar-noblank-spec + (s/or :triple.vec/spo triple-vec-novar-noblank-spec :triple.nform/spo normal-form-novar-noblank-spec)) ;; Collection of Triples @@ -329,29 +325,29 @@ ;; Collection of Quads (for UPDATE) (def quad-coll-nopath-spec - (s/coll-of (s/or :triple/vec triple-vec-nopath-spec - :triple/vec-no-po triple-vec-no-po-nopath-spec + (s/coll-of (s/or :triple.vec/spo triple-vec-nopath-spec + :triple.vec/s triple-vec-no-po-nopath-spec :triple.nform/spo normal-form-nopath-spec :triple.nform/s normal-form-no-po-nopath-spec :triple/quads quad-nopath-spec) :kind vector?)) (def quad-coll-novar-spec - (s/coll-of (s/or :triple/vec triple-vec-novar-spec - :triple/vec-no-po triple-vec-no-po-novar-spec - :triple.nform/spo normal-form-novar-spec - :triple.nform/s normal-form-no-po-novar-spec - :triple/quads quad-novar-spec) + (s/coll-of (s/or :triple.vec/spo triple-vec-novar-spec + :triple.vec/s triple-vec-no-po-novar-spec + :triple.nform/spo normal-form-novar-spec + :triple.nform/s normal-form-no-po-novar-spec + :triple/quads quad-novar-spec) :kind vector?)) (def quad-coll-noblank-spec - (s/coll-of (s/or :triple/vec triple-vec-noblank-spec + (s/coll-of (s/or :triple.vec/spo triple-vec-noblank-spec :triple.nform/spo normal-form-noblank-spec - :triple/quads quad-noblank-spec) + :triple/quads quad-noblank-spec) :kind vector?)) (def quad-coll-novar-noblank-spec - (s/coll-of (s/or :triple/vec triple-vec-novar-noblank-spec + (s/coll-of (s/or :triple.vec/spo triple-vec-novar-noblank-spec :triple.nform/spo normal-form-novar-noblank-spec - :triple/quads quad-novar-noblank-spec) + :triple/quads quad-novar-noblank-spec) :kind vector?)) diff --git a/src/main/com/yetanalytics/flint/validate.cljc b/src/main/com/yetanalytics/flint/validate.cljc index c58ee90..df81659 100644 --- a/src/main/com/yetanalytics/flint/validate.cljc +++ b/src/main/com/yetanalytics/flint/validate.cljc @@ -9,7 +9,7 @@ subquery): [:where/triple - [:triple/vec ...]] => 0 + [:triple.vec/spo ...]] => 0 [:where/triple [:triple.nform/spo ...]] => 0 [:where/special diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index aa38ddc..3d048c2 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -98,9 +98,12 @@ (defmethod get-scope-vars :triple/list [[_ list]] (mapcat get-scope-vars list)) -(defmethod get-scope-vars :triple/vec [[_ spo]] +(defmethod get-scope-vars :triple.vec/spo [[_ spo]] (mapcat get-scope-vars spo)) +(defmethod get-scope-vars :triple.vec/s [[_ s]] + (get-scope-vars s)) + (defmethod get-scope-vars :triple.nform/o [[_ o]] (mapcat get-scope-vars o)) diff --git a/src/test/com/yetanalytics/flint/format/expr_test.cljc b/src/test/com/yetanalytics/flint/format/expr_test.cljc index ce61151..504b118 100644 --- a/src/test/com/yetanalytics/flint/format/expr_test.cljc +++ b/src/test/com/yetanalytics/flint/format/expr_test.cljc @@ -180,17 +180,17 @@ (->> '[:expr/branch [[:expr/op exists] [:expr/args [[:where-sub/where [:where/triple - [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]]] + [[:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]]] format-ast))) (is (= "NOT EXISTS {\n ?x ?y ?z .\n}" (->> '[:expr/branch [[:expr/op not-exists] [:expr/args [[:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]]] format-ast))))) (deftest format-expr-as-var-test diff --git a/src/test/com/yetanalytics/flint/format/query_test.cljc b/src/test/com/yetanalytics/flint/format/query_test.cljc index b7191cc..b08d170 100644 --- a/src/test/com/yetanalytics/flint/format/query_test.cljc +++ b/src/test/com/yetanalytics/flint/format/query_test.cljc @@ -24,9 +24,9 @@ [:select [:select/var-or-exprs [[:ax/var ?x]]]] [:from [:ax/iri ""]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:order-by [[:mod/asc-desc [[:mod/op asc] [:mod/asc-desc-expr [:expr/terminal [:ax/var ?y]]]]]]] @@ -43,14 +43,14 @@ " ?x ?y ?z ." "}"]) (->> '[:query/construct - [[:construct [[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]] + [[:construct [[:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]] [:from [:ax/iri ""]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["CONSTRUCT" "FROM " @@ -61,9 +61,9 @@ [[:construct []] [:from [:ax/iri ""]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["CONSTRUCT" "WHERE {" @@ -72,9 +72,9 @@ (->> '[:query/construct [[:construct []] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast)))) (testing "Formatting DESCRIBE queries" (is (= (cstr/join "\n" ["DESCRIBE ?x ?y" @@ -88,9 +88,9 @@ [:from-named [[:ax/iri ""] [:ax/iri ""]]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast)))) (testing "Formatting ASK queries" (is (= (cstr/join "\n" ["ASK" @@ -104,9 +104,9 @@ [:from-named [[:ax/iri ""] [:ax/iri ""]]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["ASK" "WHERE {" @@ -115,7 +115,7 @@ (->> '[:query/ask [[:ask []] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]] format-ast))))) diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index af71e1c..8b27de5 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -33,5 +33,5 @@ {:pretty? true}))) (is (= "?s ?p ?o ." (f/format-ast - '[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] + '[:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] {:pretty? true}))))) diff --git a/src/test/com/yetanalytics/flint/format/update_test.cljc b/src/test/com/yetanalytics/flint/format/update_test.cljc index e5ccf89..9f1ef88 100644 --- a/src/test/com/yetanalytics/flint/format/update_test.cljc +++ b/src/test/com/yetanalytics/flint/format/update_test.cljc @@ -13,9 +13,9 @@ " foo:x dc:title \"Title\" ." "}"]) (->> '[:update/insert-data - [[:insert-data [[:triple/vec [[:ax/prefix-iri :foo/x] - [:ax/prefix-iri :dc/title] - [:ax/literal "Title"]]]]]]] + [[:insert-data [[:triple.vec/spo [[:ax/prefix-iri :foo/x] + [:ax/prefix-iri :dc/title] + [:ax/literal "Title"]]]]]]] format-ast)))) (testing "Formatting DELETE DATA clauses" (is (= (cstr/join "\n" ["DELETE DATA {" @@ -28,9 +28,9 @@ [[:triple/quads [[:ax/iri ""] [:triple/quad-triples - [[:triple/vec [[:ax/prefix-iri :foo/x] - [:ax/prefix-iri :dc/title] - [:ax/literal "Title"]]]]]]]]]]] + [[:triple.vec/spo [[:ax/prefix-iri :foo/x] + [:ax/prefix-iri :dc/title] + [:ax/literal "Title"]]]]]]]]]]] format-ast)))) (testing "Formatting DELETE WHERE clauses" (is (= (cstr/join "\n" ["DELETE WHERE {" @@ -39,8 +39,8 @@ "}"]) (->> '[:update/delete-where [[:delete-where - [[:triple/vec [[:ax/var ?x] [:ax/var ?y] [:ax/var ?z]]] - [:triple/vec [[:ax/var ?i] [:ax/var ?j] [:ax/var ?k]]]]]]] + [[:triple.vec/spo [[:ax/var ?x] [:ax/var ?y] [:ax/var ?z]]] + [:triple.vec/spo [[:ax/var ?i] [:ax/var ?j] [:ax/var ?k]]]]]]] format-ast))) (is (= (cstr/join "\n" ["DELETE WHERE {" " ?x ?y ?z ." @@ -52,7 +52,7 @@ "}"]) (->> '[:update/delete-where [[:delete-where - [[:triple/vec + [[:triple.vec/spo [[:ax/var ?x] [:ax/var ?y] [:ax/var ?z]]] [:triple.nform/spo [[[:ax/var ?i] @@ -66,7 +66,7 @@ [:triple/quads [[:ax/iri ""] [:triple/quad-triples - [[:triple/vec [[:ax/var ?q] [:ax/var ?r] [:ax/var ?s]]]]]]]]]]] + [[:triple.vec/spo [[:ax/var ?q] [:ax/var ?r] [:ax/var ?s]]]]]]]]]]] format-ast)))) (testing "Formatting DELETE...INSERT clauses" (is (= (cstr/join "\n" ["INSERT {" @@ -78,13 +78,13 @@ "}"]) (->> '[:update/modify [[:insert - [[:triple/vec [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]] + [[:triple.vec/spo [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]] [:using [:update/named-iri [:named [:ax/iri ""]]]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]]]]]] + [:triple.vec/spo [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]]]]]] format-ast))) (is (= (cstr/join "\n" ["WITH " "DELETE {" @@ -100,8 +100,8 @@ "}"]) (->> '[:update/modify [[:with [:ax/iri ""]] - [:delete [[:triple/vec [[:ax/var ?x] [:ax/var ?y] [:ax/var ?z]]]]] - [:insert [[:triple/vec [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]] + [:delete [[:triple.vec/spo [[:ax/var ?x] [:ax/var ?y] [:ax/var ?z]]]]] + [:insert [[:triple.vec/spo [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]] [:using [:update/iri [:ax/iri ""]]] [:where [:where-sub/where [[:where/triple diff --git a/src/test/com/yetanalytics/flint/format/where_test.cljc b/src/test/com/yetanalytics/flint/format/where_test.cljc index 8d16773..797b059 100644 --- a/src/test/com/yetanalytics/flint/format/where_test.cljc +++ b/src/test/com/yetanalytics/flint/format/where_test.cljc @@ -11,8 +11,8 @@ " ?s ?p ?o ." "}"]) (-> '[:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]] - [:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]] + [:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]] (f/format-ast {:pretty? true})))) (is (= (cstr/join "\n" ["{" " ?s1 ?p1 ?o1 ." @@ -52,7 +52,7 @@ "}"]) (-> '[:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]]] [:where/triple [:triple.nform/spo @@ -64,37 +64,37 @@ [:where/special [:where/recurse [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]]] [:where/special [:where/union [[:where-sub/where - [[:where/triple [:triple/vec + [[:where/triple [:triple.vec/spo [[:ax/var ?s4] [:ax/var ?p4] [:ax/var ?o4]]]]]] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]]] [:where/special [:where/optional [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]]] [:where/special [:where/minus [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]]] [:where/special [:where/graph [[:ax/prefix-iri :ns/my-graph] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s8] [:ax/var ?p8] [:ax/var ?o8]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s8] [:ax/var ?p8] [:ax/var ?o8]]]]]]]]] [:where/special [:where/service [[:ax/prefix-iri :ns/my-uri] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s9] [:ax/var ?p9] [:ax/var ?o9]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s9] [:ax/var ?p9] [:ax/var ?o9]]]]]]]]] [:where/special [:where/service-silent [[:ax/prefix-iri :ns/my-uri] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s10] [:ax/var ?p10] [:ax/var ?o10]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s10] [:ax/var ?p10] [:ax/var ?o10]]]]]]]]] [:where/special [:where/bind [:expr/as-var diff --git a/src/test/com/yetanalytics/flint/spec/expr_test.cljc b/src/test/com/yetanalytics/flint/spec/expr_test.cljc index 543e49d..649ad60 100644 --- a/src/test/com/yetanalytics/flint/spec/expr_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/expr_test.cljc @@ -42,9 +42,9 @@ (is (= [:expr/branch [[:expr/op 'exists] [:expr/args [[:where-sub/where [[:where/triple - [:triple/vec '[[:ax/var ?s] - [:ax/var ?p] - [:ax/var ?o]]]]]]]]]] + [:triple.vec/spo '[[:ax/var ?s] + [:ax/var ?p] + [:ax/var ?o]]]]]]]]]] (s/conform ::es/expr '(exists [[?s ?p ?o]])))) (is (= [:expr/branch [[:expr/op 'contains] [:expr/args [[:expr/terminal [:ax/literal "foo"]] diff --git a/src/test/com/yetanalytics/flint/spec/query_test.cljc b/src/test/com/yetanalytics/flint/spec/query_test.cljc index 791289d..b60b3ba 100644 --- a/src/test/com/yetanalytics/flint/spec/query_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/query_test.cljc @@ -19,9 +19,9 @@ [:select [:select/var-or-exprs [[:ax/var ?x]]]] [:from [:ax/iri ""]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:order-by [[:mod/asc-desc [[:mod/op asc] [:mod/asc-desc-expr [:expr/terminal [:ax/var ?y]]]]]]] diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index 96254a8..7fc6d22 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -32,7 +32,7 @@ ?p2 #{?o1 ?o2}} ?s2 {?p1 #{?o1 ?o2} ?p2 #{?o1 ?o2}}}))) - (is (= '[:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] + (is (= '[:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] (s/conform ts/triple-spec '[?s ?p ?o]))) (testing "with and without paths" (is (= '[:triple.nform/spo @@ -46,7 +46,7 @@ [:triple.nform/o [[:ax/var ?o]]]]]]]]] (s/conform ts/triple-spec '{?s {(cat :x/one :x/two) #{?o}}}))) - (is (= '[:triple/vec + (is (= '[:triple.vec/spo [[:ax/var ?s] [:triple/path [:path/branch [[:path/op cat] diff --git a/src/test/com/yetanalytics/flint/spec/update_test.cljc b/src/test/com/yetanalytics/flint/spec/update_test.cljc index bb3775d..d02502d 100644 --- a/src/test/com/yetanalytics/flint/spec/update_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/update_test.cljc @@ -5,24 +5,24 @@ (deftest conform-update-test (testing "Conforming updates" - (is (= '[[:insert-data [[:triple/vec [[:ax/prefix-iri :foo/x] - [:ax/prefix-iri :dc/title] - [:ax/literal "Title"]]] - [:triple/vec [[:ax/prefix-iri :foo/y] - [:ax/rdf-type :a] - [:ax/literal "MyType"]]]]]] + (is (= '[[:insert-data [[:triple.vec/spo [[:ax/prefix-iri :foo/x] + [:ax/prefix-iri :dc/title] + [:ax/literal "Title"]]] + [:triple.vec/spo [[:ax/prefix-iri :foo/y] + [:ax/rdf-type :a] + [:ax/literal "MyType"]]]]]] (s/conform us/insert-data-update-spec '{:insert-data [[:foo/x :dc/title "Title"] [:foo/y :a "MyType"]]}))) (is (= '[[:delete-data [[:triple/quads [[:ax/iri ""] [:triple/quad-triples - [[:triple/vec [[:ax/prefix-iri :foo/x] - [:ax/prefix-iri :dc/title] - [:ax/literal "Title"]]] - [:triple/vec [[:ax/prefix-iri :foo/y] - [:ax/rdf-type :a] - [:ax/literal "MyType"]]]]]]]]]] + [[:triple.vec/spo [[:ax/prefix-iri :foo/x] + [:ax/prefix-iri :dc/title] + [:ax/literal "Title"]]] + [:triple.vec/spo [[:ax/prefix-iri :foo/y] + [:ax/rdf-type :a] + [:ax/literal "MyType"]]]]]]]]]] (s/conform us/delete-data-update-spec '{:delete-data [[:graph "" diff --git a/src/test/com/yetanalytics/flint/spec/where_test.cljc b/src/test/com/yetanalytics/flint/spec/where_test.cljc index 4abe7fc..33ed794 100644 --- a/src/test/com/yetanalytics/flint/spec/where_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/where_test.cljc @@ -8,17 +8,17 @@ (is (= '[:where-sub/select [[:select [:select/var-or-exprs [[:ax/var ?s]]]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?s] - [:ax/var ?p] - [:ax/var ?o]]]]]]]]] + [:triple.vec/spo [[:ax/var ?s] + [:ax/var ?p] + [:ax/var ?o]]]]]]]]] (s/conform ::ws/where '{:where [[?s ?p ?o]] :select [?s]}))) (is (= '[:where-sub/select [[:select [:select/var-or-exprs [[:ax/var ?s]]]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?s] - [:ax/var ?p] - [:ax/var ?o]]]]]]] + [:triple.vec/spo [[:ax/var ?s] + [:ax/var ?p] + [:ax/var ?o]]]]]]] [:group-by [[:mod/expr-as-var [:expr/as-var [[:expr/branch @@ -33,43 +33,43 @@ [[:where/special [:where/union [[:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]] - [:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]] + [:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where '[[:union [[?s ?p ?o] [?s ?p ?o]] [[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/optional [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] (s/conform ::ws/where [[:optional '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/minus [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]] (s/conform ::ws/where [[:minus '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/graph [[:ax/prefix-iri :foo/my-graph] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where [[:graph :foo/my-graph '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/service [[:ax/prefix-iri :foo/my-uri] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where [[:service :foo/my-uri '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special [:where/service-silent [[:ax/prefix-iri :foo/my-uri] [:where-sub/where - [[:where/triple [:triple/vec [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]]]]]]]]]] (s/conform ::ws/where [[:service-silent :foo/my-uri '[[?s ?p ?o]]]]))) (is (= '[:where-sub/where [[:where/special @@ -100,9 +100,9 @@ ;; This is not a special form since it does not conform to the UNION ;; spec (or any other special form spec really) (is (= '[:where-sub/where - [[:where/triple [:triple/vec [[:ax/prefix-iri :union] - [:ax/prefix-iri :foo/bar] - [:ax/prefix-iri :baz/qux]]]]]] + [[:where/triple [:triple.vec/spo [[:ax/prefix-iri :union] + [:ax/prefix-iri :foo/bar] + [:ax/prefix-iri :baz/qux]]]]]] (s/conform ::ws/where '[[:union :foo/bar :baz/qux]]))))) (deftest invalid-where-test diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index 59ee0f5..6247c40 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -53,9 +53,9 @@ (testing "invalid blank nodes" (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.vec/spo]}]}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]] [:where [[?y :baz/qux _1]]]]} @@ -102,9 +102,9 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]}]}] + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple.vec/spo]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?y :baz/qux _1]]]]} @@ -113,11 +113,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]}]}] + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple.vec/spo]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [?y :baz/qux _1] @@ -127,11 +127,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]}]}] + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?z :far/lands _1]]] @@ -141,9 +141,9 @@ vb/validate-bnodes))) (is (= [#{'_1 '_2} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_2 - :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/special :where/optional :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_2 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]}]}] + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:optional [[?z :far/lands _2]]] @@ -153,11 +153,11 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/triple :triple/vec]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo]} {:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/filter :expr/branch :expr/args :where-sub/where :where/triple :triple/vec]}]}] + :path [:query/select :where :where-sub/where :where/special :where/filter :expr/branch :expr/args :where-sub/where :where/triple :triple.vec/spo]}]}] (->> '{:select [?x] :where [[?x :foo/bar _1] [:filter (not-exists [[?z :far/lands _1]])] @@ -167,7 +167,7 @@ vb/validate-bnodes))) (is (= [#{'_1} {:kind ::vb/dupe-bnodes-update :errors [{:bnode '_1 - :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}] + :path [:query/select :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.vec/spo]}] :prev-bnodes #{'_1}}] (->> '{:select [?x] :where [[:where [[?x :foo/bar _1]]]]} @@ -176,9 +176,9 @@ (vb/validate-bnodes #{'_1})))) (is (= [[#{'_1} {:kind ::vb/dupe-bnodes-bgp :errors [{:bnode '_1 - :path [:update/modify :insert :triple/vec]} + :path [:update/modify :insert :triple.vec/spo]} {:bnode '_1 - :path [:update/modify :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}]}]] + :path [:update/modify :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.vec/spo]}]}]] (->> '[{:insert [[?x :foo/bar _1]] :where [[:where [[?x :foo/bar _1]]]]}] (map (partial s/conform us/update-spec)) @@ -198,9 +198,9 @@ ::vb/dupe-bnodes-update :errors [{:bnode '_1 - :path [:update/modify :insert :triple/vec]} + :path [:update/modify :insert :triple.vec/spo]} {:bnode '_2 - :path [:update/modify :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple/vec]}] + :path [:update/modify :where :where-sub/where :where/special :where/recurse :where-sub/where :where/triple :triple.vec/spo]}] :prev-bnodes #{'_1 '_2}}] (->> '[{:insert [[?x :foo/bar _1]] diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index f885277..5b6fdcf 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -26,7 +26,7 @@ (is (= [{:iri :bar :prefix :$ :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/triple :triple/vec :ax/prefix-iri]}] + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo :ax/prefix-iri]}] (->> (assoc query :where '[[:bar :a ?y]]) (s/conform qs/query-spec) v/collect-nodes @@ -34,15 +34,15 @@ (is (= [{:iri :fee/bar :prefix :fee :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/triple :triple/vec :ax/prefix-iri]} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo :ax/prefix-iri]} {:iri :fii/bar :prefix :fii :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :where/triple :triple/vec :ax/prefix-iri]} + :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :where/triple :triple.vec/spo :ax/prefix-iri]} {:iri :fum/bar :prefix :fum :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :where/triple :triple/vec :ax/prefix-iri]}] + :path [:query/select :where :where-sub/where :where/special :where/union :where-sub/where :where/triple :triple.vec/spo :ax/prefix-iri]}] (->> query (s/conform qs/query-spec) v/collect-nodes @@ -54,7 +54,7 @@ {:iri :baz/Quu :prefix :baz :prefixes {:rdf ""} - :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple/vec :ax/prefix-iri]}] + :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple.vec/spo :ax/prefix-iri]}] (->> {:prefixes {:rdf ""} :insert-data [[:graph "" [{"" {:rdf/type #{:baz/Qux}}} diff --git a/src/test/com/yetanalytics/flint/validate/scope_test.cljc b/src/test/com/yetanalytics/flint/validate/scope_test.cljc index 80503a2..d64c5ea 100644 --- a/src/test/com/yetanalytics/flint/validate/scope_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/scope_test.cljc @@ -36,9 +36,9 @@ (testing "in basic graph patterns" (is (= '[?x ?y ?z] (vv/get-scope-vars - '[:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]))) + '[:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]))) (is (= '[?s ?p ?o] (vv/get-scope-vars '[:triple.nform/spo @@ -50,19 +50,19 @@ (vv/get-scope-vars '[:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]))) + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]))) (is (= '[?x ?y ?z] (vv/get-scope-vars '[:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]))) + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]))) (is (= '[?x ?ya ?yb ?z] (vv/get-scope-vars - '[:triple/vec + '[:triple.vec/spo [[:ax/var ?x] [:triple/path [:path/branch [[:path/op cat] @@ -77,9 +77,9 @@ [[:select [:ax/wildcard '*]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]]]]))) + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]]]]))) ;; This is an illegal sub-SELECT since it has both a wildcard and ;; GROUP BY, but we want to cover all of our bases. (is (= '[?x ?y ?z ?w] @@ -88,9 +88,9 @@ [[:select [:ax/wildcard '*]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:group-by [[:ax/var ?w]]]]]))) (is (= '[?a ?b ?c] (vv/get-scope-vars @@ -103,9 +103,9 @@ [:ax/var ?c]]]]]]] [:where [:where-sub/where [[:where/triple - [:triple/vec [[:ax/var ?x] - [:ax/var ?y] - [:ax/var ?z]]]]]]] + [:triple.vec/spo [[:ax/var ?x] + [:ax/var ?y] + [:ax/var ?z]]]]]]] [:group-by [[:ax/var ?a] [:ax/var ?b] [:ax/var ?c]]]]])))) @@ -123,39 +123,39 @@ [[:where/recurse [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s1] [:ax/var ?p1] [:ax/var ?o1]]]]]]] [:where/union [[:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s2] [:ax/var ?p2] [:ax/var ?o2]]]]]] [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s3] [:ax/var ?p3] [:ax/var ?o3]]]]]]]] [:where/optional [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s4] [:ax/var ?p4] [:ax/var ?o4]]]]]]] [:where/graph [[:ax/var ?graphTerm] [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]] [:where/service [[:ax/var ?serviceTerm] [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s6] [:ax/var ?p6] [:ax/var ?o6]]]]]]]] [:where/service-silent [[:ax/var ?serviceSilentTerm] [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s7] [:ax/var ?p7] [:ax/var ?o7]]]]]]]] [:where/bind [:expr/as-var @@ -177,7 +177,7 @@ [:where/minus [:where-sub/where [[:where/triple - [:triple/vec + [:triple.vec/spo [[:ax/var ?s5] [:ax/var ?p5] [:ax/var ?o5]]]]]]]]]))))) From 7288e5bedd776a6e6d39d46a3631d363efac406b Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 14:19:29 -0500 Subject: [PATCH 15/34] Replace :triple/quad keywords --- .../com/yetanalytics/flint/format/triple.cljc | 36 +++++++++---------- .../com/yetanalytics/flint/spec/triple.cljc | 16 ++++----- .../flint/format/update_test.cljc | 8 ++--- .../yetanalytics/flint/spec/update_test.cljc | 4 +-- .../flint/validate/prefix_test.cljc | 4 +-- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 196edc4..179a40e 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -10,11 +10,11 @@ (defmethod f/format-ast-node :triple/path [_ [_ path]] path) -(defmethod f/format-ast-node :triple.vec/spo [_ [_ [s p o]]] - (str s " " p " " o " .")) +(defmethod f/format-ast-node :triple.vec/spo [_ [_ [s-str p-str o-str]]] + (str s-str " " p-str " " o-str " .")) -(defmethod f/format-ast-node :triple.vec/s [_ [_ [s]]] - (str s " .")) +(defmethod f/format-ast-node :triple.vec/s [_ [_ [s-str]]] + (str s-str " .")) (defn- format-spo-map [spo pretty?] (if pretty? @@ -31,30 +31,30 @@ (cstr/join " . ")) " ."))) -(defmethod f/format-ast-node :triple.nform/spo [{:keys [pretty?]} [_ spo]] - (format-spo-map spo pretty?)) +(defmethod f/format-ast-node :triple.nform/spo [{:keys [pretty?]} [_ spo-strs]] + (format-spo-map spo-strs pretty?)) -(defmethod f/format-ast-node :triple.nform/s [{:keys [pretty?]} [_ spo]] - (format-spo-map spo pretty?)) +(defmethod f/format-ast-node :triple.nform/s [{:keys [pretty?]} [_ s-str]] + (format-spo-map s-str pretty?)) -(defmethod f/format-ast-node :triple.nform/po [{:keys [pretty?]} [_ po]] +(defmethod f/format-ast-node :triple.nform/po [{:keys [pretty?]} [_ po-strs]] (let [join-sep (if pretty? " ;\n" " ; ")] - (->> po + (->> po-strs (map (fn [[p o]] (str p " " o))) (cstr/join join-sep)))) -(defmethod f/format-ast-node :triple.nform/o [_ [_ o]] - (->> o (cstr/join " , "))) +(defmethod f/format-ast-node :triple.nform/o [_ [_ o-strs]] + (->> o-strs (cstr/join " , "))) (defn format-quads [quads pretty?] (-> quads (f/join-clauses pretty?) (f/wrap-in-braces pretty?))) -(defmethod f/format-ast-node :triple/quads - [_ [_ [var-or-iri triples-str]]] - (str "GRAPH " var-or-iri " " triples-str)) +(defmethod f/format-ast-node :triple.quad/gspo + [_ [_ [graph-str spo-str]]] + (str "GRAPH " graph-str " " spo-str)) -(defmethod f/format-ast-node :triple/quad-triples - [{:keys [pretty?]} [_ triples]] - (format-quads triples pretty?)) +(defmethod f/format-ast-node :triple.quad/spo + [{:keys [pretty?]} [_ spo-strs]] + (format-quads spo-strs pretty?)) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index c83821f..597a3e1 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -301,25 +301,25 @@ (def quad-nopath-spec (s/and (s/tuple #{:graph} ax/iri-or-var-spec - (s/or :triple/quad-triples triple-coll-nopath-spec)) + (s/or :triple.quad/spo triple-coll-nopath-spec)) (s/conformer (fn [[_ iri triples]] [iri triples])))) (def quad-novar-spec (s/and (s/tuple #{:graph} ax/iri-or-var-spec - (s/or :triple/quad-triples triple-coll-novar-spec)) + (s/or :triple.quad/spo triple-coll-novar-spec)) (s/conformer (fn [[_ iri triples]] [iri triples])))) (def quad-noblank-spec (s/and (s/tuple #{:graph} ax/iri-or-var-spec - (s/or :triple/quad-triples triple-coll-noblank-spec)) + (s/or :triple.quad/spo triple-coll-noblank-spec)) (s/conformer (fn [[_ iri triples]] [iri triples])))) (def quad-novar-noblank-spec (s/and (s/tuple #{:graph} ax/iri-or-var-spec - (s/or :triple/quad-triples triple-coll-novar-noblank-spec)) + (s/or :triple.quad/spo triple-coll-novar-noblank-spec)) (s/conformer (fn [[_ iri triples]] [iri triples])))) ;; Collection of Quads (for UPDATE) @@ -329,7 +329,7 @@ :triple.vec/s triple-vec-no-po-nopath-spec :triple.nform/spo normal-form-nopath-spec :triple.nform/s normal-form-no-po-nopath-spec - :triple/quads quad-nopath-spec) + :triple.quad/gspo quad-nopath-spec) :kind vector?)) (def quad-coll-novar-spec @@ -337,17 +337,17 @@ :triple.vec/s triple-vec-no-po-novar-spec :triple.nform/spo normal-form-novar-spec :triple.nform/s normal-form-no-po-novar-spec - :triple/quads quad-novar-spec) + :triple.quad/gspo quad-novar-spec) :kind vector?)) (def quad-coll-noblank-spec (s/coll-of (s/or :triple.vec/spo triple-vec-noblank-spec :triple.nform/spo normal-form-noblank-spec - :triple/quads quad-noblank-spec) + :triple.quad/gspo quad-noblank-spec) :kind vector?)) (def quad-coll-novar-noblank-spec (s/coll-of (s/or :triple.vec/spo triple-vec-novar-noblank-spec :triple.nform/spo normal-form-novar-noblank-spec - :triple/quads quad-novar-noblank-spec) + :triple.quad/gspo quad-novar-noblank-spec) :kind vector?)) diff --git a/src/test/com/yetanalytics/flint/format/update_test.cljc b/src/test/com/yetanalytics/flint/format/update_test.cljc index 9f1ef88..b27a5c7 100644 --- a/src/test/com/yetanalytics/flint/format/update_test.cljc +++ b/src/test/com/yetanalytics/flint/format/update_test.cljc @@ -25,9 +25,9 @@ "}"]) (->> '[:update/delete-data [[:delete-data - [[:triple/quads + [[:triple.quad/gspo [[:ax/iri ""] - [:triple/quad-triples + [:triple.quad/spo [[:triple.vec/spo [[:ax/prefix-iri :foo/x] [:ax/prefix-iri :dc/title] [:ax/literal "Title"]]]]]]]]]]] @@ -63,9 +63,9 @@ [:triple.nform/po [[[:ax/var ?p] [:triple.nform/o [[:ax/var ?o]]]]]]]]] - [:triple/quads + [:triple.quad/gspo [[:ax/iri ""] - [:triple/quad-triples + [:triple.quad/spo [[:triple.vec/spo [[:ax/var ?q] [:ax/var ?r] [:ax/var ?s]]]]]]]]]]] format-ast)))) (testing "Formatting DELETE...INSERT clauses" diff --git a/src/test/com/yetanalytics/flint/spec/update_test.cljc b/src/test/com/yetanalytics/flint/spec/update_test.cljc index d02502d..f60957b 100644 --- a/src/test/com/yetanalytics/flint/spec/update_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/update_test.cljc @@ -14,9 +14,9 @@ (s/conform us/insert-data-update-spec '{:insert-data [[:foo/x :dc/title "Title"] [:foo/y :a "MyType"]]}))) - (is (= '[[:delete-data [[:triple/quads + (is (= '[[:delete-data [[:triple.quad/gspo [[:ax/iri ""] - [:triple/quad-triples + [:triple.quad/spo [[:triple.vec/spo [[:ax/prefix-iri :foo/x] [:ax/prefix-iri :dc/title] [:ax/literal "Title"]]] diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index 5b6fdcf..83d6d1d 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -50,11 +50,11 @@ (is (= [{:iri :baz/Qux :prefix :baz :prefixes {:rdf ""} - :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple.nform/spo :triple.nform/po :triple.nform/o :ax/prefix-iri]} + :path [:update/insert-data :insert-data :triple.quad/gspo :triple.quad/spo :triple.nform/spo :triple.nform/po :triple.nform/o :ax/prefix-iri]} {:iri :baz/Quu :prefix :baz :prefixes {:rdf ""} - :path [:update/insert-data :insert-data :triple/quads :triple/quad-triples :triple.vec/spo :ax/prefix-iri]}] + :path [:update/insert-data :insert-data :triple.quad/gspo :triple.quad/spo :triple.vec/spo :ax/prefix-iri]}] (->> {:prefixes {:rdf ""} :insert-data [[:graph "" [{"" {:rdf/type #{:baz/Qux}}} From 239cf971de4e6c353aa2ff6d3eebfc036d185601 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 15:16:54 -0500 Subject: [PATCH 16/34] Add bracketted blank node blocks --- .../com/yetanalytics/flint/format/triple.cljc | 9 +- .../com/yetanalytics/flint/spec/triple.cljc | 89 +++++++++++++++---- 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 179a40e..1f99489 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -4,11 +4,16 @@ [com.yetanalytics.flint.format.axiom] [com.yetanalytics.flint.format.path])) +(defmethod f/format-ast-node :triple/path [_ [_ path]] + path) + (defmethod f/format-ast-node :triple/list [_ [_ list]] (str "( " (cstr/join " " list) " )")) -(defmethod f/format-ast-node :triple/path [_ [_ path]] - path) +(defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ bnodes]] + (let [join-sep (if pretty? " ;\n " " ; ") + bnode-strs (map (fn [[pred obj]] (str pred " " obj)) bnodes)] + (str "[ " (cstr/join join-sep bnode-strs) " ]"))) (defmethod f/format-ast-node :triple.vec/spo [_ [_ [s-str p-str o-str]]] (str s-str " " p-str " " o-str " .")) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 597a3e1..c9179a8 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -54,6 +54,33 @@ (def list-novar-spec (s/coll-of list-entry-novar-spec :kind list?)) +;; Blank Node Vectors + +(declare pred-spec) +(declare pred-nopath-spec) +(declare pred-novar-spec) + +(declare obj-spec) +(declare obj-novar-spec) + +(defn- conform-pred-obj-pairs [po-pairs] + (mapv (fn [{:keys [pred obj]}] [pred obj]) po-pairs)) + +(def bnode-vec-spec + (s/and vector? + (s/* (s/cat :pred pred-spec :obj obj-spec)) + (s/conformer conform-pred-obj-pairs))) + +(def bnode-vec-nopath-spec + (s/and vector? + (s/* (s/cat :pred pred-nopath-spec :obj obj-spec)) + (s/conformer conform-pred-obj-pairs))) + +(def bnode-vec-novar-spec + (s/and vector? + (s/* (s/cat :pred pred-novar-spec :obj obj-novar-spec)) + (s/conformer conform-pred-obj-pairs))) + ;; Subjects (def subj-spec @@ -61,19 +88,35 @@ :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :triple/list list-spec)) + :triple/list list-spec + :triple/bnodes bnode-vec-spec)) + +(def subj-coll-spec + (s/or :triple/list list-spec + :triple/bnodes bnode-vec-spec)) + +(def subj-nopath-spec + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :triple/list list-spec + :triple/bnodes bnode-vec-nopath-spec)) -(def subj-list-spec - (s/or :triple/list list-spec)) +(def subj-coll-nopath-spec + (s/or :triple/list list-spec + :triple/bnodes bnode-vec-nopath-spec)) (def subj-novar-spec (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :triple/list list-spec)) + :triple/list list-spec + :triple/bnodes bnode-vec-novar-spec)) -(def subj-list-novar-spec - (s/or :triple/list list-novar-spec)) +(def subj-coll-novar-spec + (s/or :triple/list list-novar-spec + :triple/bnodes bnode-vec-novar-spec)) (def subj-noblank-spec (s/or :ax/var ax/variable-spec @@ -112,14 +155,25 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list list-spec)) + :triple/list list-spec + :triple/bnodes bnode-vec-spec)) + +(def obj-nopath-spec + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-spec + :triple/bnodes bnode-vec-nopath-spec)) (def obj-novar-spec (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list list-novar-spec)) + :triple/list list-novar-spec + :triple/bnodes bnode-vec-novar-spec)) (def obj-noblank-spec (s/or :ax/var ax/variable-spec @@ -149,6 +203,9 @@ (def obj-set-spec (make-obj-spec obj-spec)) +(def obj-set-nopath-spec + (make-obj-spec obj-nopath-spec)) + (def obj-set-novar-spec (make-obj-spec obj-novar-spec)) @@ -171,7 +228,7 @@ (make-pred-objs-spec pred-spec obj-set-spec)) (def pred-objs-nopath-spec - (make-pred-objs-spec pred-nopath-spec obj-set-spec)) + (make-pred-objs-spec pred-nopath-spec obj-set-nopath-spec)) (def pred-objs-novar-spec (make-pred-objs-spec pred-novar-spec obj-set-novar-spec)) @@ -193,7 +250,7 @@ (make-nform-spec subj-spec pred-objs-spec)) (def normal-form-nopath-spec - (make-nform-spec subj-spec pred-objs-nopath-spec)) + (make-nform-spec subj-nopath-spec pred-objs-nopath-spec)) (def normal-form-novar-spec (make-nform-spec subj-novar-spec pred-objs-novar-spec)) @@ -215,13 +272,13 @@ :conform-keys true :into []))) (def normal-form-no-po-spec - (make-nform-no-po-spec subj-list-spec)) + (make-nform-no-po-spec subj-coll-spec)) (def normal-form-no-po-nopath-spec - (make-nform-no-po-spec subj-list-spec)) + (make-nform-no-po-spec subj-coll-nopath-spec)) (def normal-form-no-po-novar-spec - (make-nform-no-po-spec subj-list-novar-spec)) + (make-nform-no-po-spec subj-coll-novar-spec)) ;; Triple Vectors @@ -243,13 +300,13 @@ ;; Triple Vectors (List, no predicates + objects) (def triple-vec-no-po-spec - (s/tuple subj-list-spec)) + (s/tuple subj-coll-spec)) (def triple-vec-no-po-nopath-spec - (s/tuple subj-list-spec)) + (s/tuple subj-coll-spec)) (def triple-vec-no-po-novar-spec - (s/tuple subj-list-novar-spec)) + (s/tuple subj-coll-novar-spec)) ;; Triples From abab618172f71b22cb1c889014f7262b67c77e33 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 15:41:15 -0500 Subject: [PATCH 17/34] Allow bnode ves to be nested in lists --- .../com/yetanalytics/flint/spec/triple.cljc | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index c9179a8..d4a515c 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -23,37 +23,6 @@ ;; - DELETE DATA ;; - DELETE -;; Lists - -;; List entries have the same spec as objects + `:triple/list` - -;; Since lists are constructed out of blank nodes, we do not allow list -;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. - -(declare list-spec) -(declare list-novar-spec) - -(def list-entry-spec - (s/or :ax/var ax/variable-spec - :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-spec)) - -(def list-entry-novar-spec - (s/or :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-novar-spec)) - -(def list-spec - (s/coll-of list-entry-spec :kind list?)) - -(def list-novar-spec - (s/coll-of list-entry-novar-spec :kind list?)) - ;; Blank Node Vectors (declare pred-spec) @@ -81,6 +50,51 @@ (s/* (s/cat :pred pred-novar-spec :obj obj-novar-spec)) (s/conformer conform-pred-obj-pairs))) +;; Lists + +;; List entries have the same spec as objects + `:triple/list` + +;; Since lists are constructed out of blank nodes, we do not allow list +;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. + +(declare list-spec) +(declare list-novar-spec) + +(def list-entry-spec + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-spec + :triple/bnodes bnode-vec-spec)) + +(def list-entry-nopath-spec + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-spec + :triple/bnodes bnode-vec-nopath-spec)) + +(def list-entry-novar-spec + (s/or :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list list-novar-spec + :triple/bnodes bnode-vec-novar-spec)) + +(def list-spec + (s/coll-of list-entry-spec :kind list? :into [])) + +(def list-nopath-spec + (s/coll-of list-entry-nopath-spec :kind list? :into [])) + +(def list-novar-spec + (s/coll-of list-entry-novar-spec :kind list? :into [])) + ;; Subjects (def subj-spec @@ -100,11 +114,11 @@ :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :triple/list list-spec + :triple/list list-nopath-spec :triple/bnodes bnode-vec-nopath-spec)) (def subj-coll-nopath-spec - (s/or :triple/list list-spec + (s/or :triple/list list-nopath-spec :triple/bnodes bnode-vec-nopath-spec)) (def subj-novar-spec @@ -164,7 +178,7 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list list-spec + :triple/list list-nopath-spec :triple/bnodes bnode-vec-nopath-spec)) (def obj-novar-spec From a391461dddfee7e40daa53a3cfcfa09772251526 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 15:51:45 -0500 Subject: [PATCH 18/34] Add new macro to require-macros --- src/main/com/yetanalytics/flint/spec/triple.cljc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index d4a515c..6ce4605 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -5,7 +5,8 @@ #?(:cljs (:require-macros [com.yetanalytics.flint.spec.triple :refer [make-obj-spec make-pred-objs-spec - make-nform-spec]]))) + make-nform-spec + make-nform-no-po-spec]]))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Subj/Pred/Obj Specs From 0659153f4f6c08e4082a4a9b35502d57e4ad6249 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 15:57:01 -0500 Subject: [PATCH 19/34] Use s/defs to avoid undefined function errors --- .../com/yetanalytics/flint/spec/triple.cljc | 254 +++++++++--------- 1 file changed, 122 insertions(+), 132 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 6ce4605..423d23e 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -24,183 +24,173 @@ ;; - DELETE DATA ;; - DELETE -;; Blank Node Vectors - -(declare pred-spec) -(declare pred-nopath-spec) -(declare pred-novar-spec) - -(declare obj-spec) -(declare obj-novar-spec) - -(defn- conform-pred-obj-pairs [po-pairs] - (mapv (fn [{:keys [pred obj]}] [pred obj]) po-pairs)) - -(def bnode-vec-spec - (s/and vector? - (s/* (s/cat :pred pred-spec :obj obj-spec)) - (s/conformer conform-pred-obj-pairs))) - -(def bnode-vec-nopath-spec - (s/and vector? - (s/* (s/cat :pred pred-nopath-spec :obj obj-spec)) - (s/conformer conform-pred-obj-pairs))) - -(def bnode-vec-novar-spec - (s/and vector? - (s/* (s/cat :pred pred-novar-spec :obj obj-novar-spec)) - (s/conformer conform-pred-obj-pairs))) - -;; Lists - -;; List entries have the same spec as objects + `:triple/list` - -;; Since lists are constructed out of blank nodes, we do not allow list -;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. - -(declare list-spec) -(declare list-novar-spec) - -(def list-entry-spec - (s/or :ax/var ax/variable-spec - :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-spec - :triple/bnodes bnode-vec-spec)) - -(def list-entry-nopath-spec - (s/or :ax/var ax/variable-spec - :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-spec - :triple/bnodes bnode-vec-nopath-spec)) - -(def list-entry-novar-spec - (s/or :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list list-novar-spec - :triple/bnodes bnode-vec-novar-spec)) - -(def list-spec - (s/coll-of list-entry-spec :kind list? :into [])) - -(def list-nopath-spec - (s/coll-of list-entry-nopath-spec :kind list? :into [])) - -(def list-novar-spec - (s/coll-of list-entry-novar-spec :kind list? :into [])) - ;; Subjects -(def subj-spec +(s/def ::subject (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :triple/list list-spec - :triple/bnodes bnode-vec-spec)) + :triple/list ::list + :triple/bnodes ::bnodes)) -(def subj-coll-spec - (s/or :triple/list list-spec - :triple/bnodes bnode-vec-spec)) +(s/def ::subject-coll + (s/or :triple/list ::list + :triple/bnodes ::bnodes)) -(def subj-nopath-spec +(s/def ::subject-nopath (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :triple/list list-nopath-spec - :triple/bnodes bnode-vec-nopath-spec)) + :triple/list ::list-nopath + :triple/bnodes ::bnodes-nopath)) -(def subj-coll-nopath-spec - (s/or :triple/list list-nopath-spec - :triple/bnodes bnode-vec-nopath-spec)) +(s/def ::subject-coll-nopath + (s/or :triple/list ::list-nopath + :triple/bnodes ::bnodes-nopath)) -(def subj-novar-spec +(s/def ::subject-novar (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec - :triple/list list-spec - :triple/bnodes bnode-vec-novar-spec)) + :triple/list ::list-novar + :triple/bnodes ::bnodes-novar)) -(def subj-coll-novar-spec - (s/or :triple/list list-novar-spec - :triple/bnodes bnode-vec-novar-spec)) +(s/def ::subject-coll-novar + (s/or :triple/list ::list-novar + :triple/bnodes ::bnodes-novar)) -(def subj-noblank-spec +(s/def ::subject-noblank (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec)) -(def subj-novar-noblank-spec +(s/def ::subject-novar-noblank (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec)) ;; Predicates -(def pred-spec +(s/def ::predicate (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/rdf-type ax/rdf-type-spec :triple/path ::ps/path)) -(def pred-nopath-spec +(s/def ::predicate-nopath (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/rdf-type ax/rdf-type-spec)) -(def pred-novar-spec +(s/def ::predicate-novar (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/rdf-type ax/rdf-type-spec)) ;; Objects (includes Lists) -(def obj-spec +(s/def ::object (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list list-spec - :triple/bnodes bnode-vec-spec)) + :triple/list ::list + :triple/bnodes ::bnodes)) -(def obj-nopath-spec +(s/def ::object-nopath (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list list-nopath-spec - :triple/bnodes bnode-vec-nopath-spec)) + :triple/list ::list-nopath + :triple/bnodes ::bnodes-nopath)) -(def obj-novar-spec +(s/def ::object-novar (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list list-novar-spec - :triple/bnodes bnode-vec-novar-spec)) + :triple/list ::list-nopath + :triple/bnodes ::bnodes-nopath)) -(def obj-noblank-spec +(s/def ::object-noblank (s/or :ax/var ax/variable-spec :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/literal ax/literal-spec)) -(def obj-novar-noblank-spec +(s/def ::object-novar-noblank (s/or :ax/iri ax/iri-spec :ax/prefix-iri ax/prefix-iri-spec :ax/literal ax/literal-spec)) +;; Lists + +;; List entries have the same spec as objects + `:triple/list` + +;; Since lists are constructed out of blank nodes, we do not allow list +;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. + +(s/def ::list-entry + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list ::list + :triple/bnodes ::bnodes)) + +(s/def ::list-entry-nopath + (s/or :ax/var ax/variable-spec + :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list ::list-nopath + :triple/bnodes ::bnodes-nopath)) + +(s/def ::list-entry-novar + (s/or :ax/iri ax/iri-spec + :ax/prefix-iri ax/prefix-iri-spec + :ax/bnode ax/bnode-spec + :ax/literal ax/literal-spec + :triple/list ::list-novar + :triple/bnodes ::bnodes-novar)) + +(s/def ::list + (s/coll-of ::list-entry :kind list? :into [])) + +(s/def ::list-nopath + (s/coll-of ::list-entry-nopath :kind list? :into [])) + +(s/def ::list-novar + (s/coll-of ::list-entry-novar :kind list? :into [])) + +;; Blank Node Vectors + +(defn- conform-pred-obj-pairs [po-pairs] + (mapv (fn [{:keys [pred obj]}] [pred obj]) po-pairs)) + +(s/def ::bnodes + (s/and vector? + (s/* (s/cat :pred ::predicate :obj ::object)) + (s/conformer conform-pred-obj-pairs))) + +(s/def ::bnodes-nopath + (s/and vector? + (s/* (s/cat :pred ::predicate-nopath :obj ::object)) + (s/conformer conform-pred-obj-pairs))) + +(s/def ::bnodes-novar + (s/and vector? + (s/* (s/cat :pred ::predicate-novar :obj ::object-novar)) + (s/conformer conform-pred-obj-pairs))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Combo Specs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -216,19 +206,19 @@ `(s/coll-of ~obj-spec :min-count 1 :kind set? :into [])))) (def obj-set-spec - (make-obj-spec obj-spec)) + (make-obj-spec ::object)) (def obj-set-nopath-spec - (make-obj-spec obj-nopath-spec)) + (make-obj-spec ::object-nopath)) (def obj-set-novar-spec - (make-obj-spec obj-novar-spec)) + (make-obj-spec ::object-novar)) (def obj-set-noblank-spec - (make-obj-spec obj-noblank-spec)) + (make-obj-spec ::object-noblank)) (def obj-set-novar-noblank-spec - (make-obj-spec obj-novar-noblank-spec)) + (make-obj-spec ::object-novar-noblank)) ;; Predicate Object @@ -240,19 +230,19 @@ :min-count 1))) (def pred-objs-spec - (make-pred-objs-spec pred-spec obj-set-spec)) + (make-pred-objs-spec ::predicate obj-set-spec)) (def pred-objs-nopath-spec - (make-pred-objs-spec pred-nopath-spec obj-set-nopath-spec)) + (make-pred-objs-spec ::predicate-nopath obj-set-nopath-spec)) (def pred-objs-novar-spec - (make-pred-objs-spec pred-novar-spec obj-set-novar-spec)) + (make-pred-objs-spec ::predicate-novar obj-set-novar-spec)) (def pred-objs-noblank-spec - (make-pred-objs-spec pred-nopath-spec obj-set-noblank-spec)) + (make-pred-objs-spec ::predicate-nopath obj-set-noblank-spec)) (def pred-objs-novar-noblank-spec - (make-pred-objs-spec pred-novar-spec obj-set-novar-noblank-spec)) + (make-pred-objs-spec ::predicate-novar obj-set-novar-noblank-spec)) ;; Subject Predicate Object @@ -262,19 +252,19 @@ :conform-keys true :into []))) (def normal-form-spec - (make-nform-spec subj-spec pred-objs-spec)) + (make-nform-spec ::subject pred-objs-spec)) (def normal-form-nopath-spec - (make-nform-spec subj-nopath-spec pred-objs-nopath-spec)) + (make-nform-spec ::subject-nopath pred-objs-nopath-spec)) (def normal-form-novar-spec - (make-nform-spec subj-novar-spec pred-objs-novar-spec)) + (make-nform-spec ::subject-novar pred-objs-novar-spec)) (def normal-form-noblank-spec - (make-nform-spec subj-noblank-spec pred-objs-noblank-spec)) + (make-nform-spec ::subject-noblank pred-objs-noblank-spec)) (def normal-form-novar-noblank-spec - (make-nform-spec subj-novar-noblank-spec pred-objs-novar-noblank-spec)) + (make-nform-spec ::subject-novar-noblank pred-objs-novar-noblank-spec)) ;; Subject Predicate Object (List) @@ -287,41 +277,41 @@ :conform-keys true :into []))) (def normal-form-no-po-spec - (make-nform-no-po-spec subj-coll-spec)) + (make-nform-no-po-spec ::subject-coll)) (def normal-form-no-po-nopath-spec - (make-nform-no-po-spec subj-coll-nopath-spec)) + (make-nform-no-po-spec ::subject-coll-nopath)) (def normal-form-no-po-novar-spec - (make-nform-no-po-spec subj-coll-novar-spec)) + (make-nform-no-po-spec ::subject-coll-novar)) ;; Triple Vectors (def triple-vec-spec - (s/tuple subj-spec pred-spec obj-spec)) + (s/tuple ::subject ::predicate ::object)) (def triple-vec-nopath-spec - (s/tuple subj-spec pred-nopath-spec obj-spec)) + (s/tuple ::subject ::predicate-nopath ::object)) (def triple-vec-novar-spec - (s/tuple subj-novar-spec pred-novar-spec obj-novar-spec)) + (s/tuple ::subject-novar ::predicate-novar ::object-novar)) (def triple-vec-noblank-spec - (s/tuple subj-noblank-spec pred-nopath-spec obj-noblank-spec)) + (s/tuple ::subject-noblank ::predicate-nopath ::object-noblank)) (def triple-vec-novar-noblank-spec - (s/tuple subj-novar-noblank-spec pred-novar-spec obj-novar-noblank-spec)) + (s/tuple ::subject-novar-noblank ::predicate-novar ::object-novar-noblank)) ;; Triple Vectors (List, no predicates + objects) (def triple-vec-no-po-spec - (s/tuple subj-coll-spec)) + (s/tuple ::subject-coll)) (def triple-vec-no-po-nopath-spec - (s/tuple subj-coll-spec)) + (s/tuple ::subject-coll)) (def triple-vec-no-po-novar-spec - (s/tuple subj-coll-novar-spec)) + (s/tuple ::subject-coll-novar)) ;; Triples From 64a0443e42350b44a6b8b1f06baf1084c58af306 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 16:10:39 -0500 Subject: [PATCH 20/34] Add bnode-pair AST node and use objects as list entry specs --- .../com/yetanalytics/flint/format/triple.cljc | 10 +++--- .../com/yetanalytics/flint/spec/triple.cljc | 35 +++---------------- src/main/com/yetanalytics/flint/validate.cljc | 3 ++ 3 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 1f99489..48339ae 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -10,10 +10,12 @@ (defmethod f/format-ast-node :triple/list [_ [_ list]] (str "( " (cstr/join " " list) " )")) -(defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ bnodes]] - (let [join-sep (if pretty? " ;\n " " ; ") - bnode-strs (map (fn [[pred obj]] (str pred " " obj)) bnodes)] - (str "[ " (cstr/join join-sep bnode-strs) " ]"))) +(defmethod f/format-ast-node :triple/bnode-pair [_ [_ [p o]]] + (str p " " o)) + +(defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ po-strs]] + (let [join-sep (if pretty? " ;\n " " ; ")] + (str "[ " (cstr/join join-sep po-strs) " ]"))) (defmethod f/format-ast-node :triple.vec/spo [_ [_ [s-str p-str o-str]]] (str s-str " " p-str " " o-str " .")) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 423d23e..e448ef6 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -136,45 +136,20 @@ ;; Since lists are constructed out of blank nodes, we do not allow list ;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. -(s/def ::list-entry - (s/or :ax/var ax/variable-spec - :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list ::list - :triple/bnodes ::bnodes)) - -(s/def ::list-entry-nopath - (s/or :ax/var ax/variable-spec - :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list ::list-nopath - :triple/bnodes ::bnodes-nopath)) - -(s/def ::list-entry-novar - (s/or :ax/iri ax/iri-spec - :ax/prefix-iri ax/prefix-iri-spec - :ax/bnode ax/bnode-spec - :ax/literal ax/literal-spec - :triple/list ::list-novar - :triple/bnodes ::bnodes-novar)) - (s/def ::list - (s/coll-of ::list-entry :kind list? :into [])) + (s/coll-of ::object :kind list? :into [])) (s/def ::list-nopath - (s/coll-of ::list-entry-nopath :kind list? :into [])) + (s/coll-of ::object-nopath :kind list? :into [])) (s/def ::list-novar - (s/coll-of ::list-entry-novar :kind list? :into [])) + (s/coll-of ::object-novar :kind list? :into [])) ;; Blank Node Vectors (defn- conform-pred-obj-pairs [po-pairs] - (mapv (fn [{:keys [pred obj]}] [pred obj]) po-pairs)) + (mapv (fn [{:keys [pred obj]}] [:triple/bnode-pair [pred obj]]) + po-pairs)) (s/def ::bnodes (s/and vector? diff --git a/src/main/com/yetanalytics/flint/validate.cljc b/src/main/com/yetanalytics/flint/validate.cljc index df81659..661a872 100644 --- a/src/main/com/yetanalytics/flint/validate.cljc +++ b/src/main/com/yetanalytics/flint/validate.cljc @@ -49,12 +49,15 @@ (defn- ast-children [[k children]] (cond + ;; These values are colls of colls (#{:triple.nform/spo :triple.nform/po} k) (apply concat children) + ;; These values are either AST nodes or scalars (or (and (vector? children) (keyword? (first children))) (not (coll? children))) [children] + ;; These values are colls of AST nodes :else children)) From 54e62ba8c0993cf5896004ae0ddbc9172b008d1e Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 17:37:55 -0500 Subject: [PATCH 21/34] Undo the addition of :triple/bnode-pair --- .../com/yetanalytics/flint/format/triple.cljc | 31 +++++++++---------- .../com/yetanalytics/flint/spec/triple.cljc | 3 +- src/main/com/yetanalytics/flint/validate.cljc | 4 +-- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 48339ae..2457cc6 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -10,11 +10,9 @@ (defmethod f/format-ast-node :triple/list [_ [_ list]] (str "( " (cstr/join " " list) " )")) -(defmethod f/format-ast-node :triple/bnode-pair [_ [_ [p o]]] - (str p " " o)) - -(defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ po-strs]] - (let [join-sep (if pretty? " ;\n " " ; ")] +(defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ po-pairs]] + (let [join-sep (if pretty? " ;\n " " ; ") + po-strs (mapv (fn [[p-str o-str]] (str p-str " " o-str)) po-pairs)] (str "[ " (cstr/join join-sep po-strs) " ]"))) (defmethod f/format-ast-node :triple.vec/spo [_ [_ [s-str p-str o-str]]] @@ -23,26 +21,25 @@ (defmethod f/format-ast-node :triple.vec/s [_ [_ [s-str]]] (str s-str " .")) -(defn- format-spo-map [spo pretty?] +(defmethod f/format-ast-node :triple.nform/spo [{:keys [pretty?]} [_ spo-pairs]] (if pretty? - (str (->> spo - (map (fn [[s po]] - (let [indent (->> (repeat (inc (count s)) " ") + (str (->> spo-pairs + (map (fn [[s-str po-str]] + (let [indent (->> (repeat (inc (count s-str)) " ") (cstr/join "") (str "\n"))] - (str s " " (cstr/replace po #"\n" indent))))) + (str s-str " " (cstr/replace po-str #"\n" indent))))) (cstr/join " .\n")) " .") - (str (->> spo - (map (fn [[s po]] (str s " " po))) + (str (->> spo-pairs + (map (fn [[s-str po-str]] (str s-str " " po-str))) (cstr/join " . ")) " ."))) -(defmethod f/format-ast-node :triple.nform/spo [{:keys [pretty?]} [_ spo-strs]] - (format-spo-map spo-strs pretty?)) - -(defmethod f/format-ast-node :triple.nform/s [{:keys [pretty?]} [_ s-str]] - (format-spo-map s-str pretty?)) +(defmethod f/format-ast-node :triple.nform/s [{:keys [pretty?]} [_ s-pairs]] + (let [join-sep (if pretty? " .\n" " . ")] + (str (->> s-pairs (map (fn [[s-str _]] s-str)) (cstr/join join-sep)) + " ."))) (defmethod f/format-ast-node :triple.nform/po [{:keys [pretty?]} [_ po-strs]] (let [join-sep (if pretty? " ;\n" " ; ")] diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index e448ef6..0df4a77 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -148,8 +148,7 @@ ;; Blank Node Vectors (defn- conform-pred-obj-pairs [po-pairs] - (mapv (fn [{:keys [pred obj]}] [:triple/bnode-pair [pred obj]]) - po-pairs)) + (mapv (fn [{:keys [pred obj]}] [pred obj]) po-pairs)) (s/def ::bnodes (s/and vector? diff --git a/src/main/com/yetanalytics/flint/validate.cljc b/src/main/com/yetanalytics/flint/validate.cljc index 661a872..423d909 100644 --- a/src/main/com/yetanalytics/flint/validate.cljc +++ b/src/main/com/yetanalytics/flint/validate.cljc @@ -49,8 +49,8 @@ (defn- ast-children [[k children]] (cond - ;; These values are colls of colls - (#{:triple.nform/spo :triple.nform/po} k) + ;; These values are colls of non-AST colls + (#{:triple/bnodes :triple.nform/spo :triple.nform/po} k) (apply concat children) ;; These values are either AST nodes or scalars (or (and (vector? children) From 1b440eba96462d3ea86b9ef902031d9a654c126f Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 17:38:01 -0500 Subject: [PATCH 22/34] Add tests --- src/dev/com/yetanalytics/flint/sparql.clj | 5 + .../flint/format/triple_test.cljc | 72 ++++++++++- .../yetanalytics/flint/spec/triple_test.cljc | 119 +++++++++++++++++- 3 files changed, 193 insertions(+), 3 deletions(-) diff --git a/src/dev/com/yetanalytics/flint/sparql.clj b/src/dev/com/yetanalytics/flint/sparql.clj index 369afde..e25a6fb 100644 --- a/src/dev/com/yetanalytics/flint/sparql.clj +++ b/src/dev/com/yetanalytics/flint/sparql.clj @@ -61,6 +61,11 @@ FILTER NOT EXISTS { ?z foo:baz ?w . } ?y foo:qux _:1 . }") + + (QueryFactory/create + "SELECT ?x WHERE { + [ [ ?x]] \"w\" + }") ) (comment diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index 8b27de5..2b711f8 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -34,4 +34,74 @@ (is (= "?s ?p ?o ." (f/format-ast '[:triple.vec/spo [[:ax/var ?s] [:ax/var ?p] [:ax/var ?o]]] - {:pretty? true}))))) + {:pretty? true}))) + (is (= "( 1 2 ) :p \"w\" ." + (f/format-ast + '[:triple.vec/spo + [[:triple/list [[:ax/literal 1] [:ax/literal 2]]] + [:ax/prefix-iri :p] + [:ax/literal "w"]]] + {:pretty? true}))) + (is (= "( ?x ?y ) ." + (f/format-ast + '[:triple.vec/s + [[:triple/list [[:ax/var ?x] [:ax/var ?y]]]]] + {:pretty? true}))) + (is (= "( ?x ?y ) ." + (f/format-ast + '[:triple.nform/s + [[[:triple/list [[:ax/var ?x] [:ax/var ?y]]] []]]] + {:pretty? true}))) + (is (= "\"v\" :p ( 1 2 ( 3 ) ) ." + (f/format-ast + '[:triple.vec/spo + [[:ax/literal "v"] + [:ax/prefix-iri :p] + [:triple/list [[:ax/literal 1] + [:ax/literal 2] + [:triple/list [[:ax/literal 3]]]]]]] + {:pretty? true}))) + (is (= "[ foaf:name ?name ;\n foaf:mbox ] :q \"w\" ." + (f/format-ast + '[:triple.vec/spo + [[:triple/bnodes [[[:ax/prefix-iri :foaf/name] + [:ax/var ?name]] + [[:ax/prefix-iri :foaf/mbox] + [:ax/iri ""]]]] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + {:pretty? true}))) + (is (= "[ foaf:name ?name ; foaf:mbox ] :q \"w\" ." + (f/format-ast + '[:triple.vec/spo + [[:triple/bnodes [[[:ax/prefix-iri :foaf/name] + [:ax/var ?name]] + [[:ax/prefix-iri :foaf/mbox] + [:ax/iri ""]]]] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + {:pretty? false}))) + (is (= "[ foaf:name ?name ; foaf:mbox ] ." + (f/format-ast + '[:triple.vec/s + [[:triple/bnodes [[[:ax/prefix-iri :foaf/name] + [:ax/var ?name]] + [[:ax/prefix-iri :foaf/mbox] + [:ax/iri ""]]]]]] + {:pretty? false}))) + (is (= "[ foo:bar [ foaf:mbox ] ] ." + (f/format-ast + '[:triple.vec/s + [[:triple/bnodes [[[:ax/prefix-iri :foo/bar] + [:triple/bnodes + [[[:ax/prefix-iri :foaf/mbox] + [:ax/iri ""]]]]]]]]] + {:pretty? true}))) + (is (= "[ foo:bar [ foaf:mbox ] ] ." + (f/format-ast + '[:triple.vec/s + [[:triple/bnodes [[[:ax/prefix-iri :foo/bar] + [:triple/bnodes + [[[:ax/prefix-iri :foaf/mbox] + [:ax/iri ""]]]]]]]]] + {:pretty? false}))))) diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index 7fc6d22..c026104 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -24,7 +24,7 @@ [:triple.nform/po [[[:ax/var ?p1] [:triple.nform/o [[:ax/var ?o1] - [:ax/var ?o2]]]] + [:ax/var ?o2]]]] [[:ax/var ?p2] [:triple.nform/o [[:ax/var ?o1] [:ax/var ?o2]]]]]]]]] @@ -63,4 +63,119 @@ ::s/problems (filter #(-> % :path first (= :triple.nform/spo))) (map :val) - (every? (partial = '(cat :x/one :x/two)))))))) + (every? (partial = '(cat :x/one :x/two)))))) + (testing "with list and blank nodes" + (is (= '[:triple.vec/spo + [[:triple/list [[:ax/literal 1] + [:ax/var ?x] + [:ax/literal 3] + [:ax/literal 4]]] + [:ax/prefix-iri :p] + [:ax/literal "w"]]] + (s/conform ts/triple-spec + '[(1 ?x 3 4) :p "w"]))) + (is (= '[:triple.vec/spo + [[:ax/var ?s] + [:ax/var ?p] + [:triple/list [[:ax/literal 100] [:ax/literal 200] [:ax/literal 300]]]]] + (s/conform ts/triple-spec + '[?s ?p (100 200 300)]))) + (is (= '[:triple.nform/spo + [[[:triple/list [[:ax/literal 1] + [:ax/var ?x] + [:ax/literal 3] + [:ax/literal 4]]] + [:triple.nform/po + [[[:ax/prefix-iri :p] + [:triple.nform/o [[:ax/literal "w"]]]]]]]]] + (s/conform ts/triple-spec + '{(1 ?x 3 4) {:p #{"w"}}}))) + (is (= '[:triple.nform/spo + [[[:ax/var ?x] + [:triple.nform/po + [[[:ax/prefix-iri :p] + [:triple.nform/o + [[:triple/list [[:ax/literal 100] + [:ax/literal 200] + [:ax/literal 300]]]]]]]]]]] + (s/conform ts/triple-spec + '{?x {:p #{(100 200 300)}}}))) + (is (= '[:triple.vec/s + [[:triple/list [[:ax/literal 1] + [:ax/var ?x] + [:triple/list [[:ax/literal 2]]]]]]] + (s/conform ts/triple-spec + '[(1 ?x (2))]))) + (is (= '[:triple.nform/s + [[[:triple/list [[:ax/literal 1] + [:ax/var ?x] + [:triple/list [[:ax/literal 2]]]]] + []]]] + (s/conform ts/triple-spec + '{(1 ?x (2)) {}}))) + (is (= '[:triple.vec/s + [[:triple/list [[:ax/literal 1] + [:triple/bnodes [[[:ax/prefix-iri :p] + [:ax/prefix-iri :q]]]] + [:triple/list [[:ax/literal 2]]]]]]] + (s/conform ts/triple-spec + '[(1 [:p :q] (2))]))) + (is (= '[:triple.vec/spo + [[:triple/bnodes [[[:ax/prefix-iri :p] + [:ax/literal "v"]]]] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + (s/conform ts/triple-spec + '[[:p "v"] :q "w"]))) + (is (= '[:triple.vec/spo + [[:ax/prefix-iri :x] + [:ax/prefix-iri :q] + [:triple/bnodes [[[:ax/prefix-iri :p] + [:ax/literal "v"]]]]]] + (s/conform ts/triple-spec + '[:x :q [:p "v"]]))) + (is (= '[:triple.nform/spo + [[[:triple/bnodes + [[[:ax/prefix-iri :p] + [:ax/literal "v"]]]] + [:triple.nform/po + [[[:ax/prefix-iri :q] + [:triple.nform/o [[:ax/literal "w"]]]]]]]]] + (s/conform ts/triple-spec + '{[:p "v"] {:q #{"w"}}}))) + (is (= '[:triple.nform/spo + [[[:ax/prefix-iri :x] + [:triple.nform/po + [[[:ax/prefix-iri :q] + [:triple.nform/o + [[:triple/bnodes [[[:ax/prefix-iri :p] + [:ax/literal "v"]]]]]]]]]]]] + (s/conform ts/triple-spec + '{:x {:q #{[:p "v"]}}}))) + (is (= '[:triple.vec/spo + [[:triple/bnodes []] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + (s/conform ts/triple-spec + '[[] :q "w"]))) + (is (= '[:triple.vec/spo + [[:triple/bnodes + [[[:ax/prefix-iri :p0] + [:triple/bnodes + [[[:ax/prefix-iri :p1] + [:triple/bnodes [[[:ax/prefix-iri :p2] + [:ax/literal "v"]]]]]]]]]] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + (s/conform ts/triple-spec + '[[:p0 [:p1 [:p2 "v"]]] :q "w"]))) + (is (= '[:triple.vec/spo + [[:triple/bnodes + [[[:ax/prefix-iri :p1] + [:ax/var ?x1]] + [[:ax/prefix-iri :p2] + [:ax/var ?x2]]]] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + (s/conform ts/triple-spec + '[[:p1 ?x1 :p2 ?x2] :q "w"])))))) From 9a24a5e38f47e281156c0ea1ddb83d2174b83c00 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 17:52:19 -0500 Subject: [PATCH 23/34] Special case when po-pair vec is empty --- src/main/com/yetanalytics/flint/format/triple.cljc | 8 +++++--- src/test/com/yetanalytics/flint/format/triple_test.cljc | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index 2457cc6..ea6871d 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -11,9 +11,11 @@ (str "( " (cstr/join " " list) " )")) (defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ po-pairs]] - (let [join-sep (if pretty? " ;\n " " ; ") - po-strs (mapv (fn [[p-str o-str]] (str p-str " " o-str)) po-pairs)] - (str "[ " (cstr/join join-sep po-strs) " ]"))) + (if (empty? po-pairs) + "[]" ; Treat as a scalar blank node + (let [join-sep (if pretty? " ;\n " " ; ") + po-strs (mapv (fn [[p-str o-str]] (str p-str " " o-str)) po-pairs)] + (str "[ " (cstr/join join-sep po-strs) " ]")))) (defmethod f/format-ast-node :triple.vec/spo [_ [_ [s-str p-str o-str]]] (str s-str " " p-str " " o-str " .")) diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index 2b711f8..4616622 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -104,4 +104,11 @@ [:triple/bnodes [[[:ax/prefix-iri :foaf/mbox] [:ax/iri ""]]]]]]]]] + {:pretty? false}))) + (is (= "[] ?p ?o ." + (f/format-ast + '[:triple.vec/spo + [[:triple/bnodes []] + [:ax/var ?p] + [:ax/var ?o]]] {:pretty? false}))))) From f2f2ecdc1b387c9145e626e775fc3657f3235a72 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 17:52:30 -0500 Subject: [PATCH 24/34] Add tests and fix bnode bugs during validation --- .../yetanalytics/flint/validate/variable.cljc | 27 ++++++++++++------- .../flint/validate/bnode_test.cljc | 6 +++++ .../flint/validate/prefix_test.cljc | 19 ++++++++++--- .../flint/validate/scope_test.cljc | 15 ++++++++++- 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 3d048c2..68789e7 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -98,30 +98,37 @@ (defmethod get-scope-vars :triple/list [[_ list]] (mapcat get-scope-vars list)) +(defmethod get-scope-vars :triple/bnodes [[_ po-pairs]] + (mapcat (fn [[p o]] (concat (get-scope-vars p) + (get-scope-vars o))) + po-pairs)) + +(mapcat get-scope-vars '[[[:ax/var ?z1] [:ax/var ?z2]]]) + (defmethod get-scope-vars :triple.vec/spo [[_ spo]] (mapcat get-scope-vars spo)) (defmethod get-scope-vars :triple.vec/s [[_ s]] (get-scope-vars s)) -(defmethod get-scope-vars :triple.nform/o [[_ o]] - (mapcat get-scope-vars o)) +(defmethod get-scope-vars :triple.nform/o [[_ o-coll]] + (mapcat get-scope-vars o-coll)) -(defmethod get-scope-vars :triple.nform/po [[_ po]] - (reduce-kv (fn [acc p o] (apply concat - acc - (get-scope-vars p) - (map get-scope-vars o))) +(defmethod get-scope-vars :triple.nform/po [[_ po-pairs]] + (reduce-kv (fn [acc p o-coll] (apply concat + acc + (get-scope-vars p) + (map get-scope-vars o-coll))) [] - po)) + po-pairs)) -(defmethod get-scope-vars :triple.nform/spo [[_ spo]] +(defmethod get-scope-vars :triple.nform/spo [[_ spo-pairs]] (reduce-kv (fn [acc s po] (apply concat acc (get-scope-vars s) (map get-scope-vars po))) [] - spo)) + spo-pairs)) (defmethod get-scope-vars :triple.nform/s [[_ s]] (get-scope-vars s)) diff --git a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc index 6247c40..a8438bb 100644 --- a/src/test/com/yetanalytics/flint/validate/bnode_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/bnode_test.cljc @@ -49,6 +49,12 @@ [:where [[?y :baz/qux _]]]]} (s/conform qs/query-spec) v/collect-nodes + vb/validate-bnodes))) + (is (= [#{} nil] + (->> '{:select [?p] + :where [[?x ?y] ?p (?z ?w)]} + (s/conform qs/query-spec) + v/collect-nodes vb/validate-bnodes)))) (testing "invalid blank nodes" (is (= [#{'_1} {:kind ::vb/dupe-bnodes-bgp diff --git a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc index 83d6d1d..9faa487 100644 --- a/src/test/com/yetanalytics/flint/validate/prefix_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/prefix_test.cljc @@ -23,14 +23,27 @@ v/collect-nodes (vp/validate-prefixes (assoc (:prefixes query) :$ ""))))) - (is (= [{:iri :bar - :prefix :$ + (is (= [{:iri :bar + :prefix :$ :prefixes {:foo ""} - :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo :ax/prefix-iri]}] + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo :ax/prefix-iri]}] (->> (assoc query :where '[[:bar :a ?y]]) (s/conform qs/query-spec) v/collect-nodes (vp/validate-prefixes (:prefixes query))))) + (is (= [{:iri :bar + :prefix :$ + :prefixes {:foo ""} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo :triple/bnodes :ax/prefix-iri]} + {:iri :bee + :prefix :$ + :prefixes {:foo ""} + :path [:query/select :where :where-sub/where :where/triple :triple.vec/spo :triple/bnodes :ax/prefix-iri]}] + (->> (assoc query :where '[[[:bar ?x] :a ?y] + [?z :a [:bee ?w]]]) + (s/conform qs/query-spec) + v/collect-nodes + (vp/validate-prefixes (:prefixes query))))) (is (= [{:iri :fee/bar :prefix :fee :prefixes {:foo ""} diff --git a/src/test/com/yetanalytics/flint/validate/scope_test.cljc b/src/test/com/yetanalytics/flint/validate/scope_test.cljc index d64c5ea..e2b673f 100644 --- a/src/test/com/yetanalytics/flint/validate/scope_test.cljc +++ b/src/test/com/yetanalytics/flint/validate/scope_test.cljc @@ -69,7 +69,20 @@ [:path/paths [[:path/terminal [:ax/var ?ya]] [:path/terminal [:ax/var ?yb]]]]]]] - [:ax/var ?z]]])))) + [:ax/var ?z]]]))) + (is (= '[?x1 ?x2 ?y ?z1 ?z2] + (vv/get-scope-vars + '[:triple.vec/spo [[:triple/list [[:ax/var ?x1] [:ax/var ?x2]]] + [:ax/var ?y] + [:triple/bnodes [[[:ax/var ?z1] [:ax/var ?z2]]]]]]))) + (is (= '[?x1 ?x2 ?y ?z1 ?z2] + (vv/get-scope-vars + '[:triple.nform/spo + [[[:triple/list [[:ax/var ?x1] [:ax/var ?x2]]] + [:triple.nform/po + [[[:ax/var ?y] + [:triple.nform/o + [[:triple/bnodes [[[:ax/var ?z1] [:ax/var ?z2]]]]]]]]]]]])))) (testing "in sub-SELECT queries" (is (= '[?x ?y ?z] (vv/get-scope-vars From 8600e7b65d315170063ca8cd7295349e6b2eb599 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 18:22:27 -0500 Subject: [PATCH 25/34] Add end-to-end tests for new features --- .../test-fixtures/inputs/query/select/select-12.edn | 3 +++ .../test-fixtures/inputs/query/select/select-13.edn | 7 +++++++ .../test-fixtures/inputs/query/select/select-14.edn | 4 ++++ .../test-fixtures/outputs/query/select/select-12.rq | 4 ++++ .../test-fixtures/outputs/query/select/select-13.rq | 9 +++++++++ .../test-fixtures/outputs/query/select/select-14.rq | 5 +++++ 6 files changed, 32 insertions(+) create mode 100644 dev-resources/test-fixtures/inputs/query/select/select-12.edn create mode 100644 dev-resources/test-fixtures/inputs/query/select/select-13.edn create mode 100644 dev-resources/test-fixtures/inputs/query/select/select-14.edn create mode 100644 dev-resources/test-fixtures/outputs/query/select/select-12.rq create mode 100644 dev-resources/test-fixtures/outputs/query/select/select-13.rq create mode 100644 dev-resources/test-fixtures/outputs/query/select/select-14.rq diff --git a/dev-resources/test-fixtures/inputs/query/select/select-12.edn b/dev-resources/test-fixtures/inputs/query/select/select-12.edn new file mode 100644 index 0000000..051e0c4 --- /dev/null +++ b/dev-resources/test-fixtures/inputs/query/select/select-12.edn @@ -0,0 +1,3 @@ +;; SELECT with lists +{:select [?x] + :where [[?s ?p (1 ?x 3 4)]]} diff --git a/dev-resources/test-fixtures/inputs/query/select/select-13.edn b/dev-resources/test-fixtures/inputs/query/select/select-13.edn new file mode 100644 index 0000000..ecf6e55 --- /dev/null +++ b/dev-resources/test-fixtures/inputs/query/select/select-13.edn @@ -0,0 +1,7 @@ +;; SELECT with blank node vectors +{:prefixes {:$ "" + :foaf ""} + :select [?x ?name] + :where [[[:p1 "v"] :q1 "w"] + [:x :q2 [:p2 "v"]] + [[:foaf/name ?name :foaf/mbox ""]]]} diff --git a/dev-resources/test-fixtures/inputs/query/select/select-14.edn b/dev-resources/test-fixtures/inputs/query/select/select-14.edn new file mode 100644 index 0000000..21227d2 --- /dev/null +++ b/dev-resources/test-fixtures/inputs/query/select/select-14.edn @@ -0,0 +1,4 @@ +;; SELECT with both lists and blank node vectors +{:prefixes {:$ ""} + :select [?x] + :where [{(1 [:p :q] (2 ?x)) {}}]} diff --git a/dev-resources/test-fixtures/outputs/query/select/select-12.rq b/dev-resources/test-fixtures/outputs/query/select/select-12.rq new file mode 100644 index 0000000..594c674 --- /dev/null +++ b/dev-resources/test-fixtures/outputs/query/select/select-12.rq @@ -0,0 +1,4 @@ +SELECT ?x +WHERE { + ?s ?p ( 1 ?x 3 4 ) . +} diff --git a/dev-resources/test-fixtures/outputs/query/select/select-13.rq b/dev-resources/test-fixtures/outputs/query/select/select-13.rq new file mode 100644 index 0000000..0d01066 --- /dev/null +++ b/dev-resources/test-fixtures/outputs/query/select/select-13.rq @@ -0,0 +1,9 @@ +PREFIX : +PREFIX foaf: +SELECT ?x ?name +WHERE { + [ :p1 "v" ] :q1 "w" . + :x :q2 [ :p2 "v" ] . + [ foaf:name ?name ; + foaf:mbox ] . +} diff --git a/dev-resources/test-fixtures/outputs/query/select/select-14.rq b/dev-resources/test-fixtures/outputs/query/select/select-14.rq new file mode 100644 index 0000000..2f7ded6 --- /dev/null +++ b/dev-resources/test-fixtures/outputs/query/select/select-14.rq @@ -0,0 +1,5 @@ +PREFIX : +SELECT ?x +WHERE { + ( 1 [ :p :q ] ( 2 ?x ) ) . +} From a0310a33408f12753b0de5082ccc03e8e920a3dc Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 18:50:00 -0500 Subject: [PATCH 26/34] Update docs with new features --- doc/triple.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/doc/triple.md b/doc/triple.md index a2ed955..415d5e7 100644 --- a/doc/triple.md +++ b/doc/triple.md @@ -108,10 +108,68 @@ Objects can be one of the following: **NOTE:** Variables are not allowed in triples in `DELETE DATA` OR `INSERT DATA` clauses. -**NOTE:** Technically literals are allowed in subject position according to the SPARQL spec, but no RDF implementation accepts that, so Flint does not allow for subject literals either. +**NOTE:** Technically literals are allowed in subject position according to the SPARQL spec, but no RDF implementation accepts that, so Flint does not allow for subject literals either (unless they are in an RDF list as described below). **NOTE:** SPARQL has [syntactic sugar](https://www.w3.org/TR/sparql11-query/#collections) for easy writing of RDF lists, but for simplicity that is not implemented in Flint. +## RDF Lists + +Flint supports SPARQL's [syntactic sugar](https://www.w3.org/TR/sparql11-query/#collections) for easy writing of RDF lists. For example: +```clojure +{:select [?x] + :where [[(1 ?x 3 4) ?p ?o]]} +``` + +becomes +```sparql +SELECT ?x +WHERE { + (1 ?x 3 4) ?p ?o +} +``` +which should then expanded out into an RDF list by your SPARQL query engine. + +RDF lists be placed in both subject and object position. If they are placed in subject position, then predicates and objects are optional (which is not usually the case). The predicate-object map can be left empty in normal form representation: +```clojure +{:select [?x] + :where [{(1 ?x 3 4) {}}]} +``` + +and can be left out entirely in triple representation: +```clojure +{:select [?x] + :where [[(1 ?x 3 4)]]} +``` + +RDF lists can also be nested, both with themselves and with blank node vectors (see below): +```clojure +{:select [?x] + :where [[(1 [:p :q] (2))]]} +``` + +## Blank Node Vectors + +Flint also has support for SPARQL's [blank node syntactic sugar](https://www.w3.org/TR/sparql11-query/#QSynBlankNodes), which will be expanded out by the SPARQL engine. For example: + +```clojure +{:prefixes {:foaf "" + :select [?name] + :where [{[:foaf/name ?name + :foaf/mbox ""] {}}]}} +``` + +becomes: +```sparql +PREFIX foaf: +SELECT ?name +WHERE { + [ foaf:name ?name + foaf:mbox ] . +} +``` + +Note that like with RDF lists, the predicate and object may be omitted here. + ## Property Paths Reference: [9. Property Paths](https://www.w3.org/TR/sparql11-query/#propertypaths) From bd5d75b5f949f40a43c7670c8e867d7469cc2c1b Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Tue, 6 Feb 2024 18:50:12 -0500 Subject: [PATCH 27/34] Special case for empty list --- src/main/com/yetanalytics/flint/format/triple.cljc | 4 +++- src/test/com/yetanalytics/flint/format/triple_test.cljc | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index ea6871d..be7aa6d 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -8,7 +8,9 @@ path) (defmethod f/format-ast-node :triple/list [_ [_ list]] - (str "( " (cstr/join " " list) " )")) + (if (empty? list) + "()" ; Special case for empty lists + (str "( " (cstr/join " " list) " )"))) (defmethod f/format-ast-node :triple/bnodes [{:keys [pretty?]} [_ po-pairs]] (if (empty? po-pairs) diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index 4616622..af775c6 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -61,6 +61,13 @@ [:ax/literal 2] [:triple/list [[:ax/literal 3]]]]]]] {:pretty? true}))) + (is (= "\"v\" :p () ." + (f/format-ast + '[:triple.vec/spo + [[:ax/literal "v"] + [:ax/prefix-iri :p] + [:triple/list []]]] + {:pretty? true}))) (is (= "[ foaf:name ?name ;\n foaf:mbox ] :q \"w\" ." (f/format-ast '[:triple.vec/spo From 1c36963fdf96a11d66083e311e6b4a7b2d8d6b9f Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:00:02 -0500 Subject: [PATCH 28/34] Allow combinations of empty and no-empty po-maps --- .../inputs/query/select/select-14.edn | 3 +- .../outputs/query/select/select-14.rq | 1 + .../com/yetanalytics/flint/format/triple.cljc | 31 +++++----- .../com/yetanalytics/flint/spec/triple.cljc | 56 ++++++++----------- .../yetanalytics/flint/validate/variable.cljc | 3 - .../flint/format/triple_test.cljc | 5 +- .../yetanalytics/flint/spec/triple_test.cljc | 6 +- 7 files changed, 47 insertions(+), 58 deletions(-) diff --git a/dev-resources/test-fixtures/inputs/query/select/select-14.edn b/dev-resources/test-fixtures/inputs/query/select/select-14.edn index 21227d2..95dfc62 100644 --- a/dev-resources/test-fixtures/inputs/query/select/select-14.edn +++ b/dev-resources/test-fixtures/inputs/query/select/select-14.edn @@ -1,4 +1,5 @@ ;; SELECT with both lists and blank node vectors {:prefixes {:$ ""} :select [?x] - :where [{(1 [:p :q] (2 ?x)) {}}]} + :where [{(1 [:p :q] (2 ?x)) {} + () {:r #{[]}}}]} diff --git a/dev-resources/test-fixtures/outputs/query/select/select-14.rq b/dev-resources/test-fixtures/outputs/query/select/select-14.rq index 2f7ded6..ea4e806 100644 --- a/dev-resources/test-fixtures/outputs/query/select/select-14.rq +++ b/dev-resources/test-fixtures/outputs/query/select/select-14.rq @@ -2,4 +2,5 @@ PREFIX : SELECT ?x WHERE { ( 1 [ :p :q ] ( 2 ?x ) ) . + () :r [] . } diff --git a/src/main/com/yetanalytics/flint/format/triple.cljc b/src/main/com/yetanalytics/flint/format/triple.cljc index be7aa6d..3b3f99a 100644 --- a/src/main/com/yetanalytics/flint/format/triple.cljc +++ b/src/main/com/yetanalytics/flint/format/triple.cljc @@ -25,24 +25,22 @@ (defmethod f/format-ast-node :triple.vec/s [_ [_ [s-str]]] (str s-str " .")) +(defn- format-spo-pretty [s-str po-str] + (let [indent (->> (repeat (inc (count s-str)) " ") + (cstr/join "") + (str "\n"))] + (str s-str " " (cstr/replace po-str #"\n" indent)))) + +(defn- format-spo [s-str po-str] + (str s-str " " po-str)) + (defmethod f/format-ast-node :triple.nform/spo [{:keys [pretty?]} [_ spo-pairs]] - (if pretty? + (let [format-spo (if pretty? format-spo-pretty format-spo) + join-sep (if pretty? " .\n" " . ")] (str (->> spo-pairs (map (fn [[s-str po-str]] - (let [indent (->> (repeat (inc (count s-str)) " ") - (cstr/join "") - (str "\n"))] - (str s-str " " (cstr/replace po-str #"\n" indent))))) - (cstr/join " .\n")) - " .") - (str (->> spo-pairs - (map (fn [[s-str po-str]] (str s-str " " po-str))) - (cstr/join " . ")) - " ."))) - -(defmethod f/format-ast-node :triple.nform/s [{:keys [pretty?]} [_ s-pairs]] - (let [join-sep (if pretty? " .\n" " . ")] - (str (->> s-pairs (map (fn [[s-str _]] s-str)) (cstr/join join-sep)) + (if (empty? po-str) s-str (format-spo s-str po-str)))) + (cstr/join join-sep)) " ."))) (defmethod f/format-ast-node :triple.nform/po [{:keys [pretty?]} [_ po-strs]] @@ -51,6 +49,9 @@ (map (fn [[p o]] (str p " " o))) (cstr/join join-sep)))) +(defmethod f/format-ast-node :triple.nform/po-empty [_ _] + "") + (defmethod f/format-ast-node :triple.nform/o [_ [_ o-strs]] (->> o-strs (cstr/join " , "))) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 0df4a77..41cc089 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -197,11 +197,9 @@ ;; Predicate Object #?(:clj - (defmacro make-pred-objs-spec - [pred-spec objs-spec] + (defmacro make-pred-objs-spec [pred-spec objs-spec] `(s/map-of ~pred-spec (s/or :triple.nform/o ~objs-spec) - :into [] - :min-count 1))) + :min-count 1 :conform-keys true :into []))) (def pred-objs-spec (make-pred-objs-spec ::predicate obj-set-spec)) @@ -220,10 +218,24 @@ ;; Subject Predicate Object +(def empty-map-spec + (s/map-of any? any? :count 0 :conform-keys true :into [])) + +#?(:clj + (defn- valid-conformed-spo? [spo-pairs] + (every? + (fn [[s po]] + (or (#{:triple/list :triple/bnodes} (first s)) + (#{:triple.nform/po} (first po)))) + spo-pairs))) + #?(:clj (defmacro make-nform-spec [subj-spec pred-objs-spec] - `(s/map-of ~subj-spec (s/or :triple.nform/po ~pred-objs-spec) - :conform-keys true :into []))) + `(s/and (s/map-of ~subj-spec + (s/or :triple.nform/po ~pred-objs-spec + :triple.nform/po-empty empty-map-spec) + :conform-keys true :into []) + valid-conformed-spo?))) (def normal-form-spec (make-nform-spec ::subject pred-objs-spec)) @@ -240,25 +252,6 @@ (def normal-form-novar-noblank-spec (make-nform-spec ::subject-novar-noblank pred-objs-novar-noblank-spec)) -;; Subject Predicate Object (List) - -(def empty-map-spec - (s/map-of any? any? :max-count 0 :conform-keys true :into [])) - -#?(:clj - (defmacro make-nform-no-po-spec [subj-list-spec] - `(s/map-of ~subj-list-spec empty-map-spec - :conform-keys true :into []))) - -(def normal-form-no-po-spec - (make-nform-no-po-spec ::subject-coll)) - -(def normal-form-no-po-nopath-spec - (make-nform-no-po-spec ::subject-coll-nopath)) - -(def normal-form-no-po-novar-spec - (make-nform-no-po-spec ::subject-coll-novar)) - ;; Triple Vectors (def triple-vec-spec @@ -276,7 +269,7 @@ (def triple-vec-novar-noblank-spec (s/tuple ::subject-novar-noblank ::predicate-novar ::object-novar-noblank)) -;; Triple Vectors (List, no predicates + objects) +;; Triple Vectors (Coll, no predicates + objects) (def triple-vec-no-po-spec (s/tuple ::subject-coll)) @@ -292,20 +285,17 @@ (def triple-spec (s/or :triple.vec/spo triple-vec-spec :triple.vec/s triple-vec-no-po-spec - :triple.nform/spo normal-form-spec - :triple.nform/s normal-form-no-po-spec)) + :triple.nform/spo normal-form-spec)) (def triple-nopath-spec (s/or :triple.vec/spo triple-vec-nopath-spec :triple.vec/s triple-vec-no-po-nopath-spec - :triple.nform/spo normal-form-nopath-spec - :triple.nform/s normal-form-no-po-nopath-spec)) + :triple.nform/spo normal-form-nopath-spec)) (def triple-novar-spec (s/or :triple.vec/spo triple-vec-novar-spec :triple.vec/s triple-vec-no-po-novar-spec - :triple.nform/spo normal-form-novar-spec - :triple.nform/s normal-form-no-po-nopath-spec)) + :triple.nform/spo normal-form-novar-spec)) (def triple-noblank-spec (s/or :triple.vec/spo triple-vec-noblank-spec @@ -364,7 +354,6 @@ (s/coll-of (s/or :triple.vec/spo triple-vec-nopath-spec :triple.vec/s triple-vec-no-po-nopath-spec :triple.nform/spo normal-form-nopath-spec - :triple.nform/s normal-form-no-po-nopath-spec :triple.quad/gspo quad-nopath-spec) :kind vector?)) @@ -372,7 +361,6 @@ (s/coll-of (s/or :triple.vec/spo triple-vec-novar-spec :triple.vec/s triple-vec-no-po-novar-spec :triple.nform/spo normal-form-novar-spec - :triple.nform/s normal-form-no-po-novar-spec :triple.quad/gspo quad-novar-spec) :kind vector?)) diff --git a/src/main/com/yetanalytics/flint/validate/variable.cljc b/src/main/com/yetanalytics/flint/validate/variable.cljc index 68789e7..f906592 100644 --- a/src/main/com/yetanalytics/flint/validate/variable.cljc +++ b/src/main/com/yetanalytics/flint/validate/variable.cljc @@ -130,9 +130,6 @@ [] spo-pairs)) -(defmethod get-scope-vars :triple.nform/s [[_ s]] - (get-scope-vars s)) - ;; Path (defmethod get-scope-vars :triple/path [[_ p]] diff --git a/src/test/com/yetanalytics/flint/format/triple_test.cljc b/src/test/com/yetanalytics/flint/format/triple_test.cljc index af775c6..951f756 100644 --- a/src/test/com/yetanalytics/flint/format/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/format/triple_test.cljc @@ -49,8 +49,9 @@ {:pretty? true}))) (is (= "( ?x ?y ) ." (f/format-ast - '[:triple.nform/s - [[[:triple/list [[:ax/var ?x] [:ax/var ?y]]] []]]] + '[:triple.nform/spo + [[[:triple/list [[:ax/var ?x] [:ax/var ?y]]] + [:triple.nform/po-empty []]]]] {:pretty? true}))) (is (= "\"v\" :p ( 1 2 ( 3 ) ) ." (f/format-ast diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index c026104..87d0bc9 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -61,7 +61,7 @@ (is (->> '{?s {(cat :x/one :x/two) #{?o}}} (s/explain-data ts/triple-nopath-spec) ::s/problems - (filter #(-> % :path first (= :triple.nform/spo))) + (filter #(-> % :path butlast (= [:triple.nform/spo 1 :triple.nform/po 0]))) (map :val) (every? (partial = '(cat :x/one :x/two)))))) (testing "with list and blank nodes" @@ -106,11 +106,11 @@ [:triple/list [[:ax/literal 2]]]]]]] (s/conform ts/triple-spec '[(1 ?x (2))]))) - (is (= '[:triple.nform/s + (is (= '[:triple.nform/spo [[[:triple/list [[:ax/literal 1] [:ax/var ?x] [:triple/list [[:ax/literal 2]]]]] - []]]] + [:triple.nform/po-empty []]]]] (s/conform ts/triple-spec '{(1 ?x (2)) {}}))) (is (= '[:triple.vec/s From 864e4738b6650ad829ad6a78387a1e63f6bd8cdd Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:01:39 -0500 Subject: [PATCH 29/34] Update comments --- src/main/com/yetanalytics/flint/spec/triple.cljc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 41cc089..b86909f 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -131,8 +131,6 @@ ;; Lists -;; List entries have the same spec as objects + `:triple/list` - ;; Since lists are constructed out of blank nodes, we do not allow list ;; syntactic sugar (i.e. `:triple/list`) where blank nodes are banned. @@ -147,6 +145,9 @@ ;; Blank Node Vectors +;; For obvious reasons, we don't allow bnode vectors to exist where blank +;; nodes are banned. + (defn- conform-pred-obj-pairs [po-pairs] (mapv (fn [{:keys [pred obj]}] [pred obj]) po-pairs)) From 62b2cef0b496ba72ceffbfd346a8ad1bf9bc9302 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:02:13 -0500 Subject: [PATCH 30/34] Use subject-coll-nopath spec --- src/main/com/yetanalytics/flint/spec/triple.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index b86909f..d3e38ec 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -276,7 +276,7 @@ (s/tuple ::subject-coll)) (def triple-vec-no-po-nopath-spec - (s/tuple ::subject-coll)) + (s/tuple ::subject-coll-nopath)) (def triple-vec-no-po-novar-spec (s/tuple ::subject-coll-novar)) From 79aefe7991bda2416322d5ecdf28b8da7426bee1 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:25:07 -0500 Subject: [PATCH 31/34] Add nopath, novar, and noblank tests for colls --- .../com/yetanalytics/flint/spec/triple.cljc | 20 ++- .../yetanalytics/flint/spec/triple_test.cljc | 124 +++++++++++++++++- 2 files changed, 136 insertions(+), 8 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index d3e38ec..0aec6be 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -90,6 +90,12 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/rdf-type ax/rdf-type-spec)) +(s/def ::predicate-noblank + ::predicate-nopath) + +(s/def ::predicate-novar-noblank + ::predicate-novar) + ;; Objects (includes Lists) (s/def ::object @@ -115,8 +121,8 @@ :ax/prefix-iri ax/prefix-iri-spec :ax/bnode ax/bnode-spec :ax/literal ax/literal-spec - :triple/list ::list-nopath - :triple/bnodes ::bnodes-nopath)) + :triple/list ::list-novar + :triple/bnodes ::bnodes-novar)) (s/def ::object-noblank (s/or :ax/var ax/variable-spec @@ -212,10 +218,10 @@ (make-pred-objs-spec ::predicate-novar obj-set-novar-spec)) (def pred-objs-noblank-spec - (make-pred-objs-spec ::predicate-nopath obj-set-noblank-spec)) + (make-pred-objs-spec ::predicate-noblank obj-set-noblank-spec)) (def pred-objs-novar-noblank-spec - (make-pred-objs-spec ::predicate-novar obj-set-novar-noblank-spec)) + (make-pred-objs-spec ::predicate-novar-noblank obj-set-novar-noblank-spec)) ;; Subject Predicate Object @@ -259,16 +265,16 @@ (s/tuple ::subject ::predicate ::object)) (def triple-vec-nopath-spec - (s/tuple ::subject ::predicate-nopath ::object)) + (s/tuple ::subject-nopath ::predicate-nopath ::object-nopath)) (def triple-vec-novar-spec (s/tuple ::subject-novar ::predicate-novar ::object-novar)) (def triple-vec-noblank-spec - (s/tuple ::subject-noblank ::predicate-nopath ::object-noblank)) + (s/tuple ::subject-noblank ::predicate-noblank ::object-noblank)) (def triple-vec-novar-noblank-spec - (s/tuple ::subject-novar-noblank ::predicate-novar ::object-novar-noblank)) + (s/tuple ::subject-novar-noblank ::predicate-novar-noblank ::object-novar-noblank)) ;; Triple Vectors (Coll, no predicates + objects) diff --git a/src/test/com/yetanalytics/flint/spec/triple_test.cljc b/src/test/com/yetanalytics/flint/spec/triple_test.cljc index 87d0bc9..b2677b4 100644 --- a/src/test/com/yetanalytics/flint/spec/triple_test.cljc +++ b/src/test/com/yetanalytics/flint/spec/triple_test.cljc @@ -178,4 +178,126 @@ [:ax/prefix-iri :q] [:ax/literal "w"]]] (s/conform ts/triple-spec - '[[:p1 ?x1 :p2 ?x2] :q "w"])))))) + '[[:p1 ?x1 :p2 ?x2] :q "w"]))) + (testing "and path + var in subject" + (is (= '[:triple.vec/spo + [[:triple/bnodes + [[[:triple/path + [:path/branch + [[:path/op cat] + [:path/paths + [[:path/terminal [:ax/prefix-iri :p1]] + [:path/terminal [:ax/prefix-iri :p2]]]]]]] + [:ax/var ?x]]]] + [:ax/prefix-iri :q] + [:ax/literal "w"]]] + (s/conform ts/triple-spec + '[[(cat :p1 :p2) ?x] :q "w"]))) + (is (= '[:triple.nform/spo + [[[:triple/bnodes + [[[:triple/path + [:path/branch + [[:path/op cat] + [:path/paths + [[:path/terminal [:ax/prefix-iri :p1]] + [:path/terminal [:ax/prefix-iri :p2]]]]]]] + [:ax/var ?x]]]] + [:triple.nform/po + [[[:ax/prefix-iri :q] + [:triple.nform/o + [[:ax/literal "w"]]]]]]]]] + (s/conform ts/triple-spec + '{[(cat :p1 :p2) ?x] {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-nopath-spec + '[[(cat :p1 :p2) ?x] :q "w"]))) + (is (not (s/valid? ts/triple-novar-spec + '[[(cat :p1 :p2) ?x] :q "w"]))) + (is (not (s/valid? ts/triple-noblank-spec + '[[(cat :p1 :p2) ?x] :q "w"]))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '[[(cat :p1 :p2) ?x] :q "w"]))) + (is (not (s/valid? ts/triple-nopath-spec + '[[(cat :p1 :p2) ?x]]))) + (is (not (s/valid? ts/triple-novar-spec + '[[(cat :p1 :p2) ?x]]))) + (is (not (s/valid? ts/triple-noblank-spec + '[[(cat :p1 :p2) ?x]]))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '[[(cat :p1 :p2) ?x]]))) + (is (not (s/valid? ts/triple-nopath-spec + '{[(cat :p1 :p2) ?x] {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-novar-spec + '{[(cat :p1 :p2) ?x] {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-noblank-spec + '{[(cat :p1 :p2) ?x] {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '{[(cat :p1 :p2) ?x] {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-novar-spec + '[(?x ?y) :q "w"]))) + (is (not (s/valid? ts/triple-noblank-spec + '[(?x ?y) :q "w"]))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '[(?x ?y) :q "w"]))) + (is (not (s/valid? ts/triple-novar-spec + '{(?x ?y) {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-noblank-spec + '{(?x ?y) {:q #{"w"}}}))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '{(?x ?y) {:q #{"w"}}})))) + (testing "and path + var in object" + (is (= '[:triple.vec/spo + [[:ax/prefix-iri :x] + [:ax/prefix-iri :q] + [:triple/bnodes + [[[:triple/path + [:path/branch + [[:path/op cat] + [:path/paths + [[:path/terminal [:ax/prefix-iri :r1]] + [:path/terminal [:ax/prefix-iri :r2]]]]]]] + [:ax/literal "v"]]]]]] + (s/conform ts/triple-spec + '[:x :q [(cat :r1 :r2) "v"]]))) + (is (= '[:triple.nform/spo + [[[:ax/prefix-iri :x] + [:triple.nform/po + [[[:ax/prefix-iri :q] + [:triple.nform/o + [[:triple/bnodes + [[[:triple/path + [:path/branch + [[:path/op cat] + [:path/paths + [[:path/terminal [:ax/prefix-iri :r1]] + [:path/terminal [:ax/prefix-iri :r2]]]]]]] + [:ax/literal "v"]]]]]]]]]]]] + (s/conform ts/triple-spec + '{:x {:q #{[(cat :r1 :r2) "v"]}}}))) + (is (not (s/valid? ts/triple-nopath-spec + '[:x :q [(cat :r1 :r2) "v"]]))) + (is (not (s/valid? ts/triple-novar-spec + '[:x :q [:r ?v]]))) + (is (not (s/valid? ts/triple-noblank-spec + '[:x :q [:r ?v]]))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '[:x :q [:r ?v]]))) + (is (not (s/valid? ts/triple-nopath-spec + '{:x {:q #{[(cat :r1 :r2) "v"]}}}))) + (is (not (s/valid? ts/triple-novar-spec + '{:x {:q #{[:r ?v]}}}))) + (is (not (s/valid? ts/triple-noblank-spec + '{:x {:q #{[:r ?v]}}}))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '{:x {:q #{[:r ?v]}}}))) + (is (not (s/valid? ts/triple-novar-spec + '[:x :q (?w ?v)]))) + (is (not (s/valid? ts/triple-noblank-spec + '[:x :q (?w ?v)]))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '[:x :q (?w ?v)]))) + (is (not (s/valid? ts/triple-novar-spec + '{:x {:q #{(?w ?v)}}}))) + (is (not (s/valid? ts/triple-noblank-spec + '{:x {:q #{(?w ?v)}}}))) + (is (not (s/valid? ts/triple-novar-noblank-spec + '{:x {:q #{(?w ?v)}}}))))))) From 8fe0ff1997ddbcec6e6886f9a97ad06b4f80337c Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:28:36 -0500 Subject: [PATCH 32/34] Update CHANGELOG and version number --- CHANGELOG.md | 7 +++++++ README.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fce873d..72487a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v0.3.0 + +- Add support for RDF List syntactic sugar. +- Add support for blank node vector syntactic sugar. +- Modify the AST tree for triples to support the new features and to remove redundant nodes in the tree. +- Rework blank node validation to make the implementation simpler (this results in minor changes to the error output). + ## v0.2.1 - Update GitHub Actions CI and CD to remove deprecation warnings. diff --git a/README.md b/README.md index 8b593d4..59f8ec6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you are using Apache Jena, check out the [flint-jena](https://github.com/yeta Add the following to your `deps.edn` map. ```clojure -com.yetanalytics/flint {:mvn/version "0.2.1" +com.yetanalytics/flint {:mvn/version "0.3.0" :exclusions [org.clojure/clojure org.clojure/clojurescript]} ``` From e85ea39d5976b35d0b8ee013b2d1e3a688ebd952 Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:32:39 -0500 Subject: [PATCH 33/34] Fix cljs test failures --- .../com/yetanalytics/flint/spec/triple.cljc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/com/yetanalytics/flint/spec/triple.cljc b/src/main/com/yetanalytics/flint/spec/triple.cljc index 0aec6be..faef4f9 100644 --- a/src/main/com/yetanalytics/flint/spec/triple.cljc +++ b/src/main/com/yetanalytics/flint/spec/triple.cljc @@ -5,8 +5,7 @@ #?(:cljs (:require-macros [com.yetanalytics.flint.spec.triple :refer [make-obj-spec make-pred-objs-spec - make-nform-spec - make-nform-no-po-spec]]))) + make-nform-spec]]))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Subj/Pred/Obj Specs @@ -228,13 +227,14 @@ (def empty-map-spec (s/map-of any? any? :count 0 :conform-keys true :into [])) -#?(:clj - (defn- valid-conformed-spo? [spo-pairs] - (every? - (fn [[s po]] - (or (#{:triple/list :triple/bnodes} (first s)) - (#{:triple.nform/po} (first po)))) - spo-pairs))) +;; cljs-specific ignore is needed since this fn is called in a macro. +#_{:clj-kondo/ignore #?(:clj [] :cljs [:unused-private-var])} +(defn- valid-conformed-spo? [spo-pairs] + (every? + (fn [[s po]] + (or (#{:triple/list :triple/bnodes} (first s)) + (#{:triple.nform/po} (first po)))) + spo-pairs)) #?(:clj (defmacro make-nform-spec [subj-spec pred-objs-spec] From 572555b1cec0285201b19624fc1190e780d8430e Mon Sep 17 00:00:00 2001 From: kelvinqian00 Date: Wed, 7 Feb 2024 11:40:47 -0500 Subject: [PATCH 34/34] Remove outdated line in the doc --- doc/triple.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/triple.md b/doc/triple.md index 415d5e7..8d607d6 100644 --- a/doc/triple.md +++ b/doc/triple.md @@ -110,8 +110,6 @@ Objects can be one of the following: **NOTE:** Technically literals are allowed in subject position according to the SPARQL spec, but no RDF implementation accepts that, so Flint does not allow for subject literals either (unless they are in an RDF list as described below). -**NOTE:** SPARQL has [syntactic sugar](https://www.w3.org/TR/sparql11-query/#collections) for easy writing of RDF lists, but for simplicity that is not implemented in Flint. - ## RDF Lists Flint supports SPARQL's [syntactic sugar](https://www.w3.org/TR/sparql11-query/#collections) for easy writing of RDF lists. For example: