- From: Eric Prud'hommeaux <eric@w3.org>
- Date: Mon, 30 Apr 2012 08:12:24 -0400
- To: Andy Seaborne <andy.seaborne@epimorphics.com>
- Cc: SPARQL Working Group <public-rdf-dawg@w3.org>
* Andy Seaborne <andy.seaborne@epimorphics.com> [2012-04-28 11:46+0100] > This is the "BINDINGS anywhere in a graph pattern" feature. > > I called it "inline data" to step back from the syntax details. The > word "BINDINGS" gets a bit mixed up with "BIND" when they can both > be in group graph patterns. > > Andy > > == Summary > > SELECT * > { > DATA ?x { :x1 :x2 } > ?x rdfs:label ?label . > } > > > SELECT * > { > DATA (?x ?mylabel) { > (:x1 "X1") > (:x2 "X2") > } > OPTIONAL { ?x rdfs:label ?label } > } > > "DATA" being a word that isn't BINDINGS. > > == Syntax > > The comments and modification of use cases prompted me to check the > syntax. BINDINGS with one variable is a bit ugly as each term needs > a () round it. This really isn't necessary. I'm guessing that > one-variable inline data will be a common use cases if we think of > it as inline data. The comments suggest this. (It comes up in my > work on the linked data API where one query gets some candidates and > a second query gets more information on each candidate.) > > A possibility is: > > # Short form - one variable, no () at all. > DATA ?var { <iri1> <iri2> 3 4 } > > # Full from. Consistently (...) around a row header or row data. > DATA (?var1 ?var2) { > (<iri1> "a") > (<iri2> "b") > } This seems like a balance between consistency and convenience. It's grammatically distinguishable in LL/LALR(1) with this patch: -[29] DataBlock ::= Var* '{' ( '(' DataBlockValue* ')' | NIL )* '}' +[29] DataBlock ::= '(' Var* ')' '{' ( '(' DataBlockValue* ')' | NIL )* '}' | Var '{' DataBlockValue* '}' IMO, it actually adds some consistency by sticking parens around the var list. > Insert your favorite keyword choice here: > > TABLE > it's a bit concrete and tables don't get a mention anywhere else > > DATA > my pref, even though its used in INSERT DATA in SPARQL Update > > BINDINGS > OK but confusion with BIND? Unnecessarily long? One problem with "DATA" is that SPARQL's data is RDF triples, not variable bindings. Practically, we may some day want to add premises like: DATA { :Fido a :Dog } SELECT ?mammal { ?mammal a :Mammal } I don't have a strong opinion yet, want to reflect a bit after gathering ideas. > The choices of delimiters is fairly free - the only requirement is > an explicit end for variables (the "{"), end of data rows (the "}"). > Having row grouping is very useful for the multi-variable case. > > c.f.1. > > BINDINGS has an un-delimited list of variables always and the data > rows must have (...) > > BINDINGS ?var { (<iri1>) (<iri2>) (3) (4) } > > c.f.2. > > FILTER ( ?x IN (<iri1>, <iri2>, 3, 4) ) > > > ==== Spec changes > > == 10.2 BINDINGS > > Rework description and examples. > > == Grammar > > Grammar: add to list of units in a GroupGraphPattern > > [] GraphPatternNotTriples > ::= GroupOrUnionGraphPattern | OptionalGraphPattern | > MinusGraphPattern | GraphGraphPattern | ServiceGraphPattern | > Filter | Bind | InlineDataClause SWObects already has this. I find it quite handy for debugging and test cases. > == Algebra > > I suggested earlier that it should float to the end of the group, > just before the FILTERs but that does not work out. It needs to be > joined into the group in the location it occurs in (just like a > subquery). It is like BIND in that it ends the BGP. > > Worked example below. > > No new operators - everything is there already. > > 18.2.4.3 BINDINGS > Move the text from here which turns the BINDINGs syntax into a table > to just before the pattern translation step (18.2.2.6) > > 18.2.2.6 Translate Graph Patterns > > The algebra transformation step does not have to be changed at all > because it falls under the catch all > > If E is any other form > Let A := Translate(E) > G := Join(G, A) > End > > == Evaluation > > No change. We were already turning BINDINGS into join(..., data > table) and this is just the same. BINDINGS didn't have anything > special by the time evaluation is defined. > > == What to do with BINDINGS? > > We can leave BINDINGS as it is ("legacy"), rename it to be the same > as the inline data (if name changes) or remove it. > > BINDINGS happens after Grouping/Aggregates, HAVING and before select > expressions. It seems to me to be unlikely to see it used with > group/aggregate - if removed, you'd need a subquery for the group, > the a join with inline data. That is, this more specialized case > needs more syntax. > > Caveat the different syntax from DATA. > > My preference is to bite the bullet now and remove BINDINGS. There > may be complaints, and they are right to complain as we have done 2 > LC's, but if we are making changes, I think doing it properly for > the long term is better. > > I am also happy for it to be left as-is as legacy. > > ==== Worked example > > ---- Data > @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . > @prefix : <http://example/> . > > :x1 rdfs:label "foo" . > ## No :x2 > :x3 rdfs:label "foo" . > ---- Data > > ---- Query 1 > # Intuitively, start with some possibilities, > # and add rdfs:labels if available. > PREFIX : <http://example/> > PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> > > SELECT * > { > DATA ?x { :x1 :x2 } > OPTIONAL { ?x rdfs:label ?label } > } > > ---- Query 1 > ====> > --------------- > | x | label | > =============== > | :x1 | "foo" | > | :x2 | | > --------------- > > Join data table with the empty BGP (this is a no-op removed by > "simplification"). > > Do an optional (leftjoin) on > (?x=:x1 ?x=:x2) > leftjoin ((?x=:x1 ?label="foo), (?x=:x3 ?label="foo")) > > so :x2 gets no ?label but is in the answers > > ---- Query 2 > # Intuitively, do some process, restrict output > # by joining with some fixed data. > > PREFIX : <http://example/> > PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> > > SELECT * > { > OPTIONAL { ?x rdfs:label ?label } > DATA ?x { :x1 :x2 } > } > ---- Query 2 > > ====> > --------------- > | x | label | > =============== > | :x1 | "foo" | > --------------- > > The OPTIONAL finds :x1 and :x3; the join does not have :x3 in it so > only :x1 is in the results. > > join(?x=:x1 ?x=:x2) with ((?x=:x1 ?label="foo), (?x=:x3 ?label="foo") > > not leftjoin. > -- -ericP
Received on Monday, 30 April 2012 12:12:55 UTC