semsol / arc2

ARC RDF Classes for PHP
Other
332 stars 89 forks source link

Can query function handle queries like "_:foo ?p ?o" ? #86

Closed k00ni closed 7 years ago

k00ni commented 7 years ago

I really hope i am wrong, but it seems that ARC2 can't handle blank nodes using query function.

$store->query('
INSERT INTO <http://some/graph/> {
    <http://back/data/Wacken2017> <http://rdf#type> <http://back/model/Event> ;
        <http://rdfs#label> "Event1" .
    <http://back/data/user1> <http://rdf#type> <http://back/model/User> ;
        <http://back/model/has-rights> [
            <http://back/model/type> <http://back/model/Event> ;
            <http://back/model/event> <http://back/data/Event1>
        ] .
}');

// ask for created blank node to use its ID later on
$res = $this->store->getStore()->query('SELECT * FROM <http://some/graph/> WHERE {
     <http://back/data/user1> <http://back/model/has-rights> ?blank
}');
var_dump($res['result']['rows'][0]['blank']);

// get all properties and values of the created blank node
$res = $this->store->getStore()->query('SELECT * FROM <http://some/graph/> WHERE {
     '. $res['result']['rows'][0]['blank'] .' ?p ?o.
}');
var_dump($res);

It outputs the following:

string(23) "_:b1314764907_arc09d9b1"
array(3) {
  ["query_type"]=>
  string(6) "select"
  ["result"]=>
  array(2) {
    ["variables"]=>
    array(2) {
      [0]=>
      string(1) "p"
      [1]=>
      string(1) "o"
    }
    ["rows"]=>
    array(6) {
      [0]=>
      array(4) {
        ["p"]=>
        string(15) "http://rdf#type"
        ["p type"]=>
        string(3) "uri"
        ["o"]=>
        string(23) "http://back/model/Event"
        ["o type"]=>
        string(3) "uri"
      }
      [1]=>
      array(4) {
        ["p"]=>
        string(22) "http://back/model/type"
        ["p type"]=>
        string(3) "uri"
        ["o"]=>
        string(23) "http://back/model/Event"
        ["o type"]=>
        string(3) "uri"
      }
      [2]=>
      array(4) {
        ["p"]=>
        string(17) "http://rdfs#label"
        ["p type"]=>
        string(3) "uri"
        ["o"]=>
        string(6) "Wacken"
        ["o type"]=>
        string(7) "literal"
      }
      [3]=>
      array(4) {
        ["p"]=>
        string(15) "http://rdf#type"
        ["p type"]=>
        string(3) "uri"
        ["o"]=>
        string(22) "http://back/model/User"
        ["o type"]=>
        string(3) "uri"
      }
      [4]=>
      array(4) {
        ["p"]=>
        string(28) "http://back/model/has-rights"
        ["p type"]=>
        string(3) "uri"
        ["o"]=>
        string(23) "_:b1314764907_arc09d9b1"
        ["o type"]=>
        string(5) "bnode"
      }
      [5]=>
      array(4) {
        ["p"]=>
        string(23) "http://back/model/event"
        ["p type"]=>
        string(3) "uri"
        ["o"]=>
        string(27) "http://back/data/Event1"
        ["o type"]=>
        string(3) "uri"
      }
    }
  }
  ["query_time"]=>
  float(0.001662015914917)
}

I expect the result only has two entries:

_:b1314764907_arc09d9b1 <http://back/model/type> <http://back/model/Event> ;
_:b1314764907_arc09d9b1 <http://back/model/event> <http://back/data/Event1>
bnowack commented 7 years ago

That was missing in the spec back then and is still correct behavior, I think. See [1]:

Blank nodes in graph patterns act as variables, not as references to specific blank nodes in the data being queried

If you want to use blank nodes as explicit identifiers in a query, ARC2 offers an extension to the spec that allows you to mask bnodes as URIs:

 $res = $this->store->getStore()->query('SELECT * FROM <http://some/graph/> WHERE {
     <'. $res['result']['rows'][0]['blank'] .'> ?p ?o.
}');

The query above should do the trick (note the < and > around the bnode). That is off-standard, however.

[1] https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#QSynBlankNodes