Exemplo n.º 1
0
 /**
  * Constructor.
  *
  * @param  string     $query SPARQL query string to initialize this instance.
  * @throws \Exception If no where part was found in query.
  * @throws \Exception If given query is not suitable for UpdateQuery.
  * @throws \Exception If no triple part after INSERT DATA found.
  * @throws \Exception If no triple part after DELETE DATA found.
  * @throws \Exception If no valid WITH <> DELETE {...} WHERE { ...} query given.
  * @throws \Exception If no valid WITH <> DELETE {...} INSERT { ... } WHERE { ...} query given.
  * @throws \Exception If there is either no triple part after INSERT INTO GRAPH or no graph set.
  */
 public function __construct($query = '')
 {
     parent::__construct($query);
     if (null == $this->query) {
         return;
     }
     $subType = $this->getSubType();
     if (null !== $subType) {
         /**
          * Save parts for INSERT DATA
          */
         if ('insertData' === $subType) {
             preg_match('/INSERT\\s+DATA\\s+\\{(.*)\\}/si', $query, $matches);
             if (false === isset($matches[1])) {
                 throw new \Exception('No triple part after INSERT DATA found.');
             }
             /**
              * Save parts for INSERT INTO GRAPH <> {} or INSERT INTO <> {}
              */
         } elseif ('insertInto' === $subType) {
             preg_match('/INSERT\\s+INTO\\s+[GRAPH]{0,}\\s*\\<(.*)\\>\\s*\\{(.*)\\}/si', $query, $matches);
             if (false === isset($matches[1]) || false === isset($matches[2])) {
                 throw new \Exception('There is either no triple part after INSERT INTO GRAPH or no graph set.');
             }
             /**
              * Save parts for DELETE DATA {}
              */
         } elseif ('deleteData' === $subType) {
             preg_match('/DELETE\\s+DATA\\s*\\{(.*)\\}/si', $query, $matches);
             if (false === isset($matches[1])) {
                 throw new \Exception('No triple part after DELETE DATA found.');
             }
             /**
              * Save parts for WITH <> DELETE {} WHERE {}
              */
         } elseif ('withDeleteWhere' === $subType) {
             preg_match('/WITH\\s*\\<(.*)\\>\\s*DELETE\\s*\\{(.*)\\}\\s*WHERE\\s*\\{(.*)\\}/si', $query, $matches);
             if (false === isset($matches[1])) {
                 throw new \Exception('No valid WITH <> DELETE {...} WHERE { ...} query given.');
             }
             /**
              * Save parts for WITH <> DELETE {} INSERT {} WHERE {}
              */
         } elseif ('withDeleteWhere' === $subType) {
             preg_match('/WITH\\s*\\<(.*)\\>\\s*DELETE\\s*\\{(.*)\\}\\s*INSERT\\s*\\{(.*)\\}\\s*WHERE\\s*\\{(.*)\\}/si', $query, $matches);
             if (false === isset($matches[1])) {
                 throw new \Exception('No valid WITH <> DELETE {...} INSERT { ... } WHERE { ...} query given.');
             }
         }
     } else {
         throw new \Exception('Given query is not suitable for UpdateQuery: ' . $query);
     }
 }
Exemplo n.º 2
0
 /**
  * Constructor.
  *
  * @param string optional $query SPARQL query string to initialize this instance.
  */
 public function __construct($query = '')
 {
     parent::__construct($query);
     if (null !== $this->query) {
         /*
          * Set where part
          */
         $result = preg_match('/\\{(.*)\\}/s', $query, $match);
         if (false !== $result && true === isset($match[1])) {
             $this->queryParts['where'] = trim($match[1]);
         }
     }
 }
Exemplo n.º 3
0
 /**
  * This method sends a SPARQL query to the store.
  *
  * @param  string     $query            The SPARQL query to send to the store.
  * @param  array      $options optional It contains key-value pairs and should provide additional
  *                                      introductions for the store and/or its adapter(s).
  * @return Result     Returns result of the query. Its type depends on the type of the query.
  * @throws \Exception If query is no string.
  * @throws \Exception If query is malformed.
  * @throws \Exception If query is a DELETE query and contains quads, where the graph of one quad is of type var
  * @throws \Exception If a non-graph query contains no triples and quads.
  * @todo handle multiple graphs in FROM clause
  */
 public function query($query, array $options = array())
 {
     $queryObject = $this->queryFactory->createInstanceByQueryString($query);
     $queryParts = $queryObject->getQueryParts();
     // if a non-graph query was given, we assume triples or quads. If neither quads nor triples were found,
     // throw an exception.
     if (false === $queryObject->isGraphQuery() && false === isset($queryParts['triple_pattern']) && false === isset($queryParts['quad_pattern'])) {
         throw new \Exception('Non-graph queries must have triples or quads.');
     }
     // execute query on the store
     $result = $this->store->query($query);
     /*
     * special case: if you execute a SELECT COUNT(*) query, ARC2 will return the number of triples
                   instead of a result set
     */
     $countCheck = preg_match('/selectcount\\([a-z*]\\)(from|where)/si', preg_replace('/\\s+/', '', $query));
     if (1 == $countCheck) {
         $variable = 'callret-0';
         // build a set result, because the user expects it as result type because a SELECT query
         // was sent.
         $setResult = $this->resultFactory->createSetResult(array(array($variable => $this->nodeFactory->createLiteral($result, 'http://www.w3.org/2001/XMLSchema#int'))));
         $setResult->setVariables(array($variable));
         return $setResult;
         /*
          * ARC2 does not support quads, especially not in DELETE queries. The following code construct
          * tries to close that gap by transforming the query in a one which ARC2 can understand.
          *
          * This part transform queries of the kind:
          *
          *      DELETE WHERE {
          *          Graph <http://localhost/Saft/TestGraph/> {
          *              ?s ?p ?o .
          *          }
          *      }
          *
          * to SPARQL+ ones:
          *
          *      DELETE FROM <http://localhost/Saft/TestGraph/> {
          *          ?s ?p ?o .
          *      }
          *      WHERE {
          *          ?s ?p ?o .
          *      }
          *
          *
          * IMPORTANT: Please adapt
          *            https://github.com/SaftIng/safting.github.io/blob/master/doc/phpframework/addition/ARC2.md
          *            if you change the support for SPARQL 1.0/1.1 here!
          */
     } elseif ($queryObject->isUpdateQuery() && isset($queryParts['quad_pattern']) && 'deleteWhere' === $queryParts['sub_type']) {
         foreach ($queryParts['quad_pattern'] as $quad) {
             if ('uri' != $quad['g_type']) {
                 throw new \Exception('The graph of a quad must be an URI here.');
             }
             // subject
             $s = NodeUtils::createNodeInstance($this->nodeFactory, $quad['s'], $quad['s_type']);
             $s = SparqlUtils::getNodeInSparqlFormat($s);
             // predicate
             $p = NodeUtils::createNodeInstance($this->nodeFactory, $quad['p'], $quad['p_type']);
             $p = SparqlUtils::getNodeInSparqlFormat($p);
             // object
             $o = NodeUtils::createNodeInstance($this->nodeFactory, $quad['o'], $quad['o_type'], $quad['o_datatype'], $quad['o_lang']);
             $o = SparqlUtils::getNodeInSparqlFormat($o);
             return $this->query('DELETE FROM <' . $quad['g'] . '> {' . $s . ' ' . $p . ' ' . $o . ' }
                 WHERE {' . $s . ' ' . $p . ' ' . $o . ' }');
         }
         /*
          * SELECT query
          */
     } elseif ('selectQuery' === AbstractQuery::getQueryType($query)) {
         /*
          * For a SELECT query the result looks like:
          *
          * array(
          *      'query_time' => 0.2
          *      'query_type' => 'select',
          *      'result' => array(
          *          'variables' => array('s', 'o')
          *          'rows' =>
          *              array(
          *                  's' => "http://s/"
          *                  's type' => 'uri',
          *                  'o' => '42',
          *                  'o type' => "literal"
          *                  'o datatype' => "http://www.w3.org/2001/XMLSchema#string"
          *              )
          */
         $entries = array();
         // go through all rows
         foreach ($result['result']['rows'] as $row) {
             $newEntry = array();
             foreach ($result['result']['variables'] as $variable) {
                 // checks for variable type
                 // example: $row['s type']
                 switch ($row[$variable . ' type']) {
                     // ARC2 does not differenciate between typed literal and literal, like Virtuoso does
                     // for instance. You have to check for lang and datatype key by yourself.
                     case 'literal':
                         // if language is set
                         if (isset($row[$variable . ' lang'])) {
                             $newEntry[$variable] = $this->nodeFactory->createLiteral($row[$variable], 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', $row[$variable . ' lang']);
                             // if datatype is set
                         } elseif (isset($row[$variable . ' datatype'])) {
                             $newEntry[$variable] = $this->nodeFactory->createLiteral($row[$variable], $row[$variable . ' datatype']);
                             // if neither one is set, we assume its a string and use xsd:string as datatype
                         } else {
                             $newEntry[$variable] = $this->nodeFactory->createLiteral($row[$variable], 'http://www.w3.org/2001/XMLSchema#string');
                         }
                         break;
                     case 'uri':
                         $newEntry[$variable] = $this->nodeFactory->createNamedNode($row[$variable]);
                         break;
                 }
             }
             $entries[] = $newEntry;
         }
         // Create and fill SetResult instance
         $setResult = $this->resultFactory->createSetResult($entries);
         $setResult->setVariables($result['result']['variables']);
         return $setResult;
     } else {
         if ('askQuery' === AbstractQuery::getQueryType($query)) {
             return $this->resultFactory->createValueResult($result['result']);
         } else {
             return $this->resultFactory->createEmptyResult();
         }
     }
 }
Exemplo n.º 4
0
 /**
  * This method sends a SPARQL query to the store.
  *
  * @param  string     $query            The SPARQL query to send to the store.
  * @param  array      $options optional It contains key-value pairs and should provide additional
  *                                      introductions for the store and/or its adapter(s).
  * @return Result     Returns result of the query. Its type depends on the type of the query.
  * @throws \Exception If query is no string.
  * @throws \Exception If query is malformed.
  * @throws \Exception If PDO query is false.
  * @todo handle multiple graphs in FROM clause
  */
 public function query($query, array $options = array())
 {
     $queryObject = $this->queryFactory->createInstanceByQueryString($query);
     $queryParts = $queryObject->getQueryParts();
     // if a non-graph query was given, we assume triples or quads. If neither quads nor triples were found,
     // throw an exception.
     if (false === $queryObject->isGraphQuery() && false === isset($queryParts['triple_pattern']) && false === isset($queryParts['quad_pattern'])) {
         throw new \Exception('Non-graph queries must have triples or quads.');
     }
     /**
      * SPARQL query (usually to fetch data)
      */
     if ('selectQuery' === AbstractQuery::getQueryType($query)) {
         // force extended result to have detailed information about given result entries, such as datatype and
         // language information.
         $sparqlQuery = 'define output:format "JSON"' . PHP_EOL . $query;
         // escape characters that delimit the query within the query using addcslashes
         $graphUri = 'NULL';
         $graphSpec = '';
         // escape characters that delimit the query within the query
         $sparqlQuery = $graphSpec . 'CALL DB.DBA.SPARQL_EVAL(\'' . addcslashes($sparqlQuery, '\'\\') . '\', ' . '\'' . $graphUri . '\', 0)';
         // execute query
         try {
             $pdoQuery = $this->connection->prepare($sparqlQuery, array(\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY));
             $pdoQuery->execute();
         } catch (\PDOException $e) {
             throw new \Exception($e->getMessage());
         }
         $entries = array();
         // transform result to array in case we fired a non-UPDATE query
         if (false !== $pdoQuery) {
             $resultArray = json_decode(current(current($pdoQuery->fetchAll(\PDO::FETCH_ASSOC))), true);
             $variables = $resultArray['head']['vars'];
             // in case the result was empty, Virtuoso does not return a list of variables, which are
             // usually located in the SELECT part. so we try to extract the variables by ourselves.
             if (0 == count($variables)) {
                 $variables = $queryParts['variables'];
             }
             /**
              * go through all bindings and create according objects for SetResult instance.
              *
              * $bindingParts will look like:
              *
              * array(
              *      's' => array(
              *          'type' => 'uri',
              *          'value' => '...'
              *      ), ...
              * )
              */
             foreach ($resultArray['results']['bindings'] as $bindingParts) {
                 $newEntry = array();
                 /**
                  * A part looks like:
                  * array(
                  *      'type' => 'uri',
                  *      'value' => '...'
                  * )
                  */
                 foreach ($bindingParts as $variable => $part) {
                     switch ($part['type']) {
                         /**
                          * Literal (language'd)
                          */
                         case 'literal':
                             $newEntry[$variable] = $this->nodeFactory->createLiteral($part['value'], 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', $part['xml:lang']);
                             break;
                             /**
                              * Typed-Literal
                              */
                         /**
                          * Typed-Literal
                          */
                         case 'typed-literal':
                             $newEntry[$variable] = $this->nodeFactory->createLiteral($part['value'], $part['datatype']);
                             break;
                             /**
                              * NamedNode
                              */
                         /**
                          * NamedNode
                          */
                         case 'uri':
                             $newEntry[$variable] = $this->nodeFactory->createNamedNode($part['value']);
                             break;
                         default:
                             throw new \Exception('Unknown type given.');
                             break;
                     }
                 }
                 $entries[] = $newEntry;
             }
             $setResult = $this->resultFactory->createSetResult(new \ArrayIterator($entries));
             $setResult->setVariables($variables);
             return $setResult;
         } else {
             throw new \Exception('PDO query is false.');
         }
         /**
          * SPARPQL Update query
          */
     } else {
         $sparqlQuery = 'SPARQL ' . $query;
         // execute query
         try {
             $pdoQuery = $this->connection->prepare($sparqlQuery, array(\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY));
             $pdoQuery->execute();
         } catch (\PDOException $e) {
             throw new \Exception($e->getMessage());
         }
         // ask result
         if ('askQuery' === AbstractQuery::getQueryType($query)) {
             $pdoResult = $pdoQuery->fetchAll(\PDO::FETCH_ASSOC);
             return $this->resultFactory->createValueResult(true !== empty($pdoResult));
         } else {
             return $this->resultFactory->createEmptyResult();
         }
     }
 }
Exemplo n.º 5
0
 public function testGetQueryTypeUpdate()
 {
     /**
      * INSERT DATA
      */
     $query = 'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
               INSERT DATA {Graph <>}';
     $this->assertEquals('updateQuery', AbstractQuery::getQueryType($query));
     /**
      * INSERT INTO GRAPH
      */
     $query = 'INSERT INTO GRAPH {}';
     $this->assertEquals('updateQuery', AbstractQuery::getQueryType($query));
     /**
      * DELETE
      */
     $query = 'DELETE {}';
     $this->assertEquals('updateQuery', AbstractQuery::getQueryType($query));
     /**
      * DELETE DATA
      */
     $query = 'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
               DELETE DATA {}';
     $this->assertEquals('updateQuery', AbstractQuery::getQueryType($query));
 }
 /**
  * This method sends a SPARQL query to the store.
  *
  * @param  string     $query            The SPARQL query to send to the store.
  * @param  array      $options optional It contains key-value pairs and should provide additional
  *                                      introductions for the store and/or its adapter(s).
  * @return Result     Returns result of the query. Its type depends on the type of the query.
  * @throws \Exception If query is no string, is malformed or an execution error occured.
  */
 public function query($query, array $options = array())
 {
     $queryObject = $this->queryFactory->createInstanceByQueryString($query);
     if ('updateQuery' == AbstractQuery::getQueryType($query)) {
         /*
          * INSERT or DELETE query
          */
         $firstPart = substr($queryObject->getSubType(), 0, 6);
         // DELETE DATA query
         if ('delete' == $firstPart) {
             $statements = $this->getStatements($queryObject);
             // if it goes into the loop, there is more than one triple pattern in the DELETE query,
             // which is not allowed.
             $i = 0;
             foreach ($statements as $statement) {
                 if (1 <= $i++) {
                     throw new \Exception('DELETE query can not contain more than one triple pattern: ' . $query);
                 }
                 // if only one Statement is in the list, no exception will be thrown and in
                 // $statement is that Statement later on and can be used.
             }
             return $this->deleteMatchingStatements($statement);
             // INSERT DATA or INSERT INTO query
         } elseif ('insert' == $firstPart) {
             return $this->addStatements($this->getStatements($queryObject));
             // TODO Support
             // WITH ... DELETE ... WHERE queries
             // WITH ... DELETE ... INSERT ... WHERE queries
         } else {
             throw new \Exception('Not yet implemented: WITH-DELETE-WHERE and WITH-DELETE-INSERT-WHERE queries are not ' . 'supported yet.');
         }
     } elseif ('askQuery' == AbstractQuery::getQueryType($query)) {
         /*
          * ASK query
          */
         $statement = $this->getStatement($queryObject);
         return $this->hasMatchingStatement($statement);
     } elseif ('selectQuery' == AbstractQuery::getQueryType($query)) {
         /*
          * SELECT query
          */
         $statement = $this->getStatement($queryObject);
         return $this->getMatchingStatements($statement);
     } else {
         /*
          * Unsupported query
          */
         throw new \Exception('Unsupported query was given: ' . $query);
     }
 }
Exemplo n.º 7
0
 /**
  * This method sends a SPARQL query to the store.
  *
  * @param  string     $query            The SPARQL query to send to the store.
  * @param  array      $options optional It contains key-value pairs and should provide additional
  *                                      introductions for the store and/or its adapter(s).
  * @return Result     Returns result of the query. Its type depends on the type of the query.
  * @throws \Exception     If query is no string.
  * @throws \Exception     If query is malformed.
  * @throws StoreException If server returned an error.
  * @todo add support for DESCRIBE queries
  */
 public function query($query, array $options = array())
 {
     $queryObject = $this->queryFactory->createInstanceByQueryString($query);
     $queryParts = $queryObject->getQueryParts();
     /**
      * SPARQL query (usually to fetch data)
      */
     if ('selectQuery' == AbstractQuery::getQueryType($query)) {
         $resultArray = json_decode($this->client->sendSparqlSelectQuery($query), true);
         $entries = array();
         /**
          * go through all bindings and create according objects for SetResult instance.
          *
          * $bindingParts will look like:
          *
          * array(
          *      's' => array(
          *          'type' => 'uri',
          *          'value' => '...'
          *      ), ...
          * )
          */
         foreach ($resultArray['results']['bindings'] as $bindingParts) {
             $newEntry = array();
             /**
              * A part looks like:
              * array(
              *      'type' => 'uri',
              *      'value' => '...'
              * )
              */
             foreach ($bindingParts as $variable => $part) {
                 switch ($part['type']) {
                     /**
                      * Literal (language'd)
                      */
                     case 'literal':
                         $lang = null;
                         if (isset($part['xml:lang'])) {
                             $lang = $part['xml:lang'];
                         }
                         $newEntry[$variable] = $this->nodeFactory->createLiteral($part['value'], 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', $lang);
                         break;
                         /**
                          * Typed-Literal
                          */
                     /**
                      * Typed-Literal
                      */
                     case 'typed-literal':
                         $newEntry[$variable] = $this->nodeFactory->createLiteral($part['value'], $part['datatype']);
                         break;
                         /**
                          * NamedNode
                          */
                     /**
                      * NamedNode
                      */
                     case 'uri':
                         $newEntry[$variable] = $this->nodeFactory->createNamedNode($part['value']);
                         break;
                         /**
                          * BlankNode
                          */
                     /**
                      * BlankNode
                      */
                     case 'bnode':
                         $newEntry[$variable] = $this->nodeFactory->createBlankNode($part['value']);
                         break;
                     default:
                         throw new \Exception('Unknown type given.');
                         break;
                 }
             }
             $entries[] = $newEntry;
         }
         $return = $this->resultFactory->createSetResult($entries);
         $return->setVariables($resultArray['head']['vars']);
         /**
          * SPARPQL Update query
          */
     } else {
         $result = $this->client->sendSparqlUpdateQuery($query);
         $decodedResult = json_decode($result, true);
         if ('askQuery' === AbstractQuery::getQueryType($query)) {
             $askResult = json_decode($result, true);
             if (true === isset($askResult['boolean'])) {
                 $return = $this->resultFactory->createValueResult($askResult['boolean']);
                 // assumption here is, if a string was returned, something went wrong.
             } elseif (0 < strlen($result)) {
                 throw new \Exception($result);
             } else {
                 $return = $this->resultFactory->createEmptyResult();
             }
             // usually a SPARQL result does not return a string. if it does anyway, assume there is an error.
         } elseif (null === $decodedResult && 0 < strlen($result)) {
             throw new \Exception($result);
         } else {
             $return = $this->resultFactory->createEmptyResult();
         }
     }
     return $return;
 }