- From: Pierre-Antoine Champin <pierre-antoine.champin@liris.cnrs.fr>
- Date: Mon, 24 Aug 2015 17:08:51 +0200
- To: Gregg Kellogg <gregg@greggkellogg.net>
- Cc: "public-ldp-comments@w3.org" <public-ldp-comments@w3.org>
- Message-ID: <CA+OuRR_iCopd73eUN=DVJBcodLEEpcRbLH85NNgLHNgfzQ8Ckw@mail.gmail.com>
Hi Gregg, regarding Bind and paths: I as well implemented the path operator from scratch, without relying on SPARQL. And after your e-mail, I fiddled a bit with SPARQL to see how paths could be systematically converted to SPARQL, but it is quite tricky. Also, you wrote: > Thanks for the feedback, m sure I'll have more questions as I go through > test cases, for example the notion of BNodes exactly matching vs being > treated as existential quantifiers, which may make using standard BGP more > difficult. > The only part of LDPatch that would produce a BGP are the Bind statements, and BNodes are not allowed anywere in Bind statements, so that should not be a problem. BNodes may appear in Add, AddNew and UpdateList, and that should not be a problem either, since those would translate to an InsertClause in SPARQL-Upadte, where BNodes have the same semantics as in LD Patch, according to Section 3.1.1 in SPARUL <http://www.w3.org/TR/sparql11-update/#insertData>: Blank nodes in *QuadData*s are assumed to be disjoint from the blank nodes > in the Graph Store, i.e., will be inserted with "fresh" blank nodes. > It is a trickier for Delete and DeleteExisting. SPARQL-Update forbids blank nodes in a DeleteClause, arguing that deleting a fresh bnode would do nothing. LD-Patch does *not* forbid a BNode in a Delete statement, and specifies that the scope of BNode identifiers is the whole LDPatch document. So the following patch is correct: Add { :a :b _:fresh } . Delete { :a :b _:fresh } . even if it leaves the graph unchanged. This is a rather pathological case, though... On Wed, Aug 19, 2015 at 8:54 PM, Gregg Kellogg <gregg@greggkellogg.net> wrote: > On Aug 19, 2015, at 10:38 AM, Pierre-Antoine Champin < > pierre-antoine.champin@liris.cnrs.fr> wrote: > > Hi Gregg, > > On Fri, Aug 14, 2015 at 3:56 AM, Gregg Kellogg <gregg@greggkellogg.net> > wrote: > >> I’ve been attempting an implementation in Ruby [1], and came up with some >> observations and questions: >> >> # Bind >> >> These examples are of more complicated binds which are syntactically >> correct. The test suite could probably use more pathological examples. >> > > Where does this list come from? Is it a generalization of all the Bind > statements found in the test suite? If so, I think at least one example is > missing: spec_example24_positive.ldpatch contains a variable in the path. > But surely, more pathologogical examples could be added. > > > It was actually more a consequence of following legal grammar, even though > it may not be a useful path. > > Bind ?x :a / :b / :c >> Bind ?x :a / ^:b / :c >> Bind ?x :a [ / :p = "v"] / :c / ^:d >> Bind ?x :a / 1 / :b >> Bind ?x :a / [ / :c / :d = "bar"] / ^:e >> Bind ?x :a / ! / ^:e >> > > The last example is incorrect: "!" should not be preceded by "/". > > > I figured that out implementing my parser, thanks. > > Additionally, although ":a" is syntactically correct, I'm guessing what > you mean is "?a", so it should read > > > Actually, in Turtle, :a would represent the empty prefix, and is often > used as a shortcut for creating IRIs in examples. > > Bind ?x ?a ! / ^:e > > Note that the "!" here is not very interesting since, if ?a is bound, it > must be bound to a unique value -- and if it is not bound, this is an > error, see below. > > > Yes, "!" Seems useful mostly as a sieve in the middle of a path. > > What is the effect of a bind statement using unbound variables (as values)? >> > > Per the last list item of 4.3.8 Error Handling > <http://www.w3.org/TR/ldpatch/#error-handling>, If a variable is used > without being previously bound, then the parsing fails . This applies to > *any* statement. > > > Yes, that makes the most sense. > > You should not think of variable as "logical variables", as in SPARQL, but > rather as "program variables" (i.e. placeholders containing a value, a node > of the graph) that are required as an indirection to refer to blank nodes. > > > My system sequences through operations and updates a single solution with > bound variables, and then binds these within other operations using > variables, paths, or embedded graphs, triggering an error is something > remains unbound. > > A unicity constraint ("!") at the end of a path seems redundant, but might >> be used within a path. >> > > That is correct. > >> >> The above Bind statements might be equivalent to the following SPARQL >> queries. >> >> SELECT ?x WHERE {:a :b / :c ?x} >> SELECT ?x WHERE {:a ^:b / :c ?x } >> SELECT ?x WHERE {:a :p "v"; :c / ^:d ?x } >> SELECT ?x WHERE {:a rdf:rest _:0 . _:0 rdf:first _:1 . _:1 :b ?x} >> SELECT ?x WHERE {:a :c/:d "bar"; ^:e ?x} >> SELECT ?x WHERE {?a ^:e ?x} GROUP BY ?a HAVING(COUNT(?a) = 1) >> >> where each query must have exactly one single result. >> > > Correct, except for the last one, which is not valid SPARQL (according to > the SPARQL validator <http://sparql.org/query-validator.html>). > (?x can not be selected directly, as it is not part of the GROUP BY) > > > I actually found it simpler to implant my own path operator and do this > natively, rather than trying to construct a SPARQL query, but for a large > graph, this may have some performance implications. > > Let us consider a more regular use of "!" > > Bind ?x :a / :b ! / :c > > I would translate it that way: > > SELECT ?x WHERE { > { SELECT ?v1 { :a :b ?v1 } HAVING (COUNT(?v1) = 1) } > ?v1 :c ?x > } > > where the query must have exactly one single result. > > Note also that the 4th query could be simpler: > > SELECT ?x WHERE { :a rdf:rest / rdf:first / :b ?x } > > >> Compiling such queries is non-trivial; any thought about an informative >> section on turning Bind statements into SPARQL queries? For this to work >> with indexes would require a hypothetical extension to SPARQL introducing >> some INDEX-like extension to property-paths. >> > > We have not considered that, but it could indeed be valuable for people > implementing LD-Patch on top of a SPARQL engine. I don't think that an > extension to SPARQL is required, considering that numeric indexes can be > considered as syntactic sugar for property paths of the form > > rdf:rest / rdf:rest / rdf:rest ... / rdf:first > > Granted, unicity constraints are trickier to handle in the general case > (especially when they appear berween square brackets), but I think a > systematic translation process can be devised... > > > Yes, but UpdateList would create some painful SPARQL; better to get > first-class list support in some future SPARQL update. RDF.rb has good > support for lists, basically implementing the Ruby Array paradigm and > methods. > > # Add >> Can a graph contain unbound variables? >> > > No, same answer as with Bind above. > > >> Are they treated just like BNodes? >> Do such variables create bindings for subsequent usage? >> >> # Delete >> Same for add, can a delete graph contain unbound variables? Is this an >> error? >> > > Same answer :) > >> >> # Cut >> Can the argument of Cut be an IRI? Doc indicates it's a BNode, or >> variable binding to a BNode. >> Is it an error to attempt to cut an unbound variable? >> > > Yes, for the same reason as above: *any* use of an unbound variable is an > error. > > best > > > Thanks for the feedback, m sure I'll have more questions as I go through > test cases, for example the notion of BNodes exactly matching vs being > treated as existential quantifiers, which may make using standard BGP more > difficult. > > Gregg > > >> Gregg Kellogg >> gregg@greggkellogg.net >> >> [1] >> https://github.com/gkellogg/ld-patch/tree/feature/initial-implementation >> >> >> >
Received on Monday, 24 August 2015 15:09:41 UTC