Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions server/resources/migrations/73_vae_uuids.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
drop function public.json_uuid_to_uuid(v jsonb);

drop index vae_uuid_index;

drop index eav_uuid_index;
18 changes: 18 additions & 0 deletions server/resources/migrations/73_vae_uuids.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
create or replace function public.json_uuid_to_uuid(v jsonb) returns uuid
language sql
parallel safe
immutable
as $$
select (v->>0)::uuid
end;
$$;

-- Create this index concurrently before running the migration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

create index if not exists vae_uuid_index
on triples(app_id, public.json_uuid_to_uuid(value), attr_id, entity_id)
where vae;

-- Create this index concurrently before running the migration
create unique index if not exists eav_uuid_index
on triples(app_id, entity_id, attr_id, public.json_uuid_to_uuid(value))
where eav;
33 changes: 17 additions & 16 deletions server/src/instant/db/datalog.clj
Original file line number Diff line number Diff line change
Expand Up @@ -523,20 +523,20 @@
(string/replace (name x) "-" "_"))

(defn- match-table-cols
"Every match table returns entity-id, attr-id, value-blob, value-uuid,
"Every match table returns entity-id, attr-id, value-blob, is-ref-val,
and created-at columns. This is a quick helper to generate the column names"
[table-name]
[(kw table-name :-entity-id)
(kw table-name :-attr-id)
(kw table-name :-value-blob)
(kw table-name :-value-uuid)
(kw table-name :-is-ref-val)
(kw table-name :-created-at)])

(defn- match-table-select
"This generates the select portion of the match table. "
[table-name]
(map vector [:entity-id :attr-id :value
[:case :eav [:cast [:->> :value :0] :uuid] :else :null]
:eav
:created-at]
(match-table-cols table-name)))

Expand Down Expand Up @@ -722,14 +722,14 @@
{:name :ea_index
:cols [:e :a]
:idx-key :ea}
{:name :eav_index
{:name :eav_uuid_index
:cols [:e :a :v]
:idx-key :eav}
{:name :triples_string_trgm_gist_idx
:cols [:a :v]
:idx-key :ave
:data-type :string}
{:name :vae_index
{:name :vae_uuid_index
:cols [:v :a :e]
:idx-key :vae}
{:name :triples_created_at_idx
Expand Down Expand Up @@ -808,7 +808,7 @@
For example:

[1 [:v :v]] => [:value :match-1-value-blob]
[1 [:e :v]] => [:entity-id :match-1-value-uuid]
[1 [:e :v]] => [:entity-id [:json_uuid_to_uuid :match-1-value-blob]]
[1 [:v :a]] => [:value [:to_jsonb :match-1-attr-id]]"
[prefix dest-idx [origin-ctype dest-ctype]]

Expand All @@ -821,7 +821,7 @@
[:value [:to_jsonb (dest-col (component-type->col-name dest-ctype))]]

(= :v dest-ctype)
[(component-type->col-name origin-ctype) (dest-col :value-uuid)]
[(component-type->col-name origin-ctype) [:json_uuid_to_uuid (dest-col :value-blob)]]

:else
[(component-type->col-name origin-ctype)
Expand Down Expand Up @@ -863,7 +863,7 @@

The second part joins the first on

[[:= :entity-id :match-0-value-uuid]]"
[[:= :entity-id [:json_uuid_to_uuid :match-0-value-blob]]]"
[prefix symbol-map named-p]
(->> named-p
variable-components
Expand Down Expand Up @@ -1061,7 +1061,7 @@
(if (named-variable? x)
(assoc acc pat-idx {:sym sym
:ref-value? (and (= :v component)
(= :eav (idx-key (:idx named-p))))})
(= :vae (idx-key (:idx named-p))))})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also fixes a bug in the topics, where we weren't removing vae triples from the topics symbol map. (see https://github.com/jsventures/instant/pull/827 for more explanation).

I don't think we actually encounter the bug in prod because we always invalidate the id field on updates (will be fixed by #739). What could happen when we fix the id bug: say you have a query that orders on order-field, if you update order-field on an existing entity outside of the result set so that it should be in the result set, we won't invalidate the query because our topic is looking at a specific entity (e.g. [:eid :order-field _]). With this change, the topic will be [_ :order-field :_], so the query will get invalidated. Again, it's not a problem now because we have the topic [_ :id _] and it gets invalidated on any change.

acc)))
{}
[[:e 0] [:a 1] [:v 2]]))
Expand Down Expand Up @@ -1747,20 +1747,21 @@
(parse-uuid x)))

(defn- sql-row->triple
"Converts the sql result, which returns value in either the
value-uuid or value-blob col, into our triple format.
"Converts the sql result into our triple format.
Optionally parses uuids, when handling batched results that return JSON"
[row [e-col a-col v-blob-col v-uuid-col t-col] coerce-uuids?]
[row [e-col a-col v-blob-col v-is-ref-val-col t-col] coerce-uuids?]
(if coerce-uuids?
[(safe-parse-uuid (get row e-col))
(safe-parse-uuid (get row a-col))
(or (safe-parse-uuid (get row v-uuid-col))
(get row v-blob-col))
(if (get row v-is-ref-val-col)
(safe-parse-uuid (get row v-blob-col))
(get row v-blob-col))
(get row t-col)]
[(get row e-col)
(get row a-col)
(or (get row v-uuid-col)
(get row v-blob-col))
(if (get row v-is-ref-val-col)
(safe-parse-uuid (get row v-blob-col))
(get row v-blob-col))
(get row t-col)]))

(defn- ensure-default-symbol-values [symbol-fields symbol-values]
Expand Down
10 changes: 10 additions & 0 deletions server/src/instant/db/instaql.clj
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,16 @@
patterns)]
(collect-query-results ctx (:data datalog-result) forms)))))

(defn explain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh heck yeah!

"Generates a nested datalog query, then runs explain."
[ctx o]
(let [query-hash (forms-hash o)
explain-fn (or (:datalog-explain-fn ctx)
d/explain)
{:keys [patterns]} (instaql-query->patterns ctx o)]
(explain-fn (assoc ctx :query-hash query-hash)
patterns)))

;; BYOP InstaQL

(defn safe-table
Expand Down
2 changes: 1 addition & 1 deletion server/src/instant/db/model/attr_pat.clj
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
checking-data-type?]}
v-actualized?]
(let [ref? (= value-type :ref)
e-idx (if ref? :eav :ea)
e-idx (if ref? :vae :ea)
v-idx (cond
(and index?
(not indexing?)
Expand Down
34 changes: 17 additions & 17 deletions server/test/instant/db/datalog_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@
(deftest joins
(testing "join conditions bind symbols to the matching previous patterns"
(is (=
'(([:= :entity-id :match-0-value-uuid])
'(([:= :entity-id [:json_uuid_to_uuid :match-0-value-blob]])
([:= :entity-id :match-0-attr-id]
[:= :attr-id :match-0-value-uuid]
[:= :attr-id [:json_uuid_to_uuid :match-0-value-blob]]
[:= :attr-id :match-1-entity-id]))
(raw-pats->join-conds '[[:eav ?a ?b ?c]
[:ea ?c ?d ?e]
Expand All @@ -99,10 +99,10 @@
(is (= '(([:= :value [:to_jsonb :match-0-attr-id]]))
(raw-pats->join-conds '[[:av _ ?a] [:eav _ _ ?a]]))))
(testing "join conditions matches entities to coerced values"
(is (= '(([:= :entity-id :match-0-value-uuid]))
(is (= '(([:= :entity-id [:json_uuid_to_uuid :match-0-value-blob]]))
(raw-pats->join-conds '[[:eav _ _ ?a] [:vae ?a]]))))
(testing "join conditions matches attrs to coerced values"
(is (= '(([:= :attr-id :match-0-value-uuid]))
(is (= '(([:= :attr-id [:json_uuid_to_uuid :match-0-value-blob]]))
(raw-pats->join-conds '[[:eav _ _ ?a] [:av _ ?a]]))))
(testing "join conditions matches entities to attrs"
(is (= '(([:= :entity-id :match-0-attr-id]))
Expand Down Expand Up @@ -282,10 +282,10 @@
(let [movie-title-aid (resolvers/->uuid r :movie/title)
movie-director-aid (resolvers/->uuid r :movie/director)
person-name-aid (resolvers/->uuid r :person/name)]
(is (= '{:topics [[:ea _ #{:movie/title} #{"Predator"}]
[:eav #{"eid-predator"} #{:movie/director} _]
[:ea _ #{:person/name} _]]

(is (= '{:topics
[[:ea _ #{:movie/title} #{"Predator"}]
[:vae #{"eid-predator"} #{:movie/director} _]
[:ea _ #{:person/name} _]]
:symbol-values {?e #{"eid-predator"},
?director #{"eid-john-mctiernan"},
?name #{"John McTiernan"}},
Expand All @@ -296,7 +296,7 @@

(query-pretty
[[:ea '?e movie-title-aid "Predator"]
[:eav '?e movie-director-aid '?director]
[:vae '?e movie-director-aid '?director]
[:ea '?director person-name-aid '?name]])))))

(testing "refs jump vae"
Expand Down Expand Up @@ -344,16 +344,16 @@
[[:ea '?director person-name-aid "John McTiernan"]
[:vae '?movie movie-director-aid '?director]
[:ea '?movie movie-title-aid '?title]])
%
(resolvers/walk-friendly r %)
(drop-join-rows-created-at %)))
%
(resolvers/walk-friendly r %)
(drop-join-rows-created-at %)))
q2 (future (as-> (d/query
ctx [[:ea '?e movie-title-aid "Predator"]
[:eav '?e movie-director-aid '?director]
[:vae '?e movie-director-aid '?director]
[:ea '?director person-name-aid '?name]])
%
(resolvers/walk-friendly r %)
(drop-join-rows-created-at %)))]
%
(resolvers/walk-friendly r %)
(drop-join-rows-created-at %)))]

;; Wait for queries to batch
(loop [i 0]
Expand Down Expand Up @@ -387,7 +387,7 @@
@q1))
(is (=
'{:topics [[:ea _ #{:movie/title} #{"Predator"}]
[:eav #{"eid-predator"} #{:movie/director} _]
[:vae #{"eid-predator"} #{:movie/director} _]
[:ea _ #{:person/name} _]]

:symbol-values {?e #{"eid-predator"},
Expand Down
Loading
Loading