Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: bind queries #397

Merged
merged 17 commits into from
Feb 22, 2023
Merged

Feature: bind queries #397

merged 17 commits into from
Feb 22, 2023

Conversation

cap10morgan
Copy link
Contributor

Closes #314

Adds support for bind maps (only; it does implement the old bind tuple format) that only work on individual results, not aggregates across all results (to better align with the SPARQL spec).

Also adds a couple of useful query fns: quot and subStr for integer division and indexed substring support, respectively.

I left in a couple of commented-out usages of log/debug-async->vals and log/debug-async->>vals to demonstrate how they're used. But there are probably runtime perf considerations with how those work even if you're log level is higher than DEBUG, hence the commenting-out.

@cap10morgan cap10morgan requested a review from a team February 21, 2023 23:50
They weren't actually doing the logging before! I had recently converted these from fns, so didn't notice the need for this at first.
Copy link
Contributor

@zonotope zonotope left a comment

Choose a reason for hiding this comment

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

This looks very good, but I think we want to handle multiple bound values slightly differently.

(defn add-fn-result-to-solution
[solution var-name result]
(-> solution
(assoc var-name {::var var-name ::val result})))
Copy link
Contributor

Choose a reason for hiding this comment

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

We might also have to infer the data type here and add it to the map in case we ever want to use one of these bound values in an index scan while matching some later pattern. Index scans will come out with weird results with nil as the data type because of the way our sorted-set comparators treat nils.

@@ -93,3 +97,40 @@

#?(:cljs
(log-to-console!))

#?(:clj
(defmacro debug->>val
Copy link
Contributor

Choose a reason for hiding this comment

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

boy oh boy are these macros gonna come in handy.

[_db solution pattern _ error-ch]
(let [bind (val pattern)
out-ch (async/chan 2)
binds-ch (async/to-chan! (vals bind))]
Copy link
Contributor

Choose a reason for hiding this comment

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

I could be wrong, but I don't think we want to put the individual binds in a channel to be evaluated individually. I think we want all the binds to apply to the solution at once instead of the making multiple copies and applying each bind individually to one of the copies. I also don't think we need the coordination that pipeline-async gives us since the user-supplied functions won't be asynchronous.

If we have n vars in a bind map, then this would output n new solutions for each input solution, each with only one of those vars bound. I think we should instead output only one new solution for each input solution with all n vars bound in it together.

:bind pattern processing still needs to be async in case the user-supplied function throws an exception so we can put that exception onto the error channel, but I think we can get away with using the go block starting at line 366 and putting a reduce over (vals bind) that computes all the binds and adds them to the solution at once, and then returns the new solution with all the binds added instead of funneling each of the binds individually through a channel into pipeline-async.


(def allowed-symbols
(set/union allowed-aggregates allowed-filters))
(set/union allowed-aggregates allowed-fns))
Copy link
Contributor

Choose a reason for hiding this comment

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

This is pretty minor, but we might need a better name than allowed-fns, because all of the aggregates are also functions; they just act on different kinds of inputs (grouped values vs individual values). It doesn't matter in practice, but it might make the code a little more confusing for the uninitiated. I get why "filters" is no longer a good name because it's to specific. Those functions now are used in more than just filters, but I think "fns" is too general. I can't think of a better name right now, but I'll noodle over it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think of my proposal in e8e2945?

Copy link
Contributor

Choose a reason for hiding this comment

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

perfect!

:where [[?s :schema/age ?age]
{:bind {?decadesOld (quot ?age 10)}}
[?s :schema/name ?name]
{:bind {?firstLetterOfName (subStr ?name 0 1)}}]
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it might be useful to have a test that has a bind map with multiple entries. Maybe even combine the two here (after the pattern involving ?name).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

giphy

@cap10morgan
Copy link
Contributor Author

OK @zonotope I think this is ready for re-review

Copy link
Contributor

@zonotope zonotope left a comment

Choose a reason for hiding this comment

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

⛓️

@@ -16,13 +16,13 @@
[?s :ex/favNums ?favNums]]
:group-by ?name}
subject @(fluree/query db qry)]
(is (= [["Cam" 2] ["Alice" 3] ["Brian" 1]]
(is (= [["Liam" 2] ["Cam" 2] ["Alice" 3] ["Brian" 1]]
Copy link
Contributor

Choose a reason for hiding this comment

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

this name looks familiar :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

😉

@cap10morgan cap10morgan merged commit 9e9718b into main Feb 22, 2023
@cap10morgan cap10morgan deleted the feature/query-bind branch February 22, 2023 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement BIND for FlureeQL
2 participants