# 14. RDF Database and SPARQL

Chapter Contents | Prev | Next
Keyword Search:
www.openlinksw.com
docs.openlinksw.com
Book Home
Contents
Preface
RDF Database and SPARQL
Data Representation
RDF and SPARQL API and SQL
SPARQL Inline in SQL API Functions Useful Internal Functions Default and Named Graphs Calling SQL from SPARQL SPARUL -- an Update Language For RDF Graphs
IRI Dereferencing
RDF Views -- Mapping Relational Data to RDF
SPARQL Implementation
RDF Inference in Virtuoso
Using Full Text Search in SPARQL
Aggregates in SPARQL
Virtuoso SPARQL Query Service

## 14.2. RDF and SPARQL API and SQL

SPARQL can be used inline wherever SQL can be used. The only API functions that one needs to know are the ones for loading RDF data into the store. Dynamic SQL client applications can issue SPARQL queries against Virtuoso through the regular SQL client API, ODBC, JDBC or other, simply by prefixing the SPARQL query with the SPARQL keyword. Parameters work just as with dynamic SQL. Stored procedures can have SPARQL expressions inline and can declare cursors over SPARQL result sets.

Value conversions between SQL and SPARQL are most often automatic and invisible. In some cases one needs to be aware of the different SPARQL value representations (valmodes). SPARQL offers delcrations for determining if graphs to be returned are to be represented as XML or Turtle text serialization or whether these will be hash tables of triples. See dict_new() and related functions for a description of the hash table SQL data type. The use of dict's is convenient for further programmatic processing of graphs.

RDF-related procedures use Virtuoso/PL vectors and dictionaries to represent RDF triples and sets of triples.

Valmode means the "format of values returned by an expression", i.e. 'short', 'long' or 'SQL value'.

Triple vector is a vector (array) of S, P and O, where all values are in 'long' formats, i.e. IRI_ID's for IRI values, vector of 5 items if O is a string, SQL scalar value if O is neither string nor IRI.

Dictionary of triples or Hash table of triples is an dictionary object made by the SQL function dict_new () whose keys are triple vectors and values are not specified; this is a good storage format for an unordered set of distinct triples.

Dictionary of blank node names is a dictionary used for tricky processing of a number of TURTLE or RDF /XML descriptions of subgraphs that come from a common graph. Imagine a situation where different descriptions actually refer to the same blank nodes of the original graph and, moreover, the application that generates these descriptions always generates the same blank node id string for the same node. A reader of descriptions can correctly join described subgraphs into one big subgraph by filling in a dictionary that contains blank node id strings as keys and IRI_ID's assigned to that strings as dependant data. As soon as all readers of an application share the same dictionary of nodes created before, no blank node is created twice;

### 14.2.1. SPARQL Inline in SQL

Virtuoso extends the SQL 92 syntax with SPARQL queries and subqueries. Instead of writing a SQL SELECT query or subquery, one can write the SPARQL keyword and a SPARQL query after the keyword.

    SQL>sparql select distinct ?p where { graph ?g { ?s ?p ?o } };
    p
    varchar
    ----------
    http://example.org/ns#b
    http://example.org/ns#d
    http://xmlns.com/foaf/0.1/name
    http://xmlns.com/foaf/0.1/mbox
    ...

    SQL>select distinct subseq ("p", strchr ("p", '#')) as fragment
      from (sparql select distinct ?p where { graph ?g { ?s ?p ?o } } ) as all_predicates
      where "p" like '%#%';
    fragment
    varchar
    ----------
    #query
    #data
    #name
    #comment
    ...

Note that names of variables returned from SPARQL are always case-sensitive and no case mode rules apply to them. Depending on CaseMode parameter in the virtuoso configudation file, double quotes should be used to refer to them in surrounding SQL code.

It is possible to pass parameters to a SPARQL query via a Virtuoso-specific syntax extension. '??' or '$?' indicates a positional parameter similar to '?' in plain SQL. '??' can be used in graph patterns or anywhere in the place of a SPARQL variable. The value of a parameter should be passed in SQL form, i.e. this should be a number or a untyped string. An IRI ID can be passed in all cases where an absolute IRI can, except the obvious case when the variable is an argument of a function that requires string. If the parameter is used in 'graph', 'subject' or 'object' position of the sparql pattern, the string parameter is converted into IRI automatically. In other cases, IRI string is undistinguishable from string literal, so there is a need in call of iri() buil-tin SPARL function, like iri (??). Using this notation, any dynamic SQL client, whether ODBC, JDBC or other can execute parametrized SPARQL queries, binding parametres just as with dynamic SQL.

    SQL> create function param_passing_demo ()
    {
      declare stat, msg varchar;
      declare mdata, rset any;
      exec ('sparql select ?s where { graph ?g { ?s ?? ?? }}',
        stat, msg,
        vector ( /* Vector of two parameters */
          'http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#int1',
          4 ),
        10, /* Max no of rows */
        mdata, /* Variable to get metadata */
        rset ); /* Variable to get result-set */
      if (length (rset) = 0)
        signal ('23000',
          'No data found, try demo database with installed Virtuoso tutorials');
      return rset[0][0];
    }

    SQL> select param_passing_demo ();
    callret
    VARCHAR
    _______________________________________________________________________________

    http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#four

    1 Rows. -- 00000 msec.

An inline SPARQL query can refer to SQL variables that are in scope in the SQL query or stored procedure containing it. Virtuoso extends the SPARQL syntax with a special notation to this effect. A reference to SQL variable X can be written as '?:X' or '$:X'. A reference to column C of table or sub-select with alias T can be written as '?:T.C' or '$:T.C'. Both notations can be used in any place where a variable name is allowed, except 'AS' clause described below.

A column of a result set of a SPARQL SELECT can be used in SQL code inside a for statement just like any column from a SQL select.

SQL rules about double-quoted names are applicable to variables that are passed to a SPARQL query or selected from one. If a variable name contains unusual characters or should not be normalized according to SQL conventions then the name should use double quotes for escaping. E.g., the notation '?:"OrderLine"' will always refer to variable or column titled '"OrderLine"' whereas '?:OrderLine' can be converted to 'ORDERLINE' or 'orderline'.

It is safer to avoid using variable names that conflict with column names of RDF system tables, esp. 'G', 'P', 'S' and 'O'. These names are not reserved now but they may cause subtle bugs when an incorrect SPARQL subquery is compiled into SQL code that refers to table columns of same names. Some of these names may be rejected as syntax errors by future Virtuoso versions.

    SQL> create procedure sql_vars_demo ()
    {
    #pragma prefix sort0: <http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#>
      declare RES varchar;
      declare obj integer;
      result_names (RES);
      obj := 4;
      for (sparql select ?subj where { graph ?g { ?subj sort0:int1 ?:obj } } ) do
        result ("subj");
    }

    SQL> sql_vars_demo ();
    RES
    VARCHAR
    _______________________________________________________________________________

    http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#four

    1 Rows. -- 00000 msec.

The example also demonstrates the Virtuoso/PL pragma line for procedure-wide declarations of namespace prefixes. This makes the code more readable and eliminates duplicate declarations of namespace prefixes when the procedure contains many SPARQL fragments that refer to a common set of namespaces.

SPARQL ASK query can be used as an argument of the SQL EXISTS predicate.

    create function sparql_ask_demo () returns varchar
    {
      if (exists (sparql ask where { graph ?g { ?s ?p 4}}))
        return 'YES';
      else
        return 'NO';
    }

    SQL> select sparql_ask_demo ();
    _______________________________________________________________________________

    YES

#### 14.2.1.1. Controlling SPARQL Output Data Types

The compilation of a SPARQL query may depend on environment that is usually provided by the SPARQL protocol, including name of default graph URI . Environment settings that come from protocol may override settings in the text of SPARQL query. To let an application configure the environment for a query, SPARQL syntax is extended with the 'define' clause:

    define parameter-qname parameter-value

Examples of supported parameters are output:valmode and output:format

output:valmode sets the SQL representation used for values in the result set. In most cases applications need SQL values to be returned by SPARQL. By default the query returns a result set of values in SQL format and behaves as a typical SQL select. To compose triple vectors in Virtuoso/PL code application may need data in long format. If the query contains a

    define output:valmode 'LONG'

clause then all returned values are in long format. E.g., the following query returns IRI_ID's instead of IRI strings.

    SQL>sparql define output:valmode 'LONG' select distinct ?p where { graph ?g { ?s ?p ?o } };
    p
    ----------
    #i1000001
    #i1000003
    #i1000005
    #i1000006
    ...

output:format instruct SPARQL compiler that the result of the query should be serialized into an RDF document; that document will be returned as a single column of a single row result set. output:format is especially useful if SPARQL CONSTRUCT or SPARQL DESCRIBE query is executed directly via ODBC or JDBC database connection and the client can not receive the resulting dictionary of triples (there's no way to transfer such an object via ODBC). Using this option, the client can receive the document that contains the whole result set of a SELECT or the dictionary of triples of a CONSTRUCT/DESCRIBE, and parse it locally.

Supported values for output:format are RDF/XML and TURTLE (or TTL). If both output:valmode and output:format are specified, output:format has higher priority, raising an error if output:valmode is set to a value other than LONG.

When a SPARQL query is compiled, the compiler checks whether the result set is sent to the remote ODBC/JDBC client or used in some other way. The compiler will automatically set output:format to TURTLE if compiling for execution by an SQL client.

The example below demonstrates how different values of output:format affect the result of SPARQL SELECT. Note 10 rows and 4 columns in the first result, and single LONG VARCHAR in two others. Using the ISQL client, use 'set blobs on;' directive to fetch long texts without 'data truncated' warning.

    SQL> sparql select * where {graph ?g { ?s ?p ?o }} limit 10;
    g                                            s                    p                              o
    VARCHAR                                      VARCHAR              VARCHAR                        VARCHAR
    ______________________________________________________________________

    http://local.virt/DAV/bound/manifest.rdf     nodeID://1000000000  http://example.com/test#query  http://local.virt/DAV/bound/bound1.rq
    . . .
    http://local.virt/DAV/examples/manifest.rdf  nodeID://1000000019  http://example.com/test#query  http://local.virt/DAV/examples/ex11.2.3.1_1.rq

    10 Rows. -- 00000 msec.

    SQL> sparql define output:format "TTL" select * where {graph ?g { ?s ?p ?o }} limit 10;
    callret-0
    LONG VARCHAR
    _______________________________________________________________________________

    @prefix :rdf <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
     @prefix :rs <http://www.w3.org/2005/sparql-results#> .
     @prefix :xsd <http://www.w3.org/2001/XMLSchema#> .
     [ rdf:type rs:results ;
      rs:result [
          rs:binding [ rs:name "g" ; rs:value <http://local.virt/DAV/bound/manifest.rdf> ] ;
          rs:binding [ rs:name "s" ; rs:value _:nodeID1000000000 ] ;
          rs:binding [ rs:name "p" ; rs:value <http://example.com/test#query> ] ;
          rs:binding [ rs:name "o" ; rs:value <http://local.virt/DAV/bound/bound1.rq> ] ;
          ] ;

    . . .

      rs:result [
          rs:binding [ rs:name "g" ; rs:value <http://local.virt/DAV/examples/manifest.rdf> ] ;
          rs:binding [ rs:name "s" ; rs:value _:nodeID1000000019 ] ;
          rs:binding [ rs:name "p" ; rs:value <http://example.com/test#query> ] ;
          rs:binding [ rs:name "o" ; rs:value <http://local.virt/DAV/examples/ex11.2.3.1_1.rq> ] ;
          ] ;
        ] .

    1 Rows. -- 00000 msec.

    SQL> sparql define output:format "RDF/XML" select * where {graph ?g { ?s ?p ?o }} limit 10;
    callret-0
    LONG VARCHAR
    _______________________________________________________________________________

    <rdf:RDF
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:rs="http://www.w3.org/2005/sparql-results#"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema#" >
       <rs:results rdf:nodeID="rset">
      <rs:result rdf:nodeID="sol206">
       <rs:binding rdf:nodeID="sol206-0" rs:name="g"><rs:value rdf:resource="http://local.virt/DAV/bound/manifest.rdf"/></rs:binding>
       <rs:binding rdf:nodeID="sol206-1" rs:name="s"><rs:value rdf:nodeID="1000000000"/></rs:binding>
       <rs:binding rdf:nodeID="sol206-2" rs:name="p"><rs:value rdf:resource="http://example.com/test#query"/></rs:binding>
       <rs:binding rdf:nodeID="sol206-3" rs:name="o"><rs:value rdf:resource="http://local.virt/DAV/bound/bound1.rq"/></rs:binding>
      </rs:result>

    . . .

      <rs:result rdf:nodeID="sol5737">
       <rs:binding rdf:nodeID="sol5737-0" rs:name="g"><rs:value rdf:resource="http://local.virt/DAV/examples/manifest.rdf"/></rs:binding>
       <rs:binding rdf:nodeID="sol5737-1" rs:name="s"><rs:value rdf:nodeID="1000000019"/></rs:binding>
       <rs:binding rdf:nodeID="sol5737-2" rs:name="p"><rs:value rdf:resource="http://example.com/test#query"/></rs:binding>
       <rs:binding rdf:nodeID="sol5737-3" rs:name="o"><rs:value rdf:resource="http://local.virt/DAV/examples/ex11.2.3.1_1.rq"/></rs:binding>
      </rs:result>
     </rs:results>
    </rdf:RDF>

    1 Rows. -- 00000 msec.

SPARQL CONSTRUCT and SPARQL DESCRIBE results are serialized as one would expect:

    SQL> sparql define output:format "TTL" construct { ?s ?p "004" } where {graph ?g { ?s ?p 4 }};
    callret-0
    LONG VARCHAR
    _______________________________________________________________________________

    <http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#four> <http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#int1> "004" .
    _:b1000000913 <http://www.w3.org/2001/sw/DataAccess/tests/result-set#index> "004" .

    1 Rows. -- 00000 msec.

    SQL> sparql define output:format "RDF/XML" construct { ?s ?p "004" } where {graph ?g { ?s ?p 4 }};
    callret-0
    LONG VARCHAR
    _______________________________________________________________________________

    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description about="http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#four"><ns0pred:int1 xmlns:ns0pred="http://www.w3.org/2001/sw/DataAccess/tests/data/Sorting/sort-0#">004</ns0pred:int1></rdf:Description>
    <rdf:Description rdf:nodeID="b1000000913"><ns0pred:index xmlns:ns0pred="http://www.w3.org/2001/sw/DataAccess/tests/result-set#">004</ns0pred:index></rdf:Description>
    </rdf:RDF>

    1 Rows. -- 00000 msec.

SPARQL ASK returns a non-empty result set if the match is found for graph pattern, empty result-set otherwise. If output:format is specified then the query makes a 'boolean result' document instead:

    SQL> sparql ask where {graph ?g { ?s ?p 4 }};
    __ask_retval
    INTEGER
    _______________________________________________________________________________

    1

    1 Rows. -- 00000 msec.

    SQL> sparql ask where {graph ?g { ?s ?p "no such" }};
    __ask_retval
    INTEGER
    _______________________________________________________________________________

    0 Rows. -- 00000 msec.

    SQL> sparql define output:format "TTL" ask where {graph ?g { ?s ?p 4 }};
    callret
    VARCHAR
    _______________________________________________________________________________

    @prefix :rdf <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
     @prefix :rs <http://www.w3.org/2005/sparql-results#> .
    [ rdf:type rs:results ; rs:boolean TRUE ]

    1 Rows. -- 00000 msec.

    SQL> sparql define output:format "RDF/XML" ask where {graph ?g { ?s ?p 4 }};
    callret
    VARCHAR
    _______________________________________________________________________________

    <rdf:RDF
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:rs="http://www.w3.org/2005/sparql-results#"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema#" >
       <rs:results rdf:nodeID="rset">
        <rs:boolean rdf:datatype="http://www.w3.org/2001/XMLSchema#boolean">1</rs:boolean></results></rdf:RDF>

    1 Rows. -- 00000 msec.

### 14.2.2. API Functions

#### 14.2.2.1. Data Import

DB.DBA.TTLP() parses TTL (TURTLE or N3 resource) and places its triples into DB.DBA.RDF_QUAD.

    create procedure DB.DBA.TTLP (
        in strg any,       -- text of the resource
        in base varchar,  -- base IRI to resolve relative IRIs to absolute
        in graph varchar, -- target graph IRI, parsed triples will appear in that graph.
        in flags int)   -- bitmask of flags that permit some sorts of syntax errors in resource, use 0.

For loading a file of any greater length, it is most practical to use the file_to_string_output function with this, as follows:

    SQL> ttlp (file_to_string_output ('data.ttl'), '', 'http://my_graph', 0);

The DB.DBA.TTLP_MT() procedure is like DB.DBA.TTLP() but loads the file on multiple threads, using parallel IO and multiprocessing if available. The functions does not leave a transaction log. Hence, after successful load, one should execute the checkpoint statement to make sure that a server restart does not wipe out the results.

    create procedure DB.DBA.TTLP_MT (
        in strg any,       -- text of the resource
        in base varchar,   -- base IRI to resolve relative IRIs to absolute
        in graph varchar,  -- target graph IRI, parsed triples will appear in that graph.
        in flags int) -- flags, use 0

The DB.DBA.RDF_TTL2HASH() does not load TTL content, instead it returns a dict of triples in 'long valmode'.

    create function DB.DBA.RDF_TTL2HASH (
        in strg any,
        in base varchar,
        in graph varchar ) returns any

Parameter flags is useful when syntax of resource is TURTLE-like but not correct TURTLE. By default, use zero value. Add 1 to let string literals contain end-of-line characters. Add 2 to suppress error messages on blank node verbs. Add 4 to let variables instead of blank nodes. Add 8 to silently skip triples with literal subjects.

The DB.DBA.RDF_LOAD_RDFXML() procedure parses RDF/XML and places its triples into DB.DBA.RDF_QUAD.

    create procedure DB.DBA.RDF_LOAD_RDFXML (
        in strg any,           -- text of and XML document
        in base_iri varchar,   -- base IRI to resolve relative IRIs
        in graph_iri varchar ) -- the IRI of destination graph

To insert a single quad into DB.DBA.RDF_QUAD() table, use one of these procedures:

    -- Simple insertion of a quad where object is a node
    create procedure DB.DBA.RDF_QUAD_URI (
      in g_uri varchar, in s_uri varchar, in p_uri varchar,
      in o_uri varchar ) -- IRI string or IRI_ID

    -- Simple insertion of a quad where object is a literal value in 'SQL valmode'
    create procedure DB.DBA.RDF_QUAD_URI_L (
      in g_uri varchar, in s_uri varchar, in p_uri varchar,
      in o_lit any ) -- string, number or datetime, NULL is not allowed

    create procedure DB.DBA.RDF_QUAD_URI_L_TYPED (
      in g_uri varchar, in s_uri varchar, in p_uri varchar,
      in o_lit any,     -- string value of the literal
      in dt any,        -- datatype as IRI string or IRI_ID, can be NULL
      in lang varchar ) -- language as string or NULL

Arguments g_uri, s_uri and p_uri of these three functions should be IRI strings or IRI_IDs. All string arguments should be in UTF-8 encoding, otherwise they will be stored but are not queriable via SPARQL.

#### 14.2.2.2. Data Export

These two procedures serializes vector of triples into a session, in TURTLE or RDF/XML syntax. In current version, every triple is printed in separate top-level record (say, in rdf:Description tag), without any pretty-print or nesting optimization.

    create procedure DB.DBA.RDF_TRIPLES_TO_TTL (
        inout triples any, -- vector of triples in 'long valmode'.
        inout ses any )    -- an output stream in server default encoding

    create procedure DB.DBA.RDF_TRIPLES_TO_RDF_XML_TEXT (
        inout triples any,          -- vector of triples in 'long valmode'.
        in print_top_level integer, -- zero if only rdf:Description tags should be written,
          -- non-zero if the rdf:RDF top-level element should also be written
        inout ses any )             -- an output stream in server default encoding

#### 14.2.2.3. Data query

    -- Local execution of SPARQL via SPARQL protocol, produces a result set of SQL values.
    create procedure DB.DBA.SPARQL_EVAL (
        in query varchar,      -- text of SPARQL query to execute
        in dflt_graph varchar, -- default graph IRI, if not NULL then this overrides what's specified in query
        in maxrows integer )   -- limit on numbers of rows that should be returned.

    -- Similar to SPARQL_EVAL, but returns a vector of vectors of SQL values.
    create function DB.DBA.SPARQL_EVAL_TO_ARRAY (
        in query varchar,      -- text of SPARQL query to execute
        in dflt_graph varchar, -- text of SPARQL query to execute
        in maxrows integer )   -- limit on numbers of rows that should be returned.
    returns any

    -- Remote execution of SPARQL via SPARQL protocol, produces a result set of SQL values.
    create procedure DB.DBA.SPARQL_REXEC (
        in service varchar,    -- service URI to call via HTTP
        in query varchar,      -- text of SPARQL query to execute
        in dflt_graph varchar, -- default graph IRI, if not NULL then this overrides what's specified in query
        in named_graphs any,   -- vector of named graph IRIs, if not NULL then this overrides what's specified in query
        in req_hdr any,        -- additional HTTP header lines that should be passed to the service; 'Host: ...' is most po
    pular.
        in maxrows integer,    -- limit on numbers of rows that should be returned.
        in bnode_dict any )    -- dictionary of bnode ID references.

    -- Similar to SPARQL_REXEC (), but returns a vector of vectors of SQL values.
    -- All arguments are the same.
    create function DB.DBA.SPARQL_REXEC_TO_ARRAY (
        in service varchar, in query varchar, in dflt_graph varchar, in named_graphs any,
        in req_hdr any, in maxrows integer, in bnode_dict any)
    returns any

    -- Similar to SPARQL_REXEC (), but fills in output parameters with metadata (like exec metadata) and a vector of vector
    s of 'long valmode' values.
    -- First seven arguments are the same.
    create procedure DB.DBA.SPARQL_REXEC_WITH_META (
        in service varchar, in query varchar, in dflt_graph varchar, in named_graphs any,
        in req_hdr any, in maxrows integer, in bnode_dict any,
        out metadata any,  -- metadata like exec () returns.
        out resultset any) -- results as 'long valmode' value.

If the query is a CONSTRUCT or DESCRIBE then the result set consists of a single row and single column, the value inside is a dict of triples in 'long valmode'.

### 14.2.3. Useful Internal Functions

#### 14.2.3.1. Conversion Functions for XMLSchema/RDF Data Serialization Syntax

These functions emulate constructor functions from XQuery Core Function Library.

    create function DB.DBA."http://www.w3.org/2001/XMLSchema#boolean" (in strg any) returns integer
    create function DB.DBA."http://www.w3.org/2001/XMLSchema#dateTime" (in strg any) returns datetime
    create function DB.DBA."http://www.w3.org/2001/XMLSchema#double" (in strg varchar) returns double precision
    create function DB.DBA."http://www.w3.org/2001/XMLSchema#float" (in strg varchar) returns float
    create function DB.DBA."http://www.w3.org/2001/XMLSchema#integer" (in strg varchar) returns integer

#### 14.2.3.2. RDF-specific Predicates

    -- Returns 1 if string s matches pattern p, 0 otherwise
    create function DB.DBA.RDF_REGEX (
        in s varchar,            -- source string to check
        in p varchar,            -- regular expression pattern string
        in coll varchar := null) -- unused for now (modes are not yet implemented)

    -- Returns 1 if language identifier r matches lang pattern t
    create function DB.DBA.RDF_LANGMATCHES (
      in r varchar, -- language identifies (string or NULL)
      in t varchar) -- language pattern (exact name, first two letters or '*')

### 14.2.4. Default and Named Graphs

Sometimes the default graph IRI is not known when the SPARQL query is composed. It can be added at the very last moment by providing the IRI in 'define' clause as follows:

    define input:default-graph-uri <http://example.com>

Such a definition overrides the default graph URI set in query by 'FROM ...' clause (if any).

The query may contain more than one define input:default-graph-uri. The set of values of input:default-graph-uri has the highest possible priority and can not be redefined in the rest of the text of the query by FROM clauses.

Similarly, define input:named-graph-uri <http://example.com> is a replacement for FROM NAMED clause

When Virtuoso receives a SPARQL request via HTTP, the value of default graph can be set in protocol as default-graph-uri HTTP parameter. Multiple occurencies of this parameter are allowed. This HTTP parameter is converted into define input:default-graph-uri. There's similar support for named-graph-uri HTTP parameter. For debugging purposes, graph names set in protocol are sent back in the reply header as X-SPARQL-default-graph: ... and X-SPARQL-named-graph: ... header lines, one line per graph.

Web service endpoint may provide different default configurations for different host names mentioned in HTTP request. This is configured via table DB.DBA.SYS_SPARQL_HOST.

    create table DB.DBA.SYS_SPARQL_HOST (
      SH_HOST	varchar not null primary key, -- host mask
      SH_GRAPH_URI	varchar,      -- 'default default' graph uri
      SH_USER_URI	varchar,      -- reserved for any use in applications
      SH_DEFINES	long varchar  -- additional defines for requests
    )

When the SPARQL web service endpoint receives a request it checks the Host HTTP header line. This line contains zero or more target host names, delimited by commas. For every host name in the line the service scans the DB.DBA.SYS_SPARQL_HOST in search of row such that host name is like SH_HOST. The SH_HOST acts as 'pattern' argument for SQL string operator LIKE. If the row is found then the text of SPARQL request is extended. If default graph is not explicitely set by HTTP parameters and SH_GRAPH_URI is not null then default graph is set to SH_GRAPH_URI. If SH_DEFINES is not null then it is added in front of query so this field is a good place for text for any define options.

The search in DB.DBA.SYS_SPARQL_HOST stops at the first found row, other possible matches are silently ignored.

### 14.2.5. Calling SQL from SPARQL

A SPARQL expression can contain calls of Virtuoso/PL functions and built-in SQL functions in both the WHERE clause and in result set. Two namespace prefixes, bif and sql are reserved for these purposes. When a function name starts with bif: namespace prefix, the rest of name is treated as a name of SQL BIF (Built-In Function). When a function name starts with sql: namespace prefix, the rest of name is treated as a name of Virtuoso/PL function owned by DBA with database qualifier DB, e.g. sql:example(...) is converted into DB.DBA."example"(...).

In both cases, the function receives arguments in SQL format ('SQL valmode') and returns the result also in SQL format. The SPARQL compiler will automatically add code for format conversion into the resulting SQL code so SQL functions can be used even if define output:valmode 'LONG' forces the use of internal RDF representation in the result set.

### 14.2.6. SPARUL -- an Update Language For RDF Graphs

Starting from version 5.0, Virtuoso supports SPARQL/Update extension of SPARQL. This is sufficient for most of routine data manipulation operations. If SPARQL_UPDATE role is granted to SPARQL user then data manipulation statements may be executed via SPARQL web service enpoint as well as data querying.

Two functions allow the user to alter RDF storage by inserting or deleting all triples lsited in some vector. Both functions receive an IRI of a graph that should be altered and a vector of triples that should be added or removed. The graph IRI can be either IRI ID or a string. The return values of functions are not defined and should not be used by applications.

    create function DB.DBA.RDF_INSERT_TRIPLES (in graph_iri any, in triples any)
    create function DB.DBA.RDF_DELETE_TRIPLES (in graph_iri any, in triples any)

Simple operations may be faster if written as low-level SQL code instead of using SPARUL. E.g, the use of SPARQL DELETE is redundand when the application should delete from RDF_QUAD by using simple filters like

    delete from DB.DBA.RDF_QUAD
    where G = DB.DBA.RDF_MAKE_IID_OF_QNAME (
        'http://local.virt/DAV/sparql_demo/data/data-xml/source-simple2/source-data-01.rdf' );

On the other hand, simple filters does not work when search criteria refer to triples that are affected by the modification. Consider a function that deletes all triples whose subjects are nodes of type 'http://xmlns.com/foaf/0.1/Person'. Type information is stored in triples that will be deleted, so the simplest function is something like this:

    create procedure DELETE_PERSONAL_DATA (in foaf_graph varchar)
    {
      declare pdata_dict, pdata_array any;
    -- Step 1: select everything that should be deleted
      pdata_dict := ((
          sparql construct { ?s ?p ?o }
          where { graph ?:foaf_graph {
                  ?s ?p ?o . ?s rdf:type <http://xmlns.com/foaf/0.1/Person>
                } }
          ));
    -- Step 2: delete all found triples
      pdata_array := dict_list_keys (pdata_dict, 1);
      RDF_DELETE_TRIPLES (foaf_graph, pdata_array);
    };

    DELETE_PERSONAL_DATA (
      'http://local.virt/DAV/sparql_demo/data/data-xml/source-simple2/source-data-01.rdf' );

Starting from Virtuoso 5.0, application may use SPARUL to do the same in a convenient way:

    create procedure DELETE_PERSONAL_DATA (in foaf_graph varchar)
    {
      sparql delete { ?s ?p ?o }
          where { graph ?:foaf_graph {
                  ?s ?p ?o . ?s rdf:type <http://xmlns.com/foaf/0.1/Person>
               } }
    };

Previous Data Representation | Chapter Contents | Next IRI Dereferencing