8.5 SPARQL Query Execution Model

SPARQL queries executed through the Oracle RDF Graph Adapter for Eclipse RDF4J API run as SQL queries against Oracle’s relational schema for storing RDF data.

Utilizing Oracle’s SQL engine allows SPARQL query execution to take advantage of many performance features such as parallel query execution, in-memory columnar representation, and Exadata smart scan.

There are two ways to execute a SPARQL query:

  • You can obtain an implementation of Query or one of its subinterfaces from the prepareQuery functions of a RepositoryConnection that has an underlying OracleSailConnection.

  • You can obtain an Oracle-specific implementation of TupleExpr from OracleSPARQLParser and call the evaluate method of OracleSailConnection.

The following code snippet illustrates the first approach.

//run a query against the repository
String queryString = 
  "PREFIX ex: <http://example.org/ontology/>\n" + 
  "SELECT * WHERE {?x ex:name ?y} LIMIT 1 ";
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);

try (TupleQueryResult result = tupleQuery.evaluate()) {
  while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    psOut.println("value of x: " + bindingSet.getValue("x"));
    psOut.println("value of y: " + bindingSet.getValue("y"));
  }
}

When an OracleSailConnection evaluates a query, it calls the SEM_APIS.SPARQL_TO_SQL stored procedure on the database server with the SPARQL query string and obtains an equivalent SQL query, which is then executed on the database server. The results of the SQL query are processed and returned through one of the standard RDF4J query result interfaces.

8.5.1 Using BIND Values

Oracle RDF Graph Adapter for Eclipse RDF4J supports bind values through the standard RDF4J bind value APIs, such as the setBinding procedures defined on the Query interface. Oracle implements bind values by adding SPARQL BIND clauses to the original SPARQL query string.

For example, consider the following SPARQL query:
SELECT * WHERE { ?s <urn:fname> ?fname }
In the above query, you can set the value <urn:john> for the query variable ?s. The tansformed query in that case would be:
SELECT * WHERE { BIND (<urn:john> AS ?s) ?s <urn:fname> ?fname }

Note:

This approach is subject to the standard variable scoping rules of SPARQL. So query variables that are not visible in the outermost graph pattern, such as variables that are not projected out of a subquery, cannot be replaced with bind values.

8.5.2 Using JDBC BIND Values

Oracle RDF Graph Adapter for Eclipse RDF4J allows the use of JDBC bind values in the underlying SQL statement that is executed for a SPARQL query. The JDBC bind value implementation is much more performant than the standard RDF4J bind value support described in the previous section.

JDBC bind value support uses the standard RDF4J setBinding API, but bind variables must be declared in a specific way, and a special query option must be passed in with the ORACLE_SEM_SM_NS namespace prefix. To enable JDBC bind variables for a query, you must include USE_BIND_VAR=JDBC in the ORACLE_SEM_SM_NS namespace prefix (for example, PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>). When a SPARQL query includes this query option, all query variables that appear in a simple SPARQL BIND clause will be treated as JDBC bind values in the corresponding SQL query. A simple SPARQL BIND clause is one with the form BIND (<constant> as ?var), for example BIND("dummy" AS ?bindVar1).

The following code snippet illustrates how to use JDBC bind values.

Example 8-4 Using JDBC Bind Values

// query that uses USE_BIND_VAR=JDBC option and declares ?name as a JDBC bind variable
String queryStr = 
  "PREFIX ex: <http://example.org/>\n"+
  "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n"+
  "PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>\n"+
  "SELECT ?friend\n" +
  "WHERE {\n" +
  "  BIND(\"\" AS ?name)\n" +
  "  ?x foaf:name ?name\n" +
  "  ?x foaf:knows ?y\n" +
  "  ?y foaf:name ?friend\n" +
  "}";

// prepare the TupleQuery with JDBC bind var option
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryStr);

// find friends for Jack
tupleQuery.setBinding("name", vf.createLiteral("Jack");

try (TupleQueryResult result = tupleQuery.evaluate()) {
  while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    System.out.println(bindingSet.getValue("friend").stringValue());
  }
}

// find friends for Jill
tupleQuery.setBinding("name", vf.createLiteral("Jill");

try (TupleQueryResult result = tupleQuery.evaluate()) {
  while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    System.out.println(bindingSet.getValue("friend").stringValue());
  }
}

Note:

The JDBC bind value capability of Oracle RDF Graph Adapter for Eclipse RDF4J utilizes the bind variables feature of SEM_APIS.SPARQL_TO_SQL described in Using Bind Variables with SEM_APIS.SPARQL_TO_SQL.

8.5.2.1 Limitations for JDBC Bind Value Support

Only SPARQL SELECT and ASK queries support JDBC bind values.

The following are the limitations for JDBC bind value support:

  • JDBC bind values are not supported in:
    • SPARQL CONSTRUCT queries
    • DESCRIBE queries
    • SPARQL Update statements
  • Long RDF literal values of more than 4000 characters in length cannot be used as JDBC bind values.
  • Blank nodes cannot be used as JDBC bind values.

8.5.3 Additions to the SPARQL Query Syntax to Support Other Features

The Oracle RDF Graph Adapter for Eclipse RDF4J allows you to pass in options for query generation and execution. It implements these capabilities by overloading the SPARQL namespace prefix syntax by using Oracle-specific namespaces that contain query options. The namespaces are in the form PREFIX ORACLE_SEM_xx_NS, where xx indicates the type of feature (such as SM - SEM_MATCH).

8.5.3.1 Query Execution Options

You can pass query execution options to the database server by including a SPARQL PREFIX of the following form:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#option>
The option in the above SPARQL PREFIX reflects a query option (or multiple options separated by commas) to be used during query execution.

The following options are supported:

  • DOP=n: specifies the degree of parallelism (n) to use during query execution.
  • ODS=n: specifies the level of optimizer dynamic sampling to use when generating an execution plan.

The following example query uses the ORACLE_SEM_FS_NS prefix to specify that a degree of parallelism of 4 should be used for query execution.

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#dop=4>
PREFIX ex: <http://www.example.com/>
SELECT *
WHERE {?s ex:fname ?fname ;                     
          ex:lname ?lname ;                     
          ex:dob ?dob}

8.5.3.2 SPARQL_TO_SQL (SEM_MATCH) Options

You can pass SPARQL_TO_SQL options to the database server to influence the SQL generated for a SPARQL query by including a SPARQL PREFIX of the following form:

PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#option>

The option in the above PREFIX reflects a SPARQL_TO_SQL option (or multiple options separated by commas) to be used during query execution.

The available options are detailed in Using the SEM_MATCH Table Function to Query RDF Data. Any valid keywords or keyword – value pairs listed as valid for the options argument of SEM_MATCH or SEM_APIS.SPARQL_TO_SQL can be used with this prefix.

The following example query uses the ORACLE_SEM_SM_NS prefix to specify that HASH join should be used to join all triple patterns in the query.

PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_link_hash>
PREFIX ex: <http://www.example.org/>
SELECT *
WHERE {?s ex:fname ?fname ;
          ex:lname ?lname ;
          ex:dob ?dob}

8.5.4 Special Considerations for SPARQL Query Support

This section explains the special considerations for SPARQL Query Support.

Unbounded Property Path Queries

By default Oracle RDF Graph Adapter for Eclipse RDF4J limits the evaluation of the unbounded SPARQL property path operators + and * to at most 10 repetitions. This can be controlled with the all_max_pp_depth(n) SPARQL_TO_SQL option, where n is the maximum allowed number of repetitions when matching + or *. Specifying a value of zero results in unlimited maximum repetitions.

The following example uses all_max_pp_depth(0) for a fully unbounded search.
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(0)>
PREFIX ex: <http://www.example.org/>
SELECT (COUNT(*) AS ?cnt)
WHERE {ex:a ex:p1* ?y}

SPARQL Dataset Specification

The adapter for Eclipse RDF4J does not allow dataset specification outside of the SPARQL query string. Dataset specification through the setDataset() method of Operation and its subinterfaces is not supported, and passing a Dataset object into the evaluate method of SailConnection is also not supported. Instead, use the FROM and FROM NAMED SPARQL clauses to specify the query dataset in the SPARQL query string itself.

Query Timeout

Query timeout through the setMaxExecutionTime method on Operation and its subinterfaces is not supported.

Long RDF Literals

Large RDF literal values greater than 4000 bytes in length are not supported by some SPARQL query functions. See Special Considerations When Using SEM_MATCH for more information.