Skip to content

Simplify usage when passing bindings into a query #14

@RickMoynihan

Description

@RickMoynihan

Currently we do the following pattern:

(def some:predicate ,,,)

(defn my-query [binding-one binding-two db]
  ((match/construct {:binding binding-one :some-var ?val}
                                 [[binding-one some:predicate ?val]
                                   [binding-one binding-two "some constraint"]]) 
   db))

We do it quite a lot.

I'd quite like to simplify this somewhat. Perhaps with a defconstruct, defselect type syntax... though I'd also be open to just replacing the existing query macros, as it'd be good to support an anonymous usage too... and we can probably break compatibility right now, as updating the call sites probably isn't too hard at this stage.

(def myquery (newconstruct {:grafter.rdf/uri subject
                                                 ?p ?o}
                                                [[subject ?p ?o]]))

(myquery {'subject :some/value} database)

I haven't thought of all the pros and cons to the above syntax, and I intend it mainly to be illustrative.

So I'd quite like to explore some proposals here, on how this might work.

We do something similar in another macro we have (we don't have that many honest) https://github.com/Swirrl/grafter.db/blob/1329fd597d41680b0fbcf0e497888b32ea840b8f/test/grafter/db/triplestore/query_test.clj#L21 here. This was extracted into a new repo by @scottlowe from something I wrote initially in zib, the extracted version should have a few improvements, which are yet to be backported into zib. @danmidwood and @scottlowe will I'm sure be more than happy to explain how the binding syntax there works. It's essentially an explicit variant with a few more bells and whistles on a lower level variation here https://github.com/Swirrl/grafter/blob/a061ca1524149e02ca16d1737344a770b7284278/src/grafter/rdf/sparql.clj#L120 that in turn builds on some stuff in sesame/rdf4j.

You'll note the grafter.db approach requires us to be explicit about the bindings we expect to be provided to us. So that might also be beneficial here, depending on whether we can disambiguate some:predicate from an unbound local (I'm pretty sure we probably can -- though it's probably not best to assume the:in the symbol means anything. I think only?*` should be special).

I'll be in the office tomorrow to talk about it. It should be a pretty fun task, though it's not particularly critical for anything... So the definition of done could just end up being we thought it was a bad idea, or we have a proposal and design for how it would work but no implementation, or maybe an experimental implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions