fluree / db

Fluree database library
https://fluree.github.io/db/
Other
339 stars 22 forks source link

Allow `values` to include subject IRIs #703

Closed dpetran closed 6 months ago

dpetran commented 10 months ago

If a query specifies compacted IRIs in a values clause, they are not expanded.

{"@context" context
  "values" ["?s" ["ex:2914cb3a-d6a8-4978-8df2-a5919bee3054" "ex:5b673c38-aa12-4512-aee7-8fd7145c79c6"]]
  "where" {"@id" "?s" "?p" "?o"}
   "select" ["?s" "?p" "?o"]}

;; parses to

{:context {:type-key "@type", "ex" {:id "http://example.org/"}, "schema" {:id "http://schema.org/"}, "f" {:id "https://ns.flur.ee/ledger#"}},
   ;; values aren't expanded, datatype is string
   :values [{?s #:fluree.db.query.exec.where{:var ?s, :val "ex:2914cb3a-d6a8-4978-8df2-a5919bee3054", :datatype 1}}
            {?s #:fluree.db.query.exec.where{:var ?s, :val "ex:5b673c38-aa12-4512-aee7-8fd7145c79c6", :datatype 1}}],
   :where
   #:fluree.db.query.exec.where{:patterns
                                ([#:fluree.db.query.exec.where{:var ?s}
                                  #:fluree.db.query.exec.where{:var ?p}
                                  #:fluree.db.query.exec.where{:var ?o}])},
   :select [#fluree.db.query.exec.select.VariableSelector{:var ?s}
            #fluree.db.query.exec.select.VariableSelector{:var ?p}
            #fluree.db.query.exec.select.VariableSelector{:var ?o}],
   :opts {}}
zonotope commented 10 months ago

I think the problem here is not necessarily that the IRIs don't get expanded; it's that they aren't recognized as IRIs at all and treated as strings. That's why the key for the predicate match is ::where/val instead of ::where/iri.

We need a way for the user to indicate that a particular values binding should be treated as an IRI instead of a string. I don't think it's a good idea to use "@id" maps like we used previously to indicate that a string should be treated like an IRI because it breaks the FQL query map abstraction. The same variable would represent the IRI of a node's id in one place but the node itself in another.

One option is to implement the SPARQL iri function and allow it to be used in a values binding like so:

[?s [(iri "ex:foo")]]

I think this is succinct and intuitive, but I think, if we went this route, we should limit function execution in values mappings to the iri function and only that. The function execution system operates on solution maps, and the values binding is processed before any solutions are in flight.

This strategy would also only work for IRIs, and we would still need other solutions to allow users to specify other datatypes and other metadata besides datatype like language tags in a values binding.

Another option is to allow a user to supply a value map specifying the datatype to be "xsd:anyURI" like so:

[?s [{"@value" "ex:foo", "@type" "xsd:anyURI"}]]

This solution is a bit verbose, but it does provide a general mechanism for the user to specify a datatype (and language) instead of relying on the system to infer one.

aaj3f commented 10 months ago

@dpetran @zonotope -- as a test case for this before we PR, could we just add tests for using values for subject-position ?bindings generally (whether they're compacted or not).

If the requirement is that we use @type + @value like you mentioned, Ben, that's fine, as long as we have a test that articulates the expected end user behavior so we can document and ensure the functionality works for the use case