Sophie

Sophie

distrib > Fedora > 14 > x86_64 > media > updates > by-pkgid > 71d40963b505df4524269198e237b3e3 > files > 877

virtuoso-opensource-doc-6.1.4-2.fc14.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
 <head profile="http://internetalchemy.org/2003/02/profile">
  <link rel="foaf" type="application/rdf+xml" title="FOAF" href="http://www.openlinksw.com/dataspace/uda/about.rdf" />
  <link rel="schema.dc" href="http://purl.org/dc/elements/1.1/" />
  <meta name="dc.title" content="14. RDF Data Access and Data Management" />
  <meta name="dc.subject" content="14. RDF Data Access and Data Management" />
  <meta name="dc.creator" content="OpenLink Software Documentation Team ;&#10;" />
  <meta name="dc.copyright" content="OpenLink Software, 1999 - 2009" />
  <link rel="top" href="index.html" title="OpenLink Virtuoso Universal Server: Documentation" />
  <link rel="search" href="/doc/adv_search.vspx" title="Search OpenLink Virtuoso Universal Server: Documentation" />
  <link rel="parent" href="rdfandsparql.html" title="Chapter Contents" />
  <link rel="prev" href="rdfsparql.html" title="SPARQL" />
  <link rel="next" href="rdfgraphsecurity.html" title="RDF Graphs Security" />
  <link rel="shortcut icon" href="../images/misc/favicon.ico" type="image/x-icon" />
  <link rel="stylesheet" type="text/css" href="doc.css" />
  <link rel="stylesheet" type="text/css" href="/doc/translation.css" />
  <title>14. RDF Data Access and Data Management</title>
  <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
  <meta name="author" content="OpenLink Software Documentation Team ;&#10;" />
  <meta name="copyright" content="OpenLink Software, 1999 - 2009" />
  <meta name="keywords" content="" />
  <meta name="GENERATOR" content="OpenLink XSLT Team" />
 </head>
 <body>
  <div id="header">
    <a name="sparqlextensions" />
    <img src="../images/misc/logo.jpg" alt="" />
    <h1>14. RDF Data Access and Data Management</h1>
  </div>
  <div id="navbartop">
   <div>
      <a class="link" href="rdfandsparql.html">Chapter Contents</a> | <a class="link" href="rdfsparql.html" title="SPARQL">Prev</a> | <a class="link" href="rdfgraphsecurity.html" title="RDF Graphs Security">Next</a>
   </div>
  </div>
  <div id="currenttoc">
   <form method="post" action="/doc/adv_search.vspx">
    <div class="search">Keyword Search: <br />
        <input type="text" name="q" /> <input type="submit" name="go" value="Go" />
    </div>
   </form>
   <div>
      <a href="http://www.openlinksw.com/">www.openlinksw.com</a>
   </div>
   <div>
      <a href="http://docs.openlinksw.com/">docs.openlinksw.com</a>
   </div>
    <br />
   <div>
      <a href="index.html">Book Home</a>
   </div>
    <br />
   <div>
      <a href="contents.html">Contents</a>
   </div>
   <div>
      <a href="preface.html">Preface</a>
   </div>
    <br />
   <div class="selected">
      <a href="rdfandsparql.html">RDF Data Access and Data Management</a>
   </div>
    <br />
   <div>
      <a href="rdfdatarepresentation.html">Data Representation</a>
   </div>
   <div>
      <a href="rdfsparql.html">SPARQL</a>
   </div>
   <div class="selected">
      <a href="sparqlextensions.html">Extensions</a>
    <div>
        <a href="#rdfsparqlrulefulltext" title="Using Full Text Search in SPARQL">Using Full Text Search in SPARQL</a>
        <a href="#rdfsparul" title="SPARUL -- an Update Language For RDF Graphs">SPARUL -- an Update Language For RDF Graphs</a>
        <a href="#sparqlbi" title="Business Intelligence Extensions for SPARQL">Business Intelligence Extensions for SPARQL</a>
    </div>
   </div>
   <div>
      <a href="rdfgraphsecurity.html">RDF Graphs Security</a>
   </div>
   <div>
      <a href="rdfviews.html">Linked Data Views over RDBMS Data Source</a>
   </div>
   <div>
      <a href="rdfrdfviewgnr.html">Automated Generation of RDF Views over Relational Data Sources</a>
   </div>
   <div>
      <a href="rdfviewsenterpr.html">Examples of Linked Data Views</a>
   </div>
   <div>
      <a href="rdfinsertmethods.html">RDF Insert Methods in Virtuoso</a>
   </div>
   <div>
      <a href="virtuososponger.html">RDFizer Middleware (Sponger)</a>
   </div>
   <div>
      <a href="virtuosospongerfacetinstall.html">Virtuoso Faceted Browser Installation and configuration</a>
   </div>
   <div>
      <a href="virtuosospongerfacent.html">Virtuoso Faceted Web Service</a>
   </div>
   <div>
      <a href="rdfiridereferencing.html">Linked Data</a>
   </div>
   <div>
      <a href="rdfsparqlrule.html">Inference Rules &amp; Reasoning</a>
   </div>
   <div>
      <a href="rdfsparqlgeospat.html">RDF and Geometry</a>
   </div>
   <div>
      <a href="rdfperformancetuning.html">RDF Performance Tuning</a>
   </div>
   <div>
      <a href="rdfnativestorageproviders.html">RDF Data Access Providers (Drivers)</a>
   </div>
   <div>
      <a href="rdfgraphreplication.html">RDF Graph Replication</a>
   </div>
    <br />
  </div>
  <div id="text">
    <a name="sparqlextensions" />
    <h2>14.3. Extensions</h2>
<a name="rdfsparqlrulefulltext" />
    <h3>14.3.1. Using Full Text Search in SPARQL</h3>
<p>Virtuoso&#39;s triple store supports optional full text indexing of RDF object values since version 5.0.
It is possible to declare that objects of triples with a given predicate or graph get indexed.
The graphs and triples may be enumerated or a wildcard may be used.
</p>
<p>The triples for which a full text index entry exists can be found using the <strong>bif:contains</strong>
or related filters and predicates.
</p>
<p>For example, the query:
</p>
<div>
      <pre class="programlisting">
SQL&gt;SELECT *
FROM &lt;people&gt;
WHERE
  {
    ?s foaf:Name ?name . ?name bif:contains &quot;&#39;rich*&#39;&quot;.
  }
</pre>
    </div>
<p>would match all subjects whose <strong>foaf:Name</strong> contained a word starting with Rich.
This would match Richard, Richie etc.
</p>
<p>Note that words and phrases should be enclosed in quotes if they contain spaces or
other non-alphanumeric chars.
</p>
<p>If the <strong>bif:contains</strong> or related predicate is applied to an object that is not
a string or is not the object of an indexed triple, no match will be found.
</p>
<p>The syntax for text patterns is identical to the syntax for the SQL contains predicate.
</p>
<p>The SPARQL/SQL optimizer determines whether the text pattern will be used to drive the query or whether it
will filter results after other conditions are applied first. In contrast to <strong>bif:contains</strong>,
regexp matching never drives the query or makes use of an index, thus in practice regexps are checked after other conditions.
</p>
<a name="rdfsparqlrulespecifywhatindex" />
    <h4>14.3.1.1. Specifying What to Index</h4>
<p>Whether the object of a given triple is indexed in the text index depends on indexing rules. If at least one
indexing rule matches the triple, the object gets indexed if the object is a string. An indexing rule specifies
a graph and a predicate. Either may be an IRI or NULL, in which case it matches all IRI&#39;s.
</p>
<p>Rules also have a &#39;reason&#39;, which can be used to group rules into application-specific sets. A triple will stop
being indexed only after all rules mandating its indexing are removed. When an application requires indexing a
certain set of triples, rules are added for that purpose. These rules are tagged with the name of the application
as their reason. When an application no longer requires indexing, the rules belonging to this application can be
removed. This will not turn off indexing if another application still needs certain triples to stay indexed.
</p>
<p>Indexing is enabled/disabled for specific graph/predicate combinations with:
</p>
<div>
      <pre class="programlisting">
create function DB.DBA.RDF_OBJ_FT_RULE_ADD
  (in rule_g varchar, in rule_p varchar, in reason varchar) returns integer
</pre>
    </div>
<div>
      <pre class="programlisting">
create function DB.DBA.RDF_OBJ_FT_RULE_DEL
  (in rule_g varchar, in rule_p varchar, in reason varchar) returns integer
</pre>
    </div>
<strong>Example:</strong>
<p>The first function adds a rule. The first two arguments are the text representation of the IRI&#39;s for the graph
and predicate. If NULL is given then all graph&#39;s or predicates match. Specifying both as NULL means that all
string valued objects will be added to a text index.
       </p>
<strong>Example:</strong>
<div>
      <pre class="programlisting">
DB.DBA.RDF_OBJ_FT_RULE_ADD (null, null, &#39;All&#39;);	
</pre>
    </div>
<p>The second function reverses the effect of the first. Only a rule that has actually been added can be deleted.
Thus one cannot say that all except a certain enumerated set should be indexed.
</p>
<div>
      <pre class="programlisting">
DB.DBA.RDF_OBJ_FT_RULE_DEL (null, null, &#39;All&#39;);
</pre>
    </div>
<p>The reason argument is an arbitrary string identifying the application that needs this rule.
Two applications can add the same rule.
Removing one of them will still keep the rule in effect.
If an object is indexed by more than one rule, the index data remain free from duplicates, neither index size nor speed is affected.
</p>
<p>
If <strong>DB.DBA.RDF_OBJ_FT_RULE_ADD</strong> detects that <strong>DB.DBA.RDF_QUAD</strong> contains quads whose graphs and/or predicates match to the new rule but which have not been indexed before then these quads are indexed automatically.
However the function <strong>DB.DBA.RDF_OBJ_FT_RULE_DEL</strong> does not remove indexing data about related objects.
Thus the presence of indexing data about an object does not imply that it is necessarily used in some quad that matches to some rule.
</p>
<p>The above functions return one if the rule is added or deleted and zero if the call was redundant (the rule has been added before or there&#39;s no rule to delete).
</p>
<a name="rdfsparqlrulespecifywhatindexexample" />
    <h5>14.3.1.1.1. Example</h5>
<div>
      <pre class="programlisting">

-- We load Tim Berners-Lee&#39;s FOAF file into a graph called &#39;people&#39;.

SQL&gt;DB.DBA.RDF_LOAD_RDFXML (http_get (&#39;http://www.w3.org/People/Berners-Lee/card#i&#39;), &#39;no&#39;, &#39;http://www.w3.org/people#&#39;);
Done. -- 172 msec.

-- We check how many triples we got.

SQL&gt;SPARQL SELECT COUNT (*) FROM &lt;http://www.w3.org/people#&gt; WHERE {?s ?p ?o};
callret-0
INTEGER
 266
No. of rows in result: 1

-- We check the GRAPH: &lt;http://www.w3.org/people#&gt; for objects like &quot;Tim&quot;:

SQL&gt;SPARQL
SELECT *
FROM &lt;http://www.w3.org/people#&gt;
WHERE
  {
    ?s ?p ?o . FILTER (?o LIKE &#39;%Tim%&#39;)
  };
s                                               p                                           o
VARCHAR                                         VARCHAR                                     VARCHAR
_______________________________________________________________________________

http://www.w3.org/People/Berners-Lee/card#i     http://xmlns.com/foaf/0.1/name              Timothy Berners-Lee
http://www.w3.org/People/Berners-Lee/card#i     http://xmlns.com/foaf/0.1/nick              TimBL
http://www.w3.org/People/Berners-Lee/card#i     http://www.w3.org/2002/07/owl#sameAs        http://www4.wiwiss.fu-berlin.de/bookmashup/persons/Tim+Berners-Lee
http://www.w3.org/People/Berners-Lee/card#i     http://xmlns.com/foaf/0.1/knows             http://dbpedia.org/resource/Tim_Bray
http://www.w3.org/People/Berners-Lee/card#i     http://www.w3.org/2000/01/rdf-schema#label  Tim Berners-Lee
http://www.w3.org/People/Berners-Lee/card#i     http://xmlns.com/foaf/0.1/givenname         Timothy
http://dbpedia.org/resource/Tim_Bray            http://xmlns.com/foaf/0.1/name              Tim Bray
no                                              http://purl.org/dc/elements/1.1/title       Tim Berners-Lee&#39;s FOAF file

8 Rows. -- 230 msec.


-- We specify that all string objects in the graph &#39;people&#39; should be text indexed.

SQL&gt;DB.DBA.RDF_OBJ_FT_RULE_ADD(&#39;http://www.w3.org/people#&#39;, null, &#39;people&#39;);
Done. -- 130 msec.

-- We update the text index.

SQL&gt;DB.DBA.VT_INC_INDEX_DB_DBA_RDF_OBJ ();
Done. -- 140 msec.

-- See impact of the index  by querying the subjects and predicates
-- of all triples in the GRAPH: &lt;http://www.w3.org/people#&gt;,
-- where the object is a string which contains a word beginning with &quot;TIM&quot;.

SQL&gt;SPARQL SELECT * FROM &lt;http://www.w3.org/people#&gt; WHERE { ?s ?p ?o . ?o bif:contains &#39;&quot;Timo*&quot;&#39;};
s                                               p                                     o
VARCHAR                                         VARCHAR                               VARCHAR
_______________________________________________________________________________

 http://www.w3.org/People/Berners-Lee/card#i	http://xmlns.com/foaf/0.1/name	      Timothy Berners-Lee
 http://www.w3.org/People/Berners-Lee/card#i	http://xmlns.com/foaf/0.1/givenname   Timothy

2 Rows. -- 2 msec.
</pre>
    </div>
<p>
The query below is identical with that above but uses a different syntax.
The filter syntax is more flexible in that it allows passing extra options to the <strong>contains</strong> predicate. These may be useful in the future.
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL SELECT * FROM &lt;people&gt; WHERE { ?s ?p ?o . FILTER (bif:contains(?o,  &#39;&quot;Timo*&quot;&#39;)) };
</pre>
    </div>
<br />
<div class="note">
      <div class="notetitle">Note:</div>
      <p>It is advisable to upgrade to the latest version of Virtuoso before adding free-text rules for the first time.
This is especially the case if large amounts of text are to be indexed. The reason is that the free-text index on RDF may be changed in future versions
and automatic upgrading of an existing index data into the new format may take much more time than indexing from scratch.</p>
    </div>
<p>The table <strong>DB.DBA.RDF_OBJ_FT_RULES</strong> stores list of free-text index configuration rules.
</p>
<div>
      <pre class="programlisting">
create table DB.DBA.RDF_OBJ_FT_RULES (
  ROFR_G varchar not null,       -- specific graph IRI or NULL for &quot;all graphs&quot;
  ROFR_P varchar not null,       -- specific predicate IRI or NULL for &quot;all predicates&quot;
  ROFR_REASON varchar not null,  -- identification string of a creator, preferably human-readable
  primary key (ROFR_G, ROFR_P, ROFR_REASON) );
</pre>
    </div>
<p>
Applications may read from this table but they should not write to it directly.
Duplications in the rules do not affect the speed of free-text index operations because the content of the table is cached in memory in a special form.
Unlike the use of configuration functions, directly writing to the table will not update the in-memory cache.
</p>
<p>
The table is convenient to search for rules added by a given application.
If a unique identification string is used during installation of an application when rules are added then it&#39;s easy to remove those rules
as part of any uninstall routine.
</p>
   <br />
<a name="rdfsparqlruletimeindexing" />
    <h4>14.3.1.2. Time of Indexing</h4>
<p>The triple store&#39;s text index is in manual batch mode by default. This means that changes in triples are periodically
reflected in the text index but are not maintained in strict synchrony. This is much more efficient than keeping the
indices in constant synchrony. This setting may be altered with the <strong>db.dba.vt_batch_update</strong> stored procedure.
</p>
<p>To force synchronization of the RDF text index, use:
</p>
<div>
      <pre class="programlisting">
DB.DBA.VT_INC_INDEX_DB_DBA_RDF_OBJ ();
</pre>
    </div>
<p>To set the text index to follow the triples in real time, use:
</p>
<div>
      <pre class="programlisting">
DB.DBA.VT_BATCH_UPDATE (&#39;DB.DBA.RDF_OBJ&#39;, &#39;OFF&#39;, null);
</pre>
    </div>
<p>To set the text index to be updated every 10 minutes, use:
</p>
<div>
      <pre class="programlisting">
DB.DBA.VT_BATCH_UPDATE (&#39;DB.DBA.RDF_OBJ&#39;, &#39;ON&#39;, 10);
</pre>
    </div>
<p>To make the update always manual, specify NULL as the last argument above.
</p>
<p>
One problem related to free-text indexing of <strong>DB.DBA.RDF_QUAD</strong> is that some applications (e.g. those that import billions of triples) may set off triggers.
This will make free-text index data incomplete.
Calling procedure <strong>DB.DBA.RDF_OBJ_FT_RECOVER ()</strong> will insert all missing free-text index items by dropping and re-inserting every existing free-text index rule.
</p>
<br />
<a name="rdfviewsandfreetext" />
    <h4>14.3.1.3. Free-Text Indexes on Linked Data Views</h4>
<p>
If an <strong>O</strong> field of a quad map pattern gets its value from a database column that has a free text index then this index can be used in SPARQL for efficient text searching. As a variation of this facility, the free-text index of another table may be used.
</p>
<p>
If a statement of a quad map pattern declaration starts with a declaration of table aliases, the table alias declaration may include the name of a table column that should have a text index.
For example, consider the possibility of using a free-text index on the content of DAV resources stored in the DAV system tables of Virtuoso:
</p>
<div>
      <pre class="programlisting">
prefix mydav: &lt;...&gt;
create quad storage mydav:metadata
FROM WS.WS.SYS_DAV_RES as dav_resource text literal RES_CONTENT
...
  {
    ...
    mydav:resource-iri (dav_resource.RES_FULL_PATH)
        a mydav:resource ;
        mydav:resource-content dav_resource.RES_CONTENT ;
        mydav:resource-mime-type dav_resource.RESTYPE ;
    ...
  }
</pre>
    </div>
<p>
The clause <strong>text literal RES_CONTENT</strong> grants the SPARQL compiler permission to use a free-text index for objects that are literals composed from column <strong>dav_resource.RES_CONTENT</strong>. This clause also allows choosing between <strong>text literal</strong> (supports only the <strong>contains()</strong> predicate) and <strong>text xml literal</strong> (supports both <strong>contains()</strong> and <strong>xcontains()</strong>) text indexes.
It is important to understand that the free-text index will produce results using raw relational data.
If a literal class transformation changes the text stored in the column then these changes are ignored by free-text search.
e.g. if a transformation concatenates a word to the value of the column, but the free-text search will not find this word.
</p>
<p>
The free-text index may be used in a more sophisticated way. Consider a built-in table <strong>DB.DBA.RDF_QUAD</strong> that does not have a free-text index.
Moreover, the table does not contain the full values of all objects; the <strong>O</strong> column contains &quot;short enough&quot; values inlined, but long and special values are represented by links to the <strong>DB.DBA.RDF_OBJ</strong> table.
The RDF_OBJ table, however, has free-text index that can be used.
The full declaration of the built-in default mapping for default storage could be written this way:
   </p>
<div>
      <pre class="programlisting">
-- Important! Do not try to execute on live system
-- without first changing the quad storage and quad map pattern names!

SPARQL
create virtrdf:DefaultQuadMap as
graph rdfdf:default-iid-nonblank (DB.DBA.RDF_QUAD.G)
subject rdfdf:default-iid (DB.DBA.RDF_QUAD.S)
predicate rdfdf:default-iid-nonblank (DB.DBA.RDF_QUAD.P)
object rdfdf:default (DB.DBA.RDF_QUAD.O)

create quad storage virtrdf:DefaultQuadStorage
FROM DB.DBA.RDF_QUAD as physical_quad
FROM DB.DBA.RDF_OBJ as physical_obj text xml literal RO_DIGEST of (physical_quad.O)
WHERE (^{physical_quad.}^.O = ^{physical_obj.}^.RO_DIGEST)
  {
    create virtrdf:DefaultQuadMap as
      graph rdfdf:default-iid-nonblank (physical_quad.G)
      subject rdfdf:default-iid (physical_quad.S)
      predicate rdfdf:default-iid-nonblank (physical_quad.P)
      object rdfdf:default (physical_quad.O) .
 }
;
</pre>
    </div>
<p>
The reference to the free-text index is extended by clause <strong> of (physical_quad.O)</strong>.
This means that the free-text on <strong>DB.DBA.RDF_OBJ.RO_DIGEST</strong> will be used when the object value comes from <strong>physical_quad.O</strong> as if <strong>physical_quad.O</strong> were indexed itself.
If a SPARQL query invokes <strong>virtrdf:DefaultQuadMap</strong> but contains no free-text criteria then only <strong>DB.DBA.RDF_QUAD</strong> appears in the final SQL statement and no join with <strong>DB.DBA.RDF_OBJ</strong> is made.
Adding a free-text predicate will add <strong>DB.DBA.RDF_OBJ</strong> to the list of source tables and a join condition for <strong>DB.DBA.RDF_QUAD.O</strong> and <strong>DB.DBA.RDF_OBJ.RO_DIGEST</strong>; and it will add <strong>contains (RO_DIGEST, ...)</strong> predicate, rather than <strong>contains (O, ...)</strong>.
As a result, &quot;you pay only for what you use&quot;: adding free-text index to the declaration does not add tables to the query unless the index is actually used.
</p>
<p>
Boolean functions <span class="computeroutput">bif:contains</span> and <span class="computeroutput">bif:xcontains</span> are used 
for objects that come from Linked Data Views as well as for regular &quot;physical&quot; triples.
Every function takes two arguments and returns a boolean value. The first argument is an local variable.
The argument variable should be used as an object field in the group pattern where the filter condition is placed.
Moreover, the occurrence of the variable in an object field should be placed <strong>before</strong> the filter.
If there are many occurrences of the variable in object fields then the free-text search is associated with the rightmost occurrence that is still to the left of the filter.
The triple pattern that contains the rightmost occurrence is called the &quot;intake&quot; of the free-text search.
When the SPARQL compiler chooses the appropriate quad map patterns that may generate data matching the intake triple pattern, it skips quad map patterns that have no declared free-text indexes, because nothing can be found by free-text search in data that have no free-text index.
Every quad map pattern that has a free-text pattern will ultimately produce an invocation of the SQL <a href="queryingftcols.html#containspredicate">contains</a> or <a href="queryingxmldata.html#xcontainspredicate">xcontains</a> predicate, so the final result of a free-text search may be a union of free-text searches from different quad map patterns.
</p>
<p>
The described logic is important only in very complicated cases, whereas simple queries are self-evident:
   </p>
<div>
      <pre class="programlisting">
SELECT * FROM &lt;my-dav-graph&gt;
WHERE {
    ?resource a mydav:resource ;
        mydav:resource-content ?text .
    FILTER (bif:contains (?text, &quot;hello and world&quot;)) }
</pre>
    </div>
<p>
or, more succinctly,
   </p>
<div>
      <pre class="programlisting">
SELECT * FROM &lt;my-dav-graph&gt;
WHERE {
    ?resource a mydav:resource ;
        mydav:resource-content ?text .
    ?text bif:contains &quot;hello and world&quot; . }
</pre>
    </div>
<br />
<a name="rdfsparqlrulescoreexmp" />
    <h4>14.3.1.4. Example Using Score</h4>
<div>
      <pre class="programlisting">
SQL&gt;
SPARQL
SELECT *
WHERE
  {
    ?s ?p ?o .
    ?o bif:contains &#39;NEW AND YORK&#39;
    OPTION (score ?sc) .
  }
ORDER BY DESC (?sc)
LIMIT 10

s                                                                        p                                               o                                                sc
ANY                                                                      ANY                                             ANY 	                                          ANY
______________________________________________________________________________________________________________________________________________________________________________

http://dbpedia.org/resource/New_York%2C_New_York_%28disambiguation%29	 http://www.w3.org/2000/01/rdf-schema#comment	 New York, New York, New York kentini........     88
http://dbpedia.org/resource/New_York%2C_New_York_%28disambiguation%29	 http://dbpedia.org/property/abstract	         New York, New York, New York kentinin re....     88
http://newyorkjobs.wordpress.com/2006/07/10/new-york-jobs-71006	         http://purl.org/dc/elements/1.1/description	 York Marketing Jobs New York Retail Jobs....     84
http://dbpedia.org/resource/Global_Communication	                 http://dbpedia.org/property/contenu	         A - New York, New York (Headfuq Mix) B1 ....     84
http://dbpedia.org/resource/New_York_%28disambiguation%29	         http://www.w3.org/2000/01/rdf-schema#comment	 New York a^?? New York amerikai vA~?ros ....     76
http://dbpedia.org/resource/New_York_%28disambiguation%29	         http://dbpedia.org/property/abstract	         New York a^?? New York amerikai vA~?ros ....     76
http://dbpedia.org/resource/New_York_%28disambiguation%29	         http://www.w3.org/2000/01/rdf-schema#comment	 New York ima lahko naslednje pomene: New ...     74
http://dbpedia.org/resource/New_York_%28disambiguation%29	         http://dbpedia.org/property/abstract	         New York ima lahko naslednje pomene: New ...     74
http://dbpedia.org/resource/New_York_College	                         http://www.w3.org/2000/01/rdf-schema#comment	 There are several colleges of New York t ...     72
http://dbpedia.org/resource/New_York_College	                         http://dbpedia.org/property/abstract	         There are several colleges of New York t ...     72
No. of rows in result: 10

</pre>
    </div>
<br />
<br />
<a name="rdfsparul" />
    <h3>14.3.2. SPARUL -- an Update Language For RDF Graphs</h3>
     <a name="rdfsparulintro" />
    <h4>14.3.2.1. Introduction</h4>
       <p>Starting with version 5.0, Virtuoso supports the
<a href="http://jena.hpl.hp.com/~afs/SPARQL-Update.html">SPARQL/Update</a> extension to SPARQL.
This is sufficient for most of routine data manipulation operations. If the <strong>SPARQL_UPDATE</strong>
role is granted to user <strong>SPARQL</strong> user then data manipulation statements may be
executed via the SPARQL web service endpoint as well as by data querying.
       </p>
     <br />
     <a name="rdfsparulfunc" />
    <h4>14.3.2.2. Manage RDF Storage</h4>
       <p>Two functions allow the user to alter RDF storage by inserting or deleting all
triples listed in some vector. Both functions receive the IRI of the graph that should be altered and
a vector of triples that should be added or removed. The graph IRI can be either an IRI ID or a string.
The third optional argument controls the transactional behavior - the parameter value is
passed to the <a href="fn_log_enable.html">log_enable</a> function.
The return values of these functions are not defined and should not be used by applications.
       </p>
       <div>
      <pre class="programlisting">
create function DB.DBA.RDF_INSERT_TRIPLES (in graph_iri any, in triples any, in log_mode integer := null)
create function DB.DBA.RDF_DELETE_TRIPLES (in graph_iri any, in triples any, in log_mode integer := null)
       </pre>
    </div>
       <p>Simple operations may be faster if written as low-level SQL code instead of using SPARUL.
The use of SPARQL DELETE is unnecessary in cases where the better alternative is for the application to delete from RDF_QUAD
using simple SQL filters like:
       </p>
       <div>
      <pre class="programlisting">
DELETE FROM DB.DBA.RDF_QUAD
WHERE G = DB.DBA.RDF_MAKE_IID_OF_QNAME (
    &#39;http://local.virt/DAV/sparql_demo/data/data-xml/source-simple2/source-data-01.rdf&#39; );
       </pre>
    </div>
       <p>On the other hand, simple filters does not work when the search criteria refer to triples
that are affected by the modification. Consider a function that deletes all triples whose subjects
are nodes of type &#39;http://xmlns.com/foaf/0.1/Person&#39;. Type information is stored in triples that
will be deleted, so the simplest function is something like this:
       </p>
<div>
      <pre class="programlisting">
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 &lt;http://xmlns.com/foaf/0.1/Person&gt;
            } }
      ));
-- Step 2: delete all found triples
  pdata_array := dict_list_keys (pdata_dict, 1);
  RDF_DELETE_TRIPLES (foaf_graph, pdata_array);
};

DELETE_PERSONAL_DATA (
  &#39;http://local.virt/DAV/sparql_demo/data/data-xml/source-simple2/source-data-01.rdf&#39; );
</pre>
    </div>
       <p>From Virtuoso 5.0 onwards, applications can use SPARUL to do the same in a more convenient way:
       </p>
<div>
      <pre class="programlisting">
create procedure DELETE_PERSONAL_DATA (in foaf_graph varchar)
  {
  sparql delete { ?s ?p ?o }
      WHERE { graph ?:foaf_graph {
              ?s ?p ?o . ?s rdf:type &lt;http://xmlns.com/foaf/0.1/Person&gt;
            } }
};
</pre>
    </div>
     <br />
     <a name="rdfsparulexamples" />
    <h4>14.3.2.3. Examples</h4>
     <a name="rdfsparulexamples1" />
    <h5>14.3.2.3.1. Example for changing the graph</h5>
       <p>The graph to be changed may be specified by an option preceding of query, instead
of being specified in the &#39;insert into graph&#39; clause.
       </p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL DEFINE input:default-graph-uri &lt;http://mygraph.com&gt;
INSERT INTO &lt;http://mygraph.com&gt; { &lt;http://myopenlink.net/dataspace/Kingsley#this&gt; &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://rdfs.org/sioc/ns#User&gt; };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 20 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples2" />
    <h5>14.3.2.3.2. Example for delete graph equivalence</h5>
       <p>The following two statements are equivalent but the latter may work faster, especially
if there are many RDF views in the system or if the graph in question contains triples from RDF views.
Note that neither of these two statements affects data coming from RDF views.
</p>
<div>
      <pre class="programlisting">
SQL&gt; SPARQL DELETE FROM GRAPH &lt;http://mygraph.com&gt; { ?s ?p ?o } FROM &lt;http://mygraph&gt; WHERE { ?s ?p ?o };
callret-0
VARCHAR
_______________________________________________________________________________

Delete from &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 10 msec.

SQL&gt; SPARQL CLEAR GRAPH &lt;http://mygraph.com&gt;;
callret-0
VARCHAR
__________________________________________________________

Clear &lt;http://mygraph.com&gt; -- done

1 Rows. -- 10 msec.
</pre>
    </div>
   <p>DROP GRAPH is equivalent of CLEAR GRAPH. It requires initially the graph to be 
   	created explicitly.</p>
   <p>Note: All SPARQL commands should work via SPARUL ( i.e. executed from the /sparql endpoint) 
   	as soon as &quot;SPARQL&quot; user has &quot;SPARQL_UPDATE&quot; privilege.</p>
   <p>Assume the following sequence of commands to be executed from the /sparql endpoint:</p>
   <ul>
     <li>Create explicitly a graph:
<div>
          <pre class="programlisting">
CREATE GRAPH &lt;qq&gt;
	
callret-0
Create graph &lt;qq&gt; -- done
</pre>
        </div>     	
     </li>
     <li>If you don&#39;t know whether the graph is created explicitly or not, use <strong>DROP SILENT GRAPH</strong>:
<div>
          <pre class="programlisting">
DROP SILENT	GRAPH &lt;qq&gt; 
	
callret-0	
Drop silent graph &lt;qq&gt; -- done	
</pre>
        </div>     	
     </li>
     <li>If you know the graph is created explicitly, use <strong>DROP GRAPH</strong>:
<div>
          <pre class="programlisting">
DROP GRAPH &lt;qq&gt; 	
	
callret-0
Drop graph &lt;qq&gt; -- done	
</pre>
        </div>     	
     </li>
   </ul>
<br />
<a name="rdfsparulexamples3" />
    <h5>14.3.2.3.3. Example for deleting all triples for given subject</h5>
<p>The following statement deletes all records with &lt;http://myopenlink.net/dataspace/Kingsley#this&gt; as the subject:</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
DELETE FROM GRAPH &lt;http://mygraph.com&gt; { ?s ?p ?o }
 FROM &lt;http://mygraph.com&gt;
WHERE { ?s ?p ?o . filter ( ?s = &lt;http://myopenlink.net/dataspace/Kingsley#this&gt;) };
callret-0
VARCHAR
_______________________________________________________________________________

Delete from &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 10 msec.
</pre>
    </div>
<p>Alternatively, the statement can be written in this way:</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
DELETE FROM GRAPH &lt;http://mygraph.com&gt; { &lt;http://myopenlink.net/dataspace/Kingsley#this&gt; ?p ?o }
 FROM &lt;http://mygraph.com&gt;
WHERE { &lt;http://myopenlink.net/dataspace/Kingsley#this&gt; ?p ?o };
callret-0
VARCHAR
_______________________________________________________________________________

Delete from &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 10 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples4" />
    <h5>14.3.2.3.4. Example for INSERT statements equivalent</h5>
       <p>Keywords &#39;insert in&#39; and &#39;insert into&#39; are interchangeable in Virtuoso for backward
compatibility, but the SPARUL specification lists only &#39;insert into&#39;. For example,
the statements below are equivalent:
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL INSERT INTO GRAPH &lt;http://mygraph.com&gt; {  &lt;http://myopenlink.net/dataspace/Kingsley#this&gt;
                                                     &lt;http://rdfs.org/sioc/ns#id&gt;
                                                     &lt;Kingsley&gt; };
callret-0
VARCHAR
______________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 0 msec.
SQL&gt;SPARQL INSERT INTO GRAPH &lt;http://mygraph.com&gt; {  &lt;http://myopenlink.net/dataspace/Caroline#this&gt;
                                                     &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt;
                                                     &lt;http://rdfs.org/sioc/ns#User&gt; };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 0 msec.

-- and

SQL&gt;SPARQL INSERT IN GRAPH &lt;http://mygraph.com&gt; {  &lt;http://myopenlink.net/dataspace/Kingsley#this&gt;
                                                   &lt;http://rdfs.org/sioc/ns#id&gt;
                                                   &lt;Kingsley&gt; };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 10 msec.
SQL&gt;SPARQL INSERT IN GRAPH &lt;http://mygraph.com&gt; {  &lt;http://myopenlink.net/dataspace/Caroline#this&gt;
                                                   &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt;
                                                   &lt;http://rdfs.org/sioc/ns#User&gt; };
callret-0
VARCHAR
________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 1 triples -- done

1 Rows. -- 0 msec.

</pre>
    </div>
<br />
<a name="rdfsparulexamples5" />
    <h5>14.3.2.3.5. Example for various expressions usage</h5>
       <p>It is possible to use various expressions to calculate fields of new triples. This is
very convenient, even if not a part of the original specification.
       </p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL INSERT INTO GRAPH &lt;http://mygraph.com&gt; { ?s &lt;http://rdfs.org/sioc/ns#id&gt; `iri (bif:concat (str (?o), &quot;Idehen&quot;))` }
WHERE { ?s &lt;http://rdfs.org/sioc/ns#id&gt; ?o };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 4 triples -- done

1 Rows. -- 0 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples6" />
    <h5>14.3.2.3.6. Example for operator IN usage</h5>
<p>The example shows how to find which predicate/object pairs the following
subjects have in common and count the occurances:</p>
<div>
      <pre class="programlisting">
http://dbpedia.org/resource/Climate_change
http://dbpedia.org/resource/Disaster_risk_reduction
http://dbpedia.org/resource/Tanzania
http://dbpedia.org/resource/Capacity_building
http://dbpedia.org/resource/Poverty
http://dbpedia.org/resource/Construction
http://dbpedia.org/resource/Vulnerability
http://dbpedia.org/resource/Mount_Kilimanjaro
http://dbpedia.org/resource/Social_vulnerability
</pre>
    </div>
<p>The following query returns the desired results:</p>
<div>
      <pre class="programlisting">
SPARQL
SELECT ?s1 ?s2 COUNT (1)
WHERE
  {
    ?s1 ?p ?o .
    FILTER (?s1 IN (&lt;http://dbpedia.org/resource/Climate_change&gt;,
    &lt;http://dbpedia.org/resource/Disaster_risk_reduction&gt;,
    &lt;http://dbpedia.org/resource/Tanzania&gt;,
    &lt;http://dbpedia.org/resource/Capacity_building&gt;,
    &lt;http://dbpedia.org/resource/Poverty&gt;,
    &lt;http://dbpedia.org/resource/Construction&gt;,
    &lt;http://dbpedia.org/resource/Vulnerability&gt;,
    &lt;http://dbpedia.org/resource/Mount_Kilimanjaro&gt;,
    &lt;http://dbpedia.org/resource/Social_vulnerability&gt; ))
    ?s2 ?p ?o .
    FILTER (?s2 IN (&lt;http://dbpedia.org/resource/Climate_change&gt;,
    &lt;http://dbpedia.org/resource/Disaster_risk_reduction&gt;,
    &lt;http://dbpedia.org/resource/Tanzania&gt;,
    &lt;http://dbpedia.org/resource/Capacity_building&gt;,
    &lt;http://dbpedia.org/resource/Poverty&gt;,
    &lt;http://dbpedia.org/resource/Construction&gt;,
    &lt;http://dbpedia.org/resource/Vulnerability&gt;,
    &lt;http://dbpedia.org/resource/Mount_Kilimanjaro&gt;,
    &lt;http://dbpedia.org/resource/Social_vulnerability&gt; ))
    FILTER (?s1 != ?s2)
    FILTER (str(?s1) &lt; str (?s2))
  }
LIMIT 20
</pre>
    </div>
<p>The result of executing the query:</p>
<div>
      <pre class="programlisting">
s1  	                                         s2  	                                              callret-2
http://dbpedia.org/resource/Climate_change 	 http://dbpedia.org/resource/Tanzania 	              2
http://dbpedia.org/resource/Social_vulnerability http://dbpedia.org/resource/Vulnerability 	      1
http://dbpedia.org/resource/Mount_Kilimanjaro 	 http://dbpedia.org/resource/Poverty 	              1
http://dbpedia.org/resource/Mount_Kilimanjaro 	 http://dbpedia.org/resource/Tanzania 	              3
http://dbpedia.org/resource/Capacity_building 	 http://dbpedia.org/resource/Disaster_risk_reduction  1
http://dbpedia.org/resource/Poverty 	         http://dbpedia.org/resource/Tanzania 	              1
</pre>
    </div>
<p>You can also find live demo query results <a href="http://dbpedia.org/sparql?default-graph-uri=http%3A%2F%2Fdbpedia.org&amp;should-sponge=&amp;query=SELECT+%0D%0A%3Fs1+%3Fs2+count+%281%29+where+{%0D%0A%3Fs1+%3Fp+%3Fo+.%0D%0Afilter+%28%3Fs1+in+%28%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FClimate_change%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FDisaster_risk_reduction%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FTanzania%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FCapacity_building%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FPoverty%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FConstruction%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FVulnerability%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FMount_Kilimanjaro%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FSocial_vulnerability%3E+%29%29%0D%0A%3Fs2+%3Fp+%3Fo+.%0D%0Afilter+%28%3Fs2+in+%28%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FClimate_change%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FDisaster_risk_reduction%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FTanzania%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FCapacity_building%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FPoverty%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FConstruction%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FVulnerability%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FMount_Kilimanjaro%3E%2C%0D%0A%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FSocial_vulnerability%3E+%29%29%0D%0Afilter+%28%3Fs1+!%3D+%3Fs2%29%0D%0Afilter+%28str%28%3Fs1%29+%3C+str+%28%3Fs2%29%29%0D%0A}+limit+20&amp;format=html&amp;debug=on&amp;timeout=">here</a>
    </p>
  <div class="tip">
      <div class="tiptitle">See Also:</div>
    <p>
        <a href="sparqlextensions.html#rdfsparulexamples18">Example usage of IN operator for retrieving all triples for each entity.</a>
      </p>
  </div>
<br />
<a name="rdfsparulexamples7" />
    <h5>14.3.2.3.7. Example for Modify used as Update</h5>
       <p>&#39;Modify graph&#39; may be used as a form of &#39;update&#39; operation.
       </p>
<div>
      <pre class="programlisting">
-- update a graph with insert scoped on the same graph	
SQL&gt;SPARQL 
MODIFY GRAPH &lt;http://mygraph.com&gt; 
DELETE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o } 
INSERT { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type1&gt; ?o } 
FROM &lt;http://mygraph.com&gt; 	
WHERE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o };

-- update a graph with insert scoped on another graph	
SQL&gt;SPARQL 
MODIFY GRAPH &lt;http://mygraph.com&gt; 
DELETE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o } 
INSERT { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type1&gt; ?o } 
FROM &lt;http://mytest.com&gt; 	
WHERE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o };
	

-- update a graph with insert scoped over the whole RDF Quad Store
SQL&gt;SPARQL 
MODIFY GRAPH &lt;http://mygraph.com&gt; 
DELETE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o } 
INSERT { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type1&gt; ?o } 
WHERE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o };
	
-- update a graph with delete of particular tripple
SQL&gt;SPARQL
DELETE FROM GRAPH &lt;http://mygraph.com&gt; { &lt;http://myopenlink.net/dataspace/Caroline#this&gt; &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type1&gt; &lt;http://rdfs.org/sioc/ns#User&gt; };

</pre>
    </div>
<br />
<a name="rdfsparulexamples8" />
    <h5>14.3.2.3.8. Example for generating RDF information resource URI</h5>
       <p>The RDF information resource URI can be generated via a string expression.</p>
<ul>
  <li>Suppose there is a sample file kidehen.n3:
<div>
          <pre class="programlisting">
&lt;http://www.openlinksw.com/dataspace/kidehen@openlinksw.com#this&gt; &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://rdfs.org/sioc/ns#User&gt; .
&lt;http://www.openlinksw.com/dataspace/kidehen@openlinksw.com#this&gt; &lt;http://www.w3.org/2000/01/rdf-schema#label&gt; 	&quot;Kingsley&quot; .
&lt;http://www.openlinksw.com/dataspace/kidehen@openlinksw.com#this&gt; &lt;http://rdfs.org/sioc/ns#creator_of&gt; &lt;http://www.openlinksw.com/dataspace/kidehen@openlinksw.com/weblog/kidehen@openlinksw.com%27s%20BLOG%20%5B127%5D/1300&gt; .
</pre>
        </div>
</li>
  <li>Using Conductor UI go to Web Application Server and create folder, for ex. with name &quot;n3_collection&quot;</li>
  <li>Upload the &quot;n3_collection&quot; folder the file kidehen.n3</li>
  <li>Click properties for the folder &quot;n3_collection&quot; and set to be public readable in the Permissions section</li>
  <li>Check &quot;Apply changes to all subfolders and resources&quot;.</li>
  <li>Finally Click &quot;Update&quot;</li>
     <table class="figure" border="0" cellpadding="0" cellspacing="0">
     <tr>
      <td>
            <img alt="Generating RDF information resource URI" src="../images/ui/exmp1.png" />
      </td>
     </tr>
     <tr>
          <td>Figure: 14.3.2.3.8.1. Generating RDF information resource URI</td>
     </tr>
      </table>
  <li>To clear the graph execute:
<div>
          <pre class="programlisting">
SQL&gt;SPARQL CLEAR GRAPH &lt;http://mygraph.com&gt;;
callret-0
VARCHAR
_____________________________________________________________________

Clear &lt;http://mygraph.com&gt; -- done

1 Rows. -- 10 msec.
</pre>
        </div>
      </li>
   <li>To load the kidehen.n3 file execute:
<div>
          <pre class="programlisting">
SQL&gt;SPARQL
load bif:concat (&quot;http://&quot;, bif:registry_get(&quot;URIQADefaultHost&quot;), &quot;/DAV/n3_collection/kidehen.n3&quot;)
INTO GRAPH &lt;http://mygraph.com&gt;;
callret-0
VARCHAR
_______________________________________________________________________________

Load &lt;http://localhost:8890/DAV/n3_collection/kidehen.n3&gt; into graph &lt;http://mygraph.com&gt; -- done

1 Rows. -- 30 msec.
</pre>
        </div>
  </li>
  <li>In order to check the new inserted triples execute:
<div>
          <pre class="programlisting">
SQL&gt;SPARQL
SELECT *
FROM &lt;http://mygraph.com&gt;
WHERE
{
    ?s ?p ?o
}
;
s                                                                  p                                                   o
VARCHAR                                                            VARCHAR                                             VARCHAR
_______________________________________________________________________________

http://www.openlinksw.com/dataspace/kidehen@openlinksw.com#this    http://www.w3.org/1999/02/22-rdf-syntax-ns#type     http://rdfs.org/sioc/ns#User
http://www.openlinksw.com/dataspace/kidehen@openlinksw.com#this    http://rdfs.org/sioc/ns#creator_of                  http://www.openlinksw.com/dataspace/kidehen@openlinksw.com/weblog/kidehen@openlinksw.com%27s%20BLOG%20%5B127%5D/1300
http://www.openlinksw.com/dataspace/kidehen@openlinksw.com#this    http://www.w3.org/2000/01/rdf-schema#label          Kingsley

3 Rows. -- 10 msec.
</pre>
        </div>
  </li>
</ul>
<br />
<a name="rdfsparulexamples9" />
    <h5>14.3.2.3.9. Example for operations over a web service endpoint</h5>
       <p>Several operations can be sent to a web service endpoint as a single statement and
executed in sequence.
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
INSERT IN GRAPH &lt;http://mygraph.com&gt; { &lt;http://myopenlink.net/dataspace/Kingsley#this&gt;
                                       &lt;http://rdfs.org/sioc/ns#id&gt;
                                       &lt;Kingsley&gt; }
INSERT INTO GRAPH &lt;http://mygraph.com&gt; { &lt;http://myopenlink.net/dataspace/Caroline#this&gt;
                                         &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt;
                                         &lt;http://rdfs.org/sioc/ns#User&gt; }
INSERT INTO GRAPH &lt;http://mygraph.com&gt; { ?s &lt;http://rdfs.org/sioc/ns#id&gt; `iri (bif:concat (str (?o), &quot;Idehen&quot;))` }
WHERE { ?s &lt;http://rdfs.org/sioc/ns#id&gt; ?o };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://mygraph.com&gt;, 1 triples -- done
Insert into &lt;http://mygraph.com&gt;, 1 triples -- done
Insert into &lt;http://mygraph.com&gt;, 8 triples -- done
Commit -- done


1 Rows. -- 10 msec.

SQL&gt;SPARQL
MODIFY GRAPH &lt;http://mygraph.com&gt;
DELETE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o }
INSERT { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type1&gt; ?o }
FROM &lt;http://mygraph.com&gt;	
WHERE { ?s &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; ?o };

SQL&gt;DELETE FROM GRAPH &lt;http://mygraph.com&gt; { &lt;http://myopenlink.net/dataspace/Caroline#this&gt; &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type1&gt; &lt;http://rdfs.org/sioc/ns#User&gt; };

SQL&gt;SPARQL
load bif:concat (&quot;http://&quot;, bif:registry_get(&quot;URIQADefaultHost&quot;), &quot;/DAV/n3_collection/kidehen.n3&quot;) INTO GRAPH &lt;http://mygraph.com&gt;;
</pre>
    </div>
  <div class="tip">
      <div class="tiptitle">See Also:</div>
    <p>
        <a href="sparqlextensions.html#rdfsparulexamples7">Examples for Modify used as Update</a>
      </p>
  </div>
<br />
<a name="rdfsparulexamples10" />
    <h5>14.3.2.3.10. Example for Dropping graph</h5>
<p>When handling very large RDF data collections (e.g. 600 million triples ) loaded into Virtuoso
server as a single graph, the fastest operation to drop the graph is:</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL CLEAR GRAPH &lt;http://mygraph.com&gt;;
callret-0
VARCHAR
______________________________________________________________________________

Clear &lt;http://mygraph.com&gt; -- done

1 Rows. -- 10 msec.
</pre>
    </div>
<p>The operation can be speeded up by executing log_enable (0) or even log_enable (2) beforehand,
and log_enable(1) after it completes.
</p>
<br />
<a name="rdfsparulexamples11" />
    <h5>14.3.2.3.11. Example for testing Graph Equality</h5>
<p>The procedure below keeps simple cases of graphs with bnodes:</p>
<ol>
      <li>First it compares all triples without bnodes</li>
      <li>Then it iteratively establishes equivalences between bnodes that
are directly and unambiguously connected to equivalent vertexes by identical predicates.</li>
    </ol>
<div>
      <pre class="programlisting">
-- Fast Approximate RDF Graph Equivalence Test
-- (C) 2009 OpenLink Software
-- License: GNU General Public License (only version 2 of the license).
-- No warranty, even implied warranty

-- This compares the content of triple dictionaries \c dict1 and \c dict2,
-- returns NULL if no difference found (with bnode equivalence in mind),
-- returns description of a difference otherwise.
-- The function is experimental (note suffix _EXP), so no accurate QA is made.
-- Some version of the function may be inserted later in OpenLink Virtuoso Server under some different name.
create function DB.DBA.RDF_TRIPLE_DICTS_DIFFER_EXP (
  in dict1 any, --- Triple dictionary, traditional, (vectors of S, P, O are keys, any non-nulls are values)
  in dict2 any, --- Second triple dictionary, like to \c dict1
  in accuracy integer,	--- Accuracy, 0 if no bnodes expected, 1 if &quot;convenient&quot; trees with intermediate bnodes expected, 2 and more are not yet implemented
  in equiv_map any := null, --- If specified then it contain mapping from IRI_IDs of bnodes of \c dict1 to equivalent IRI_IDs of bnodes of \c dict1.
-- It can be extended during the run so use dict_duplicate() before call if needed.
  in equiv_rev any := null --- If specified then it is an inverted dictionary of \c equiv_map (this time \c dict2 bnodes are keys and \c dict1 bnodes are values)
  )
{
  declare dict_size1, dict_size2 integer;
  declare old_dirt_level, dirt_level integer;
  declare ctr, tailctr, sp_made_new_equiv integer;
  declare array1, array2, dict2_sp, dict1_op, dict2_op, array1_op any;
  dict_size1 := dict_size (dict1);
  dict_size2 := dict_size (dict2);
  dict2 := dict_duplicate (dict2);
  if (dict_size1 &lt;&gt; dict_size2)
    return &#39;Sizes differ&#39;;
  if (equiv_map is null)
    {
      equiv_map := dict_new (dict_size1);
      equiv_rev := dict_new (dict_size1);
    }
  old_dirt_level := dict_size1 - dict_size (equiv_map);
  array1 := dict_list_keys (dict1, 0);
next_loop:
-- Step 1: removing triples with all three items matched
  ctr := dict_size1-1;
  while (ctr &gt;= 0)
    {
      declare s_in_1, o_in_1, s_in_2, o_in_2, triple_in_2 any;
      s_in_1 := array1[ctr][0];
      o_in_1 := array1[ctr][2];
      if (is_bnode_iri_id (s_in_1))
        {
          s_in_2 := dict_get (equiv_map, s_in_1, null);
          if (s_in_2 is null)
            goto next_full_eq_check;
        }
      else
        s_in_2 := s_in_1;
      if (is_bnode_iri_id (o_in_1))
        {
          o_in_2 := dict_get (equiv_map, o_in_1, null);
          if (o_in_2 is null)
            goto next_full_eq_check;
        }
      else
        o_in_2 := o_in_1;
      triple_in_2 := vector (s_in_2, array1[ctr][1], o_in_2);
      if (dict_get (dict2, triple_in_2, null) is null)
        return vector (array1[ctr], &#39; is in first, &#39;, triple_in_2, &#39; is missing in second&#39;);
      dict_remove (dict2, triple_in_2);
      if (ctr &lt; dict_size1-1)
        array1[ctr] := array1[dict_size1-1];
      dict_size1 := dict_size1-1;
next_full_eq_check:
      ctr := ctr-1;
    }
-- Step 1 end, garbage truncated:
  if ((0 = dict_size1) or (0 = accuracy))
    return null;
  if (dict_size1 &lt; length (array1))
    array1 := subseq (array1, 0, dict_size1);
  if (dict_size (dict2) &lt;&gt; dict_size1)
    signal (&#39;OBLOM&#39;, &#39;Internal error: sizes of graphs suddenly differ&#39;);
-- Step 2: establishing equivs between not-yet-coupled bnodes that are values of functional predicates of coupled subjects
  sp_made_new_equiv := 0;
  dict2_sp := dict_new (dict_size1);
  array2 := dict_list_keys (dict2, 0);
  for (ctr := dict_size1-1; ctr &gt;= 0; ctr := ctr-1)
    {
      declare sp2, o2, prev_uniq_o2 any;
      sp2 := vector (array2[ctr][0], array2[ctr][1]);
      prev_uniq_o2 := dict_get (dict2_sp, sp2, null);
      if (prev_uniq_o2 is null)
        {
          o2 := array2[ctr][2];
          if (is_bnode_iri_id (o2))
            dict_put (dict2_sp, sp2, o2);
          else
            dict_put (dict2_sp, sp2, #i0);
        }
      else if (prev_uniq_o2 &lt;&gt; #i0)
        dict_put (dict2_sp, sp2, #i0);
    }
  rowvector_subj_sort (array1, 0, 1);
  rowvector_subj_sort (array1, 1, 1);
  rowvector_subj_sort (array2, 1, 1);
  ctr := 0;
  while (ctr &lt; dict_size1)
    {
      declare s_in_1, o_in_1, s_in_2, o_in_2, o_in_dict2_sp, o_in_dict2_sp_in_1 any;
      tailctr := ctr+1;
      if (array1[ctr][1] &lt;&gt; array2[ctr][1])
        {
          if (array1[ctr][1] &gt; array2[ctr][1])
            return vector (&#39;Cardinality of predicate &#39;, array2[ctr][1], &#39; is greater in second than in first&#39;);
          else
            return vector (&#39;Cardinality of predicate &#39;, array1[ctr][1], &#39; is greater in first than in second&#39;);
        }
      while ((tailctr &lt; dict_size1) and
        (array1[tailctr][0] = array1[ctr][0]) and
        (array1[tailctr][1] = array1[ctr][1]) )
        tailctr := tailctr+1;
      if ((tailctr - ctr) &gt; 1)
        goto next_sp_check;
      o_in_1 := array1[ctr][2];
      if (not is_bnode_iri_id (o_in_1))
        goto next_sp_check;
      o_in_2 := dict_get (equiv_map, o_in_1, null);
      if (o_in_2 is not null)
        goto next_sp_check;
      s_in_1 := array1[ctr][0];
      if (is_bnode_iri_id (s_in_1))
        {
          s_in_2 := dict_get (equiv_map, s_in_1, null);
          if (s_in_2 is null)
            goto next_sp_check;
        }
      else
        s_in_2 := s_in_1;
      o_in_dict2_sp := dict_get (dict2_sp, vector (s_in_2, array1[ctr][1]), null);
      if (o_in_dict2_sp is null)
        return vector (vector (s_in_1, array1[ctr][1], o_in_1), &#39; is unique SP in first, &#39;, vector (s_in_2, array1[ctr][1]), &#39; is missing SP in second&#39;);
      if (o_in_dict2_sp = #i0)
        return vector (vector (s_in_1, array1[ctr][1], o_in_1), &#39; is unique SP in first, &#39;, vector (s_in_2, array1[ctr][1]), &#39; is not unique SP-to-bnode in second&#39;);
      o_in_dict2_sp_in_1 := dict_get (equiv_rev, o_in_dict2_sp, null);
      if (o_in_dict2_sp_in_1 is not null)
  {
          if (o_in_dict2_sp_in_1 = o_in_1)
            goto next_sp_check;
          return vector (vector (s_in_1, array1[ctr][1], o_in_1), &#39; is unique SP in first, &#39;, vector (s_in_2, array1[ctr][1], o_in_dict2_sp), &#39; is unique SP in second but &#39;, o_in_dict2_sp, &#39; rev-equiv to &#39;, o_in_dict2_sp_in_1);
        }
      dict_put (equiv_map, o_in_1, o_in_dict2_sp);
      dict_put (equiv_rev, o_in_dict2_sp, o_in_1);
      sp_made_new_equiv := sp_made_new_equiv + 1;
next_sp_check:
      ctr := tailctr;
    }
  dict_list_keys (dict2_sp, 2);
-- Step 2 end
  if (sp_made_new_equiv * 10 &gt; dict_size1)
    goto next_loop; -- If dictionary is noticeably extended then it&#39;s worth to remove more triples before continue.
-- Step 3: establishing equivs between not-yet-coupled bnodes that are subjects of inverse functional properties with coupled objects.
  dict1_op := dict_new (dict_size1);
  for (ctr := dict_size1-1; ctr &gt;= 0; ctr := ctr-1)
    {
      declare op1, s1, prev_uniq_s1 any;
      op1 := vector (array1[ctr][2], array1[ctr][1]);
      prev_uniq_s1 := dict_get (dict1_op, op1, null);
      if (prev_uniq_s1 is null)
        {
          s1 := array1[ctr][0];
          if (is_bnode_iri_id (s1))
            dict_put (dict1_op, op1, s1);
          else
            dict_put (dict1_op, op1, #i0);
        }
      else if (prev_uniq_s1 &lt;&gt; #i0)
        dict_put (dict1_op, op1, #i0);
    }
  array1_op := dict_to_vector (dict1_op, 2);
  dict2_op := dict_new (dict_size1);
  for (ctr := dict_size1-1; ctr &gt;= 0; ctr := ctr-1)
    {
      declare op2, s2, prev_uniq_s2 any;
      op2 := vector (array2[ctr][2], array2[ctr][1]);
      prev_uniq_s2 := dict_get (dict2_op, op2, null);
      if (prev_uniq_s2 is null)
        {
          s2 := array2[ctr][0];
          if (is_bnode_iri_id (s2))
            dict_put (dict2_op, op2, s2);
          else
            dict_put (dict2_op, op2, #i0);
        }
      else if (prev_uniq_s2 &lt;&gt; #i0)
        dict_put (dict2_op, op2, #i0);
    }
  ctr := length (array1_op) - 2;
  while (ctr &gt;= 0)
    {
      declare o_in_1, s_in_1, o_in_2, s_in_2, s_in_dict2_op, s_in_dict2_op_in_1 any;
      s_in_1 := array1_op[ctr+1];
      if (not is_bnode_iri_id (s_in_1))
        goto next_op_check;
      s_in_2 := dict_get (equiv_map, s_in_1, null);
      if (s_in_2 is not null)
        goto next_op_check;
      o_in_1 := array1_op[ctr][0];
      if (is_bnode_iri_id (o_in_1))
        {
          o_in_2 := dict_get (equiv_map, o_in_1, null);
          if (o_in_2 is null)
            goto next_op_check;
        }
      else
        o_in_2 := o_in_1;
      s_in_dict2_op := dict_get (dict2_op, vector (o_in_2, array1_op[ctr][1]), null);
      if (s_in_dict2_op is null)
        return vector (vector (s_in_1, array1_op[ctr][1], o_in_1), &#39; is unique OP in first, &#39;, vector (o_in_2, array1_op[ctr][1]), &#39; is missing OP in second&#39;);
      if (s_in_dict2_op = #i0)
        return vector (vector (s_in_1, array1_op[ctr][1], o_in_1), &#39; is unique OP in first, &#39;, vector (o_in_2, array1_op[ctr][1]), &#39; is not unique OP-to-bnode in second&#39;);
      s_in_dict2_op_in_1 := dict_get (equiv_rev, s_in_dict2_op, null);
      if (s_in_dict2_op_in_1 is not null)
        {
          if (s_in_dict2_op_in_1 = s_in_1)
            goto next_op_check;
          return vector (vector (s_in_1, array1_op[ctr][1], o_in_1), &#39; is unique OP in first, &#39;, vector (s_in_dict2_op, array1[ctr][1], o_in_2), &#39; is unique OP in second but &#39;, s_in_dict2_op, &#39; rev-equiv to &#39;, s_in_dict2_op_in_1);
        }
      dict_put (equiv_map, s_in_1, s_in_dict2_op);
      dict_put (equiv_rev, s_in_dict2_op, s_in_1);
next_op_check:
      ctr := ctr - 2;
    }
  dict_list_keys (dict2_op, 2);
-- Step 3 end
  dirt_level := dict_size1 - dict_size (equiv_map);
  if (dirt_level &gt;= old_dirt_level)
    return vector (vector (array1[0][0], array1[0][1], array1[0][2]), &#39; has no matches in second with the requested accuracy&#39;);
  old_dirt_level := dirt_level;
  goto next_loop;
}
;

create function DB.DBA.RDF_GRAPHS_DIFFER_EXP (in g1_uri varchar, in g2_uri varchar, in accuracy integer)
{
  return DB.DBA.RDF_TRIPLE_DICTS_DIFFER_EXP (
    (sparql define output:valmode &quot;LONG&quot; construct { ?s ?p ?o } where { graph `iri(?:g1_uri)` { ?s ?p ?o }}),
    (sparql define output:valmode &quot;LONG&quot; construct { ?s ?p ?o } where { graph `iri(?:g2_uri)` { ?s ?p ?o }}),
    accuracy );
}
;

-- The rest of file contains some minimal tests.

set verbose off;
set banner off;
set types off;

create function DB.DBA.DICT_EXTEND_WITH_KEYS (in dict any, in keys any)
  {
  if (dict is null)
    dict := dict_new (length (keys));
  foreach (any k in keys) do
    dict_put (dict, k, 1);
  return dict;
}
;

create function DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP (in title varchar, in should_differ integer, in v1 any, in v2 any, in accuracy integer)
{
  declare d1, d2, eqm, eqr, differ_status any;
  d1 := DB.DBA.DICT_EXTEND_WITH_KEYS (null, v1);
  d2 := DB.DBA.DICT_EXTEND_WITH_KEYS (null, v2);
  eqm := dict_new (10);
  eqr := dict_new (10);
  dbg_obj_princ (&#39;===== &#39; || title);
  differ_status := DB.DBA.RDF_TRIPLE_DICTS_DIFFER_EXP (d1, d2, accuracy, eqm, eqr);
  dbg_obj_princ (&#39;Result: &#39;, differ_status);
  if (0 &lt; dict_size (eqm))
  dbg_obj_princ (&#39;Equivalence map: &#39;, dict_to_vector (eqm, 0));
  dbg_obj_princ (&#39;Equivalence rev: &#39;, dict_to_vector (eqr, 0));
  return sprintf (&#39;%s: %s&#39;,
    case when (case when should_differ then equ (0, isnull (differ_status)) else isnull (differ_status) end) then &#39;PASSED&#39; else &#39;***FAILED&#39; end,
    title );
}
;

create function DB.DBA.TEST_RDF_GRAPHS_DIFFER_EXP (in title varchar, in should_differ integer, in g1_uri varchar, in g2_uri varchar, in accuracy integer)
{
  declare differ_status any;
  differ_status := DB.DBA.RDF_GRAPHS_DIFFER_EXP (g1_uri, g2_uri, accuracy);
  dbg_obj_princ (&#39;Result: &#39;, differ_status);
  return sprintf (&#39;%s: %s&#39;,
    case when (case when should_differ then equ (0, isnull (differ_status)) else isnull (differ_status) end) then &#39;PASSED&#39; else &#39;***FAILED&#39; end,
    title );
}
;

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;Identical graphs&#39;, 0,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i200, 1) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i200, 1) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;Sizes differ&#39;, 1,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i200, 1) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i200, 1),
    vector (#i101, #i201, #i301) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;Cardinality of a pred differ&#39;, 1,
  vector (
    vector (#i100, #i200, #ib300),
    vector (#i101, #i200, #ib302),
    vector (#i103, #i201, #ib304),
    vector (#ib109, #i200, #ib109) ),
  vector (
    vector (#i100, #i200, #ib301),
    vector (#i101, #i200, #ib303),
    vector (#i103, #i201, #ib305),
    vector (#ib109, #i201, #ib109) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;Bnodes in O with unique SP (equiv)&#39;, 0,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib301),
    vector (#i101, #i201, #ib301),
    vector (#i102, #i202, #ib303),
    vector (#ib303, #i204, #i306),
    vector (#ib303, #i205, #ib305),
    vector (#i100, #i200, 1) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib302),
    vector (#i101, #i201, #ib302),
    vector (#i102, #i202, #ib304),
    vector (#ib304, #i204, #i306),
    vector (#ib304, #i205, #ib306),
    vector (#i100, #i200, 1) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;Bnodes in O with unique SP (diff 1)&#39;, 1,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib301),
    vector (#i102, #i202, #ib303),
    vector (#ib303, #i204, #i306),
    vector (#ib303, #i205, #ib305),
    vector (#i100, #i200, 1) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib302),
    vector (#i102, #i202, #ib304),
    vector (#ib304, #i204, #i306),
    vector (#ib304, #i205, #i306),
    vector (#i100, #i200, 1) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;Bnodes in O with unique SP (diff 2)&#39;, 1,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib301),
    vector (#i102, #i202, #ib303),
    vector (#ib303, #i204, #i306),
    vector (#ib303, #i205, #ib305),
    vector (#i100, #i200, 1) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib302),
    vector (#i102, #i202, #ib304),
    vector (#ib304, #i204, #i306),
    vector (#ib304, #i205, #ib304),
    vector (#i100, #i200, 1) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;foaf-like-mix (equiv)&#39;, 0,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib301),
    vector (#i100, #i201, #ib303),
    vector (#i100, #i201, #ib305),
    vector (#i100, #i201, #ib307),
    vector (#ib301, #i202, &#39;Anna&#39;),
    vector (#ib303, #i202, &#39;Anna&#39;),
    vector (#ib305, #i202, &#39;Brigit&#39;),
    vector (#ib307, #i202, &#39;Clara&#39;),
    vector (#ib301, #i203, &#39;ann@ex.com&#39;),
    vector (#ib303, #i203, &#39;ann@am.com&#39;),
    vector (#ib305, #i203, &#39;root@ple.com&#39;),
    vector (#ib307, #i203, &#39;root@ple.com&#39;) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib302),
    vector (#i100, #i201, #ib304),
    vector (#i100, #i201, #ib306),
    vector (#i100, #i201, #ib308),
    vector (#ib302, #i202, &#39;Anna&#39;),
    vector (#ib304, #i202, &#39;Anna&#39;),
    vector (#ib306, #i202, &#39;Brigit&#39;),
    vector (#ib308, #i202, &#39;Clara&#39;),
    vector (#ib302, #i203, &#39;ann@ex.com&#39;),
    vector (#ib304, #i203, &#39;ann@am.com&#39;),
    vector (#ib306, #i203, &#39;root@ple.com&#39;),
    vector (#ib308, #i203, &#39;root@ple.com&#39;) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;foaf-like-mix (swapped names)&#39;, 1,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib301),
    vector (#i100, #i201, #ib303),
    vector (#i100, #i201, #ib305),
    vector (#i100, #i201, #ib307),
    vector (#ib301, #i202, &#39;Anna&#39;),
    vector (#ib303, #i202, &#39;Anna&#39;),
    vector (#ib305, #i202, &#39;Brigit&#39;),
    vector (#ib307, #i202, &#39;Clara&#39;),
    vector (#ib301, #i203, &#39;ann@ex.com&#39;),
    vector (#ib303, #i203, &#39;ann@am.com&#39;),
    vector (#ib305, #i203, &#39;root@ple.com&#39;),
    vector (#ib307, #i203, &#39;root@ple.com&#39;) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib302),
    vector (#i100, #i201, #ib304),
    vector (#i100, #i201, #ib306),
    vector (#i100, #i201, #ib308),
    vector (#ib302, #i202, &#39;Anna&#39;),
    vector (#ib304, #i202, &#39;Brigit&#39;),
    vector (#ib306, #i202, &#39;Anna&#39;),
    vector (#ib308, #i202, &#39;Clara&#39;),
    vector (#ib302, #i203, &#39;ann@ex.com&#39;),
    vector (#ib304, #i203, &#39;ann@am.com&#39;),
    vector (#ib306, #i203, &#39;root@ple.com&#39;),
    vector (#ib308, #i203, &#39;root@ple.com&#39;) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;foaf-like-mix (swapped names)&#39;, 1,
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib301),
    vector (#i100, #i201, #ib303),
    vector (#i100, #i201, #ib305),
    vector (#i100, #i201, #ib307),
    vector (#ib301, #i202, &#39;Anna&#39;),
    vector (#ib303, #i202, &#39;Anna&#39;),
    vector (#ib305, #i202, &#39;Brigit&#39;),
    vector (#ib307, #i202, &#39;Clara&#39;),
    vector (#ib301, #i203, &#39;ann@ex.com&#39;),
    vector (#ib303, #i203, &#39;ann@am.com&#39;),
    vector (#ib305, #i203, &#39;root@ple.com&#39;),
    vector (#ib307, #i203, &#39;root@ple.com&#39;) ),
  vector (
    vector (#i100, #i200, #i300),
    vector (#i100, #i201, #ib302),
    vector (#i100, #i201, #ib304),
    vector (#i100, #i201, #ib306),
    vector (#i100, #i201, #ib308),
    vector (#ib302, #i202, &#39;Anna&#39;),
    vector (#ib304, #i202, &#39;Brigit&#39;),
    vector (#ib306, #i202, &#39;Anna&#39;),
    vector (#ib308, #i202, &#39;Clara&#39;),
    vector (#ib302, #i203, &#39;ann@ex.com&#39;),
    vector (#ib304, #i203, &#39;ann@am.com&#39;),
    vector (#ib306, #i203, &#39;root@ple.com&#39;),
    vector (#ib308, #i203, &#39;root@ple.com&#39;) ),
  100
);

select DB.DBA.TEST_RDF_TRIPLE_DICTS_DIFFER_EXP ( &#39;bnodes only (equiv that can not be proven)&#39;, 1,
  vector (
    vector (#ib101, #i200, #ib103),
    vector (#ib103, #i201, #ib101) ),
  vector (
    vector (#ib102, #i200, #ib104),
    vector (#ib104, #i201, #ib102) ),
  100
);

sparql clear graph &lt;http://GraphCmp/One&gt;;

TTLP (&#39;@prefix foaf: &lt;http://i-dont-remember-it&gt; .
_:me
	a foaf:Person ;
	foaf:knows	[ foaf:nick &quot;oerling&quot; ; foaf:title &quot;Mr.&quot; ; foaf:sha1 &quot;abra&quot; ] ;
	foaf:knows	[ foaf:nick &quot;kidehen&quot; ; foaf:title &quot;Mr.&quot; ; foaf:sha1 &quot;bra&quot; ] ;
	foaf:knows	[ foaf:nick &quot;aldo&quot; ; foaf:title &quot;Mr.&quot; ; foaf:sha1 &quot;cada&quot; ] .&#39;,
&#39;&#39;, &#39;http://GraphCmp/One&#39; );

sparql clear graph &lt;http://GraphCmp/Two&gt;;
TTLP (&#39;@prefix foaf: &lt;http://i-dont-remember-it&gt; .
_:iv
	foaf:knows	[ foaf:title &quot;Mr.&quot; ; foaf:sha1 &quot;cada&quot; ; foaf:nick &quot;aldo&quot; ] ;
	foaf:knows	[ foaf:sha1 &quot;bra&quot; ; foaf:title &quot;Mr.&quot; ; foaf:nick &quot;kidehen&quot; ] ;
	foaf:knows	[ foaf:nick &quot;oerling&quot; ; foaf:sha1 &quot;abra&quot; ; foaf:title &quot;Mr.&quot; ] ;
	a foaf:Person .&#39;,
&#39;&#39;, &#39;http://GraphCmp/Two&#39; );

select DB.DBA.TEST_RDF_GRAPHS_DIFFER_EXP ( &#39;nonexisting graphs (equiv, of course)&#39;, 0,
  &#39;http://GraphCmp/NoSuch&#39;, &#39;http://GraphCmp/NoSuch&#39;,
  100 );

select DB.DBA.TEST_RDF_GRAPHS_DIFFER_EXP ( &#39;throughout test on foafs (equiv)&#39;, 0,
  &#39;http://GraphCmp/One&#39;, &#39;http://GraphCmp/Two&#39;,
  100 );

</pre>
    </div>
<br />
<a name="rdfsparulexamples12" />
    <h5>14.3.2.3.12. Example for Adding triples to graph</h5>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL 
INSERT INTO GRAPH &lt;http://BookStore.com&gt;
{ &lt;http://www.dajobe.org/foaf.rdf#i&gt; &lt;http://purl.org/dc/elements/1.1/title&gt;  &quot;SPARQL and RDF&quot; .
  &lt;http://www.dajobe.org/foaf.rdf#i&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;1999-01-01T00:00:00&gt;.
  &lt;http://www.w3.org/People/Berners-Lee/card#i&gt; &lt;http://purl.org/dc/elements/1.1/title&gt; &quot;Design notes&quot; .
  &lt;http://www.w3.org/People/Berners-Lee/card#i&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2001-01-01T00:00:00&gt;.
  &lt;http://www.w3.org/People/Connolly/#me&gt; &lt;http://purl.org/dc/elements/1.1/title&gt; &quot;Fundamentals of Compiler Design&quot; .
  &lt;http://www.w3.org/People/Connolly/#me&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2002-01-01T00:00:00&gt;. };
callret-0
VARCHAR
_________________________________________________________________

Insert into &lt;http://BookStore.com&gt;, 6 triples -- done

1 Rows. -- 0 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples13" />
    <h5>14.3.2.3.13. Example for Updating triples from graph</h5>
<p>A SPARQL/Update request that contains a triple to be deleted and a triple to be added (used here to correct a book title).
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
MODIFY GRAPH &lt;http://BookStore.com&gt;
DELETE
 { &lt;http://www.w3.org/People/Connolly/#me&gt;  &lt;http://purl.org/dc/elements/1.1/title&gt;  &quot;Fundamentals of Compiler Design&quot; }
INSERT
 { &lt;http://www.w3.org/People/Connolly/#me&gt;  &lt;http://purl.org/dc/elements/1.1/title&gt;  &quot;Fundamentals&quot; };
callret-0
VARCHAR
_______________________________________________________________________________

Modify &lt;http://BookStore.com&gt;, delete 1 and insert 1 triples -- done

1 Rows. -- 20 msec.
</pre>
    </div>
  <div class="tip">
      <div class="tiptitle">See Also:</div>
    <p>
        <a href="sparqlextensions.html#rdfsparulexamples7">Examples for Modify used as Update</a>
      </p>
  </div>
<br />
<a name="rdfsparulexamples14" />
    <h5>14.3.2.3.14. Example for Deleting triples from graph</h5>
<p>The example below has a request to delete all records of old books (dated before year 2000)
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
PREFIX dc:  &lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt;
DELETE FROM GRAPH &lt;http://BookStore.com&gt; { ?book ?p ?v }
WHERE
  { GRAPH  &lt;http://BookStore.com&gt;
   { ?book dc:date ?date
     FILTER ( xsd:dateTime(?date) &lt; xsd:dateTime(&quot;2000-01-01T00:00:00&quot;)).
    ?book ?p ?v.
   }
  };
_______________________________________________________________________________

Delete from &lt;http://BookStore.com&gt;, 6 triples -- done

1 Rows. -- 10 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples15" />
    <h5>14.3.2.3.15. Example for Copying triples from one graph to another</h5>
<p>The next snippet copies records from one named graph to another based on a pattern:
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL clear graph &lt;http://BookStore.com&gt;;
SQL&gt;SPARQL clear graph &lt;http://NewBookStore.com&gt;;
SQL&gt;SPARQL
insert in graph &lt;http://BookStore.com&gt;
  {
    &lt;http://www.dajobe.org/foaf.rdf#i&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;1999-04-01T00:00:00&gt; .
    &lt;http://www.w3.org/People/Berners-Lee/card#i&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;1998-05-03T00:00:00&gt; .
    &lt;http://www.w3.org/People/Connolly/#me&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2001-02-08T00:00:00&gt;
  };
SQL&gt;SPARQL
PREFIX dc:  &lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt;
INSERT INTO GRAPH &lt;http://NewBookStore.com&gt; { ?book ?p ?v }
WHERE
  { GRAPH  &lt;http://BookStore.com&gt;
   { ?book dc:date ?date
     FILTER ( xsd:dateTime(?date) &gt; xsd:dateTime(&quot;2000-01-01T00:00:00&quot;)).
     ?book ?p ?v.
   }
  };
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://NewBookStore.com&gt;, 6 triples -- done

1 Rows. -- 30 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples16" />
    <h5>14.3.2.3.16. Example for Moving triples from one graph to another</h5>
<p>This example moves records from one named graph to another named graph based on a pattern:
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
PREFIX dc:  &lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt;

INSERT INTO GRAPH &lt;http://NewBookStore.com&gt;
 { ?book ?p ?v }
WHERE
  { GRAPH  &lt;http://BookStore.com&gt;
     { ?book dc:date ?date .
       FILTER ( xsd:dateTime(?date) &gt; xsd:dateTime(&quot;2000-01-01T00:00:00&quot;)).
       ?book ?p ?v.
     }
  };
_______________________________________________________________________________

Insert into &lt;http://NewBookStore.com&gt;, 6 triples -- done

1 Rows. -- 10 msec.

SQL&gt;SPARQL
PREFIX dc:  &lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt;
DELETE FROM GRAPH &lt;http://BookStore.com&gt;
 { ?book ?p ?v }
WHERE
  { GRAPH  &lt;http://BookStore.com&gt;
      { ?book dc:date ?date .
        FILTER ( xsd:dateTime(?date) &gt; xsd:dateTime(&quot;2000-01-01T00:00:00&quot;)).
        ?book ?p ?v.
      }
  };
_______________________________________________________________________________

Delete from &lt;http://BookStore.com&gt;, 3 triples -- done

1 Rows. -- 10 msec.
</pre>
    </div>
<br />
<a name="rdfsparulexamples17" />
    <h5>14.3.2.3.17. Example for BBC SPARQL Collection</h5>
<div>
      <pre class="programlisting">
## All programmes related to James Bond:
PREFIX po: &lt;http://purl.org/ontology/po/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
SELECT ?uri ?label
WHERE
  {
    ?uri po:category
      &lt;http://www.bbc.co.uk/programmes/people/bmFtZS9ib25kLCBqYW1lcyAobm8gcXVhbGlmaWVyKQ#person&gt; ;
    rdfs:label ?label.
   }
</pre>
    </div>

<div>
      <pre class="programlisting">
## Find all Eastenders broadcasta after 2009-01-01,
## along with the broadcast version &amp; type
PREFIX event: &lt;http://purl.org/NET/c4dm/event.owl#&gt;
PREFIX tl: &lt;http://purl.org/NET/c4dm/timeline.owl#&gt;
PREFIX po: &lt;http://purl.org/ontology/po/&gt;
PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt;
SELECT ?version_type ?broadcast_start
WHERE
  {
    &lt;http://www.bbc.co.uk/programmes/b006m86d#programme&gt; po:episode ?episode .
    ?episode po:version ?version .
    ?version a ?version_type .
    ?broadcast po:broadcast_of ?version .
    ?broadcast event:time ?time .
    ?time tl:start ?broadcast_start .
    FILTER ( (?version_type != &lt;http://purl.org/ontology/po/Version&gt;)
    &amp;&amp; (?broadcast_start &gt; &quot;2009-01-01T00:00:00Z&quot;^^xsd:dateTime) )
  }
</pre>
    </div>

<div>
      <pre class="programlisting">
## Find all programmes that featured both the Foo Fighters and Al Green
PREFIX po: &lt;http://purl.org/ontology/po/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX mo: &lt;http://purl.org/ontology/mo/&gt;
PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX event: &lt;http://purl.org/NET/c4dm/event.owl#&gt;
PREFIX tl: &lt;http://purl.org/NET/c4dm/timeline.owl#&gt;
PREFIX owl: &lt;http://www.w3.org/2002/07/owl#&gt;
SELECT DISTINCT ?programme ?label
WHERE
  {
    ?event1 po:track ?track1 .
    ?track1 foaf:maker ?maker1 .
    ?maker1 owl:sameAs
       &lt;http://www.bbc.co.uk/music/artists/67f66c07-6e61-4026-ade5-7e782fad3a5d#artist&gt; .
    ?event2 po:track ?track2 .
    ?track2 foaf:maker ?maker2 .
    ?maker2 owl:sameAs
       &lt;http://www.bbc.co.uk/music/artists/fb7272ba-f130-4f0a-934d-6eeea4c18c9a#artist&gt; .
    ?event1 event:time ?t1 .
    ?event2 event:time ?t2 .
    ?t1 tl:timeline ?tl .
    ?t2 tl:timeline ?tl .
    ?version po:time ?t .
    ?t tl:timeline ?tl .
    ?programme po:version ?version .
    ?programme rdfs:label ?label .
  }
</pre>
    </div>

<div>
      <pre class="programlisting">
## Get short synopsis&#39; of EastEnders episodes
PREFIX po: &lt;http://purl.org/ontology/po/&gt;
PREFIX dc: &lt;http://purl.org/dc/elements/1.1/&gt;
SELECT ?t ?o
WHERE
{
    &lt;http://www.bbc.co.uk/programmes/b006m86d#programme&gt; po:episode ?e .
    ?e a po:Episode .
    ?e po:short_synopsis ?o .
    ?e dc:title ?t
  }
</pre>
    </div>

<div>
      <pre class="programlisting">
## Get short synopsis&#39; of EastEnders episodes (with graph)
PREFIX po: &lt;http://purl.org/ontology/po/&gt;
PREFIX dc: &lt;http://purl.org/dc/elements/1.1/&gt;
SELECT ?g ?t ?o
WHERE
  {
    graph ?g
      {
         &lt;http://www.bbc.co.uk/programmes/b006m86d#programme&gt; po:episode ?e .
         ?e a po:Episode .
         ?e po:short_synopsis ?o .
         ?e dc:title ?t
      }
  }
</pre>
    </div>

<div>
      <pre class="programlisting">
## Get reviews where John Paul Jones&#39; has been involved

PREFIX mo: &lt;http://purl.org/ontology/mo/&gt;
PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX dc: &lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX rev: &lt;http://purl.org/stuff/rev#&gt;
PREFIX po: &lt;http://purl.org/ontology/po/&gt;
SELECT DISTINCT ?r_name, ?rev
WHERE
  {
    {
      &lt;http://www.bbc.co.uk/music/artists/4490113a-3880-4f5b-a39b-105bfceaed04#artist&gt; foaf:made ?r1 .
      ?r1 a mo:Record .
      ?r1 dc:title ?r_name .
      ?r1 rev:hasReview ?rev
    }
    UNION
    {
      &lt;http://www.bbc.co.uk/music/artists/4490113a-3880-4f5b-a39b-105bfceaed04#artist&gt; mo:member_of ?b1 .
      ?b1 foaf:made ?r1 .
      ?r1 a mo:Record .
      ?r1 dc:title ?r_name .
      ?r1 rev:hasReview ?rev
    }
  }
</pre>
    </div>
<br />
<a name="rdfsparulexamples18" />
    <h5>14.3.2.3.18. Example usage of IN operator for retrieving all triples for each entity</h5>
<p>To retrieve all triples for each entity for a given list of entities uris, one might use the following syntax:</p>
<div>
      <pre class="programlisting">
SELECT ?p ?o
WHERE
  {
    ?s ?p ?o .
    FILTER ( ?s IN (&lt;someGraph#entity1&gt;, &lt;someGraph#entity2&gt;, ...&lt;someGraph#entityN&gt; ) )
  }
</pre>
    </div>
<p>So to demonstrate this feature, execute the following query:
</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
SELECT DISTINCT ?p ?o
WHERE
  {
    ?s ?p ?o .
    FILTER ( ?s IN (&lt;http://dbpedia.org/resource/Climate_change&gt;, &lt;http://dbpedia.org/resource/Social_vulnerability&gt; ) )
  }
LIMIT 100

p    	                                                o
ANY                                                     ANY
_______________________________________________________________________________

http://www.w3.org/1999/02/22-rdf-syntax-ns#type 	http://s.zemanta.com/ns#Target
http://s.zemanta.com/ns#title 	                        Climate change
http://s.zemanta.com/ns#targetType 	                http://s.zemanta.com/targets#rdf

3 Rows. -- 10 msec.
</pre>
    </div>
    <div class="tip">
      <div class="tiptitle">See Also:</div>
    <p>
        <a href="sparqlextensions.html#rdfsparulexamples6">Example usage of IN operator.</a>
      </p>
    </div>
<br />
<a name="rdfsparulexamples19" />
    <h5>14.3.2.3.19. Example for extending SPARQL via SQL for Full Text search: Variant I</h5>
<p>To find all albums looked up by album name, one might use the following syntax:</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
SELECT ?s ?o ?an ( bif:search_excerpt ( bif:vector ( &#39;In&#39;, &#39;Your&#39; ) , ?o ) ) 
WHERE
  {
    ?s rdf:type mo:Record .
    ?s foaf:maker ?a .
    ?a foaf:name ?an .
    ?s dc:title ?o .
    FILTER ( bif:contains ( ?o, &#39;&quot;in your&quot;&#39; ) ) 
      }
LIMIT 10;


http://musicbrainz.org/music/record/30f13688-b9ca-4fa5-9430-f918e2df6fc4  China in Your Hand  	          Fusion  China             &lt;b&gt;in&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Hand.
http://musicbrainz.org/music/record/421ad738-2582-4512-b41e-0bc541433fbc 	China in Your Hand 	            T&#39;Pau 	China             &lt;b&gt;in&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Hand.
http://musicbrainz.org/music/record/01acff2a-8316-4d4b-af93-97289e164379 	China in Your Hand 	            T&#39;Pau 	China             &lt;b&gt;in&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Hand.
http://musicbrainz.org/music/record/4fe99b06-ac73-40dd-8be7-bdaefb014981 	China in Your Hand 	            T&#39;Pau 	China             &lt;b&gt;in&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Hand.
http://musicbrainz.org/music/record/ac1cb011-6040-4515-baf2-59551a9884ac 	In Your Hands 	                Stella One Eleven 	      &lt;b&gt;In&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Hands.
http://dbtune.org/magnatune/album/mercy-inbedinst 	                      In Your Bed - instrumental mix 	Mercy Machine 	          &lt;b&gt;In&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Bed mix.
http://musicbrainz.org/music/record/a09ae12e-3694-4f68-bf25-f6ff4f790962 	A Word in Your Ear 	Alfie 	    A Word &lt;b&gt;in&lt;/b&gt;          &lt;b&gt;Your&lt;/b&gt; Ear.
http://dbtune.org/magnatune/album/mercy-inbedremix 	                      In Your Bed - the remixes 	    Mercy Machine 	          &lt;b&gt;In&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Bed the remixes.
http://musicbrainz.org/music/record/176b6626-2a25-42a7-8f1d-df98bec092b4 	Smoke Gets in Your Eyes 	      The Platters 	Smoke Gets  &lt;b&gt;in&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Eyes.
http://musicbrainz.org/music/record/e617d90e-4f86-425c-ab97-efdf4a8a452b 	Smoke Gets in Your Eyes 	      The Platters 	Smoke Gets  &lt;b&gt;in&lt;/b&gt; &lt;b&gt;Your&lt;/b&gt; Eyes.
</pre>
    </div>
<p>Note that the query will not show anything when there are triples like:</p>
<div>
      <pre class="programlisting">
&lt;x&gt; &lt;y&gt; &quot;In&quot; 
&lt;z&gt; &lt;q&gt; &quot;Your&quot;		
</pre>
    </div>

<br />
<a name="rdfsparulexamples20" />
    <h5>14.3.2.3.20. Example for extending SPARQL via SQL for Full Text search: Variant II</h5>
<p>To get movies from DBpedia, where the query can contain terms from the title, 
one might use the following syntax:</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL
 SELECT ?s ?an ?dn ?o( bif:search_excerpt ( bif:vector ( &#39;Broken&#39;, &#39;Flowers&#39; ) , ?o ) ) 
 WHERE
  {
    ?s rdf:type dbpedia-owl:Film .
    ?s dbpprop:name ?o .
    FILTER ( bif:contains ( ?o, &#39;&quot;broken flowers&quot;&#39; ) )
    OPTIONAL { ?s dbpprop:starring ?starring .}
    OPTIONAL { ?s dbpprop:director ?director . }
    OPTIONAL { ?starring dbpprop:name ?an . }
    OPTIONAL { ?director dbpprop:name ?dn . }
  };


http://dbpedia.org/resource/Broken_Flowers  Tilda Swinton  	Jim Jarmusch  	Broken Flowers  	          &lt;b&gt;Broken&lt;/b&gt; &lt;b&gt;Flowers&lt;/b&gt;.
http://dbpedia.org/resource/Broken_Flowers 	Swinton, Tilda 	Jim Jarmusch 	  Broken Flowers 	            &lt;b&gt;Broken&lt;/b&gt; &lt;b&gt;Flowers&lt;/b&gt;.
....
http://dbpedia.org/resource/Broken_Flowers  Bill Murray  	  Jim Jarmusch  	Music from Broken Flowers  	Music from &lt;b&gt;Broken&lt;/b&gt; &lt;b&gt;Flowers&lt;/b&gt;.
....
</pre>
    </div>
<p>Note that the query will not show anything when there are triples like:</p>
<div>
      <pre class="programlisting">
&lt;x&gt; &lt;y&gt; &quot;Broken&quot; 
&lt;z&gt; &lt;q&gt; &quot;Flowers&quot;		
</pre>
    </div>
<br />
<a name="rdfsparulexamples21" />
    <h5>14.3.2.3.21. Example for date manipulation of xsd types within SPARQL</h5>
<p>This example shows usage of dateTime column truncation to date only
and performs a group by on this column:
  </p>
<div>
      <pre class="programlisting">
-- prepare the data by inserting triples in a graph:
SQL&gt;SPARQL
INSERT INTO GRAPH &lt;http://BookStore.com&gt;
  {
    &lt;http://www.dajobe.org/foaf.rdf#i&gt; &lt;http://purl.org/dc/elements/1.1/title&gt;  &quot;SPARQL and RDF&quot; .
    &lt;http://www.dajobe.org/foaf.rdf#i&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;1999-01-01T00:00:00&gt;.
    &lt;http://www.w3.org/People/Berners-Lee/card#i&gt; &lt;http://purl.org/dc/elements/1.1/title&gt; &quot;Design notes&quot; .
    &lt;http://www.w3.org/People/Berners-Lee/card#i&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2001-01-01T00:00:00&gt;.
    &lt;http://www.w3.org/People/Connolly/#me&gt; &lt;http://purl.org/dc/elements/1.1/title&gt; &quot;Fundamentals of Compiler Design&quot; .
    &lt;http://www.w3.org/People/Connolly/#me&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2002-01-01T00:00:00&gt;.
    &lt;http://www.ivan-herman.net/foaf.rdf#me&gt; &lt;http://purl.org/dc/elements/1.1/title&gt;  &quot;RDF Store&quot; .
    &lt;http://www.ivan-herman.net/foaf.rdf#me&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2001-03-05T00:00:00&gt;.
    &lt;http://bblfish.net/people/henry/card#me&gt; &lt;http://purl.org/dc/elements/1.1/title&gt; &quot;Design RDF notes&quot; .
    &lt;http://bblfish.net/people/henry/card#me&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2001-01-01T00:00:00&gt;.
    &lt;http://hometown.aol.com/chbussler/foaf/chbussler.foaf#me&gt; &lt;http://purl.org/dc/elements/1.1/title&gt; &quot;RDF Fundamentals&quot; .
    &lt;http://hometown.aol.com/chbussler/foaf/chbussler.foaf#me&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2002-01-01T00:00:00&gt;. 
  };

_______________________________________________________

Insert into &lt;http://BookStore.com&gt;, 12 triples -- done

-- Find Count of Group by Dates
SQL&gt;SPARQL 
SELECT (xsd:date(bif:subseq(str(?a_dt), 0, 10))), count(*)
FROM &lt;http://BookStore.com&gt; 
WHERE 
  { 
    ?s &lt;http://purl.org/dc/elements/1.1/date&gt; ?a_dt 
  }
GROUP BY (xsd:date(bif:subseq(str(?a_dt), 0, 10)));

callret-0                                         callret-1
VARCHAR                                           VARCHAR
__________________________________________________
1999-01-01                                        1
2001-01-01                                        2
2002-01-01                                        2
2001-03-05                                        1

4 Rows. -- 15 msec.
SQL&gt;	
</pre>
    </div>
     <br />
   <br />
   <br />
<a name="sparqlbi" />
    <h3>14.3.3. Business Intelligence Extensions for SPARQL</h3>
<p>
Virtuoso extends SPARQL with expressions in results, subqueries, aggregates and grouping.
These extensions allow a straightforward translation of arbitrary SQL queries to SPARQL.
This extension is called  &quot;SPARQL BI&quot;, because the primary objective is to match needs of Business Intelligence.
The extended features apply equally to querying physical quads or relational tables mapped through RDF views.
  </p>
<div class="note">
      <div class="notetitle">Note:</div>
      <p>In this section, many examples use the TPC-H namespace. You may test them on your local demo database.
They use data from the TPC-H dataset that is mapped into a graph with an IRI of the form
http://example.com/tpch. When testing, you should replace the fake host name &quot;example.com&quot; with the host name of your own installation
verbatim, that is as specified in the &quot;DefaultHost&quot; parameter in the [URIQA] section of the Virtuoso configuration file.</p>
    </div>
<a name="rdfsparqlaggregate" />
    <h4>14.3.3.1. Aggregates in SPARQL</h4>
<p>Virtuoso extends SPARQL with SQL like aggregate and &quot;group by&quot; functionality. This functionality is
also available by embedding SPARQL text inside SQL, but the SPARQL extension syntax has the benefit
of also working over the SPARQL protocol and of looking more SPARQL-like.
</p>
<p>The supported aggregates are <strong>COUNT</strong>, <strong>MIN</strong>,
<strong>MAX</strong>, <strong>AVG</strong> and <strong>SUM</strong>. These can take an
optional <strong>DISTINCT</strong> keyword. These are permitted only in the selection part of a
select query. If a selection list consists of a mix of variables and aggregates, the non-aggregate
selected items are considered to be grouping columns and a <strong>GROUP BY</strong> over them is implicitly added
at the end of the generated SQL query. Virtuoso also supports explicit syntax for
<strong>GROUP BY</strong>, <strong>ORDER BY</strong>, <strong>LIMIT</strong> and <strong>OFFSET</strong>.
There is no explicit syntax for <strong>HAVING</strong> in Virtuoso SPARQL.
</p>
<p>If a selection consists of aggregates exclusively, the result set has one row with the values
of the aggregates. If there are aggregates and variables in the selection, the result set has as many
rows as there are distinct combinations of the variables; the aggregates are then calculated over each
such distinct combination, as if there were a SQL GROUP BY over all non-aggregates.
The implicit grouping pays attention to all subexpressions in the return list; say, if a result column expression is (?x * max (?y)) then
?y is aggregated and ?x is not so it is grouped by ?x.
This also means that if a result column expression is (bif:year (?shipdate)) then a group is made for each distinct ?shipdate,
i.e. up to 366 groups for each distinct year.
If you need one group per year, write explicit GROUP BY (bif:year (?shipdate)).

</p>
<p>With the count aggregate the argument may be either <strong>*</strong>, meaning counting all rows, or a variable
name, meaning counting all the rows where this variable is bound. If there is no implicit <strong>GROUP BY</strong>,
there can be an optional <strong>DISTINCT</strong> keyword before the variable that is the argument of an aggregate.
  </p>
<p>There is a special syntax for counting distinct combinations of selected variables. This is:</p>
<div>
      <pre class="programlisting">
SELECT COUNT DISTINCT ?v1 ... ?vn
  FROM ....
</pre>
    </div>
<p>User-defined aggregate functions are not supported in current version of the SPARQL compiler.</p>
<a name="rdfsparqlaggregatepathexpressions" />
    <h5>14.3.3.1.1. Path Expressions</h5>
<p>Virtuoso has support for paths consisting of dereferencing properties in SPARQL. Virtuoso allows
simple paths in expressions and has a separate feature for transitivity:</p>

  <ul>
  <li>S+&gt;P: for &quot;one or many values of P of S&quot;</li>
  <li>S*&gt;P: for &quot;zero or many values of P of S&quot;, so *&gt; may form a LEFT OUTER JOIN whereas +&gt; forms an INNER JOIN.</li>
  <li>S|&gt;P: is reserved for potential &quot;single value of P of S or an error if there are many values&quot;</li>
   </ul>
<p>If this property is set (for example by an RDF View) then +&gt; should be used.</p>

<p>
      <strong>Simple Example</strong>
    </p>
  <div>
      <pre class="programlisting">
SELECT ?f+&gt;foaf:name ?f|&gt;foaf:mbox WHERE { ?x foaf:name &quot;Alice&quot; . ?x foaf:knows ?f . FILTER (?f+&gt;foaf:name = &quot;John&quot;) }
  </pre>
    </div>
<p>means:</p>
  <div>
      <pre class="programlisting">
SELECT ?fname ?mbox
 WHERE
  {
    ?x foaf:knows ?f .
    ?x foaf:knows ?f .
    OPTIONAL {?f foaf:mbox ?mbox} .
    ?f foaf:name ?fname .
    ?x foaf:name &quot;Alice&quot; .
    ?x foaf:knows ?f2 .
    ?f2 foaf:name &quot;John&quot; .
  }
  </pre>
    </div>
<p>
      <strong>Other Examples</strong>
    </p>
  <div>
      <pre class="programlisting">
SPARQL
DEFINE sql:signal-void-variables 1
PREFIX tpcd: &lt;http://www.openlinksw.com/schemas/tpcd#&gt;
PREFIX oplsioc: &lt;http://www.openlinksw.com/schemas/oplsioc#&gt;
PREFIX sioc: &lt;http://rdfs.org/sioc/ns#&gt;
PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
SELECT
  ?l+&gt;tpcd:returnflag,
  ?l+&gt;tpcd:linestatus,
  sum(?l+&gt;tpcd:linequantity) as ?sum_qty,
  sum(?l+&gt;tpcd:lineextendedprice) as ?sum_base_price,
  sum(?l+&gt;tpcd:lineextendedprice*(1 - ?l+&gt;tpcd:linediscount)) as ?sum_disc_price,
  sum(?l+&gt;tpcd:lineextendedprice*(1 - ?l+&gt;tpcd:linediscount)*(1+?l+&gt;tpcd:linetax)) as ?sum_charge,
  avg(?l+&gt;tpcd:linequantity) as ?avg_qty,
  avg(?l+&gt;tpcd:lineextendedprice) as ?avg_price,
  avg(?l+&gt;tpcd:linediscount) as ?avg_disc,
  count(1) as ?count_order
FROM &lt;http://example.com/tpcd&gt;
WHERE {
    ?l a tpcd:lineitem .
    FILTER (?l+&gt;tpcd:shipdate &lt;= bif:dateadd (&quot;day&quot;, -90, &#39;1998-12-01&#39;^^xsd:date)) }
ORDER BY ?l+&gt;tpcd:returnflag ?l+&gt;tpcd:linestatus

  </pre>
    </div>
  <div>
      <pre class="programlisting">
SPARQL
DEFINE sql:signal-void-variables 1
PREFIX tpcd: &lt;http://www.openlinksw.com/schemas/tpcd#&gt;
SELECT
  ?supp+&gt;tpcd:acctbal,
  ?supp+&gt;tpcd:name,
  ?supp+&gt;tpcd:has_nation+&gt;tpcd:name as ?nation_name,
  ?part+&gt;tpcd:partkey,
  ?part+&gt;tpcd:mfgr,
  ?supp+&gt;tpcd:address,
  ?supp+&gt;tpcd:phone,
  ?supp+&gt;tpcd:comment
FROM &lt;http://example.com/tpcd&gt;
   WHERE {
  ?ps a tpcd:partsupp; tpcd:has_supplier ?supp; tpcd:has_part ?part .
  ?supp+&gt;tpcd:has_nation+&gt;tpcd:has_region tpcd:name &#39;EUROPE&#39; .
  ?part tpcd:size 15 .
  ?ps tpcd:supplycost ?minsc .
  { SELECT ?part min(?ps+&gt;tpcd:supplycost) as ?minsc
            WHERE {
        ?ps a tpcd:partsupp; tpcd:has_part ?part; tpcd:has_supplier ?ms .
        ?ms+&gt;tpcd:has_nation+&gt;tpcd:has_region tpcd:name &#39;EUROPE&#39; .
      } }
    FILTER (?part+&gt;tpcd:type like &#39;%BRASS&#39;) }
ORDER BY
  desc (?supp+&gt;tpcd:acctbal)
  ?supp+&gt;tpcd:has_nation+&gt;tpcd:name
  ?supp+&gt;tpcd:name
  ?part+&gt;tpcd:partkey

  </pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples" />
    <h5>14.3.3.1.2. Examples</h5>
<a name="rdfsparqlaggregateexamples1" />
    <h6>Example for count of physical triples in http://mygraph.com</h6>
<div>
      <pre class="programlisting">
SPARQL
SELECT COUNT (*)
  FROM &lt;http://mygraph.com&gt;
 WHERE {?s ?p ?o}
</pre>
    </div>
<p>
      <strong>Example for count of O&#39;s for each distinct P</strong>
    </p>
<div>
      <pre class="programlisting">
SPARQL define input:inference &quot;http://mygraph.com&quot;
SELECT ?p COUNT (?o)
  FROM &lt;http://mygraph.com&gt;
 WHERE {?s ?p ?o}
</pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples2" />
    <h6>Example for count of triples, including inferred triples and the count of
distinct O values</h6>
<div>
      <pre class="programlisting">
SPARQL define input:inference &quot;http://mygraph.com&quot;
SELECT COUNT (?p) COUNT (?o) COUNT (DISTINCT ?o)
 FROM &lt;http://mygraph.com&gt;
WHERE {?s ?p ?o}
</pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples3" />
    <h6>Example for get number of distinct bindings of ?s ?p ?o</h6>
<div>
      <pre class="programlisting">
SPARQL define input:inference &quot;http://mygraph.com&quot;
SELECT count distinct ?s ?p ?o
  FROM &lt;http://mygraph.com&gt;
 WHERE {?s ?p ?o}
</pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples4" />
    <h6>Example for get counts and total prices of ordered items, grouped by item status</h6>
  <div>
      <pre class="programlisting">
  SPARQL
prefix tpch: &lt;http://www.openlinksw.com/schemas/tpch#&gt;
SELECT ?status count(*) sum(?extendedprice)
FROM &lt;http://localhost.localdomain:8310/tpch&gt;
WHERE {
    ?l a tpch:lineitem ;
      tpch:lineextendedprice ?extendedprice ;
      tpch:linestatus ?status .
    }
  </pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples5" />
    <h6>Example for get counts and total prices of ordered items, grouped by item status</h6>
   <p>
      <strong>Example: A dataset of people, some duplicated</strong>
    </p>
   <p>Suppose there is a dataset with many people, some of them sharing the same name. To list them we would, ideally, execute the query:
   </p>
  <div>
      <pre class="programlisting">
  SPARQL
SELECT DISTINCT
 (?name) ?person ?mail
 WHERE {
   ?person rdf:type foaf:Person .
   ?person foaf:name ?name .
   ?person foaf:mbox_sha1sum ?mail
    }
  </pre>
    </div>
   <p>Unfortunately, the facility to apply DISTINCT to a part of the result set row (i.e. to ?name) does not currently exist.
   (Although the above form is permitted, it&#39;s interpreted as being identical to &#39;SELECT DISTINCT ?name, ?person, ?mail WHERE ...&#39;)
   If there&#39;s demand for such a feature then we may introduce an aggregate called, say, SPECIMEN, that will return the very first of the aggregated values. e.g.:
   </p>
<div>
      <pre class="programlisting">
SPARQL
SELECT ?name (specimen(?person)) (specimen(?mail))
      WHERE
        {
    ?person rdf:type foaf:Person .
    ?person foaf:name ?name .
    ?person foaf:mbox_sha1sum ?mail
  }
</pre>
    </div>
   <p>As a workaround to this limitation, the MIN aggregate can be used, provided duplicates are few and there&#39;s no requirement
   that ?person should correspond to ?mail
(i.e. the result should contain some person node and some mail node but they don&#39;t have to be connected by foaf:mbox_sha1sum):
   </p>
<div>
      <pre class="programlisting">
SPARQL
SELECT ?name (min(?person)) (min(?mail))
      WHERE
        {
    ?person rdf:type foaf:Person .
    ?person foaf:name ?name .
    ?person foaf:mbox_sha1sum ?mail
}
</pre>
    </div>
   <p>Otherwise, a complicated query is needed:</p>
<div>
      <pre class="programlisting">
SPARQL
SELECT
 ?name
 ((SELECT (min (?person3))
     WHERE {
         ?person3 rdf:type foaf:Person .
         ?person3 foaf:name ?name .
         ?person3 foaf:mbox_sha1sum ?mail } )) as ?person
 ?mail
 WHERE {
     { SELECT distinct ?name
       WHERE {
           ?person1 rdf:type foaf:Person .
           ?person1 foaf:name ?name .
           ?person1 foaf:mbox_sha1sum ?mail1 } }
     { SELECT ?name (min(?mail2)) as ?mail
       WHERE {
           ?person2 rdf:type foaf:Person .
           ?person2 foaf:name ?name .
           ?person2 foaf:mbox_sha1sum ?mail2 } }
 }
</pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples6" />
    <h6>Example quering dbpedia</h6>
<p>The following example demonstrate how to query dbpedia. Suppose there is local onotlogy,
which has a datatype property hasLocation with a string containing city names. The query below finds
which of those cities are in dbpedia:</p>
<div>
      <pre class="programlisting">
SPARQL
PREFIX dbpprop: &lt;http://dbpedia.org/property/&gt;
PREFIX dbo: &lt;http://dbpedia.org/ontology/&gt;
PREFIX vocab:&lt;http://myexample.com/localOntology.rdf&gt;
PREFIX dbpedia: &lt;http://dbpedia.org/&gt;
PREFIX dbpres: &lt;http://dbpedia.org/resource/&gt;
SELECT ?city
WHERE
  {
    ?sub :location ?city .
    FILTER(bif:exists(( ASK { ?subdb a dbo:City . ?subdb dbpprop:officialName ?city })))
  }
</pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples7" />
    <h6>Example for MAX with HAVING and GROUP BY</h6>
<div>
      <pre class="programlisting">
## Example &quot;Find which town or city in
## the UK has the largest proportion of students.

PREFIX dbpedia-owl: &lt;http://dbpedia.org/ontology/&gt;
PREFIX dbpedia-owl-uni: &lt;http://dbpedia.org/ontology/University/&gt;
PREFIX dbpedia-owl-inst: &lt;http://dbpedia.org/ontology/EducationalInstitution/&gt;

SELECT ?town COUNT(?uni)
       ?pgrad ?ugrad
       MAX(?population)
       ( ((?pgrad+?ugrad)/ MAX(?population))*100 ) AS ?percentage
WHERE
  {
    ?uni dbpedia-owl-inst:country dbpedia:United_Kingdom ;
                         dbpedia-owl-uni:postgrad ?pgrad ;
                        dbpedia-owl-uni:undergrad ?ugrad ;
                             dbpedia-owl-inst:city ?town .
    OPTIONAL
    {
          ?town dbpedia-owl:populationTotal ?population .
          FILTER (?population &gt; 0 )
    }
  }
GROUP BY ?town ?pgrad ?ugrad
HAVING ( ( ( (?pgrad+?ugrad)/ MAX(?population) )*100 ) &gt; 0 )
ORDER BY DESC 6
</pre>
    </div>
<br />
<a name="rdfsparqlaggregateexamples8" />
    <h6>Example Aggregating Distance Values Over Years</h6>
<p>The following example demonstrate how to aggregate Distance Values Over Years:</p>
<p>First we insert some data in a graph with name for ex. &lt;urn:dates:distances&gt;:</p>
<div>
      <pre class="programlisting">
SQL&gt; SPARQL INSERT INTO GRAPH &lt;urn:dates:distances&gt;
  {
    &lt;:a1&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-23T00:00:00&gt; .
    &lt;:a1&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.955218675&gt; .    
    &lt;:a2&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-24T00:00:00&gt; .
    &lt;:a2&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.798155989&gt; .
    &lt;:a3&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-25T00:00:00&gt; .
    &lt;:a3&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.064686628&gt; .
    &lt;:a4&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-26T00:00:00&gt; .
    &lt;:a4&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.279800332&gt; .
    &lt;:a5&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-27T00:00:00&gt; .
    &lt;:a5&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.651255995&gt; .
    &lt;:a6&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-28T00:00:00&gt; .
    &lt;:a6&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.094410557&gt; .
    &lt;:a7&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-29T00:00:00&gt; .
    &lt;:a7&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.43461913&gt; .
    &lt;:a8&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-30T00:00:00&gt; .
    &lt;:a8&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.264862918&gt; .
    &lt;:a9&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2010-12-31T00:00:00&gt; .
    &lt;:a9&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.770588658&gt; .
    &lt;:a10&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-01T00:00:00&gt; .
    &lt;:a10&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.900997627&gt; .
    &lt;:a11&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-02T00:00:00&gt; .
    &lt;:a11&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.324972375&gt; .
    &lt;:a12&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-03T00:00:00&gt; .
    &lt;:a12&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.937221226&gt; .
    &lt;:a13&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-04T00:00:00&gt; .
    &lt;:a13&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.269511925&gt; .
    &lt;:a14&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-05T00:00:00&gt; .
    &lt;:a14&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.726014538&gt; .
    &lt;:a15&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-06T00:00:00&gt; .
    &lt;:a15&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.843581439&gt; .
    &lt;:a16&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-07T00:00:00&gt; .
    &lt;:a16&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.835685559&gt; .
    &lt;:a17&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-08T00:00:00&gt; .
    &lt;:a17&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.673213742&gt; .
    &lt;:a18&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-09T00:00:00&gt; .
    &lt;:a18&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.055026879&gt; .
    &lt;:a19&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-10T00:00:00&gt; .
    &lt;:a19&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.987475424&gt; .
    &lt;:a20&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-11T00:00:00&gt; .
    &lt;:a20&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.167315598&gt; .
    &lt;:a21&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-12T00:00:00&gt; .
    &lt;:a21&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.545317103&gt; .
    &lt;:a22&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-13T00:00:00&gt; .
    &lt;:a22&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.75137005&gt; .
    &lt;:a23&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-14T00:00:00&gt; .
    &lt;:a23&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.123649985&gt; .
    &lt;:a24&gt; &lt;http://purl.org/dc/elements/1.1/date&gt; &lt;2011-01-15T00:00:00&gt; .
    &lt;:a24&gt; &lt;http://linkedgeodata.org/vocabulary#distance&gt; &lt;0.750214251&gt; .
  };	
callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;urn:dates:distances&gt;, 48 (or less) triples -- done

1 Rows. -- 94 msec.
</pre>
    </div>
<p>Then we execute the following query:</p>
<div>
      <pre class="programlisting">
SQL&gt; SPARQL 
PREFIX dst: &lt;http://linkedgeodata.org/vocabulary#&gt;
PREFIX dc: &lt;http://purl.org/dc/elements/1.1/&gt;
SELECT (bif:year( bif:stringdate(?sdate)) AS ?syear) (bif:sum( bif:number(?dist)) AS ?distance)
FROM &lt;urn:dates:distances&gt;
WHERE
  {
    ?row dc:date ?sdate .
    ?row dst:distance ?dist
  }
GROUP BY (bif:year(bif:stringdate(?sdate)))
ORDER BY ASC(bif:year(bif:stringdate(?sdate)));

syear                                distance
VARCHAR                              VARCHAR
________________________________________________

2010                                 4.313598882
2011                                 8.891567721

2 Rows. -- 31 msec.
</pre>
    </div>
<br />	
<br />
<a name="rdfsparqlaggregatenote" />
    <h5>14.3.3.1.3. Note on Aggregates and Inference</h5>
<p>Inferencing is added to a SPARQL query only for those variables whose value is actually used. Thus,
</p>
<div>
      <pre class="programlisting">
SELECT COUNT (*)
 FROM &lt;http://mygraph.com&gt;
WHERE {?s ?p ?o}
</pre>
    </div>
<p>will not return inferred values since s, p, and o are not actually used. In contrast,
</p>
<div>
      <pre class="programlisting">
SPARQL
SELECT COUNT (?s) COUNT (?p) COUNT (?o)
 FROM &lt;http://mygraph.com&gt;
WHERE {?s ?p ?o}
</pre>
    </div>
<p>will also return all the inferred triples.
</p>
<p>
Note: This difference in behaviour may lead to confusion and will, therefore, likely be altered in the future.
</p>
<br />
<br />
<a name="rdfsparqlarrowop" />
    <h4>14.3.3.2. Pointer Operator (<strong>+&gt;</strong> and <strong>*&gt;</strong>)</h4>
<p>
When expressions occur in result sets, many variables are often introduced only for the purpose of passing a value from a triple pattern to the result expression.
This is inconvenient because many triple patterns are trivial. The presence of large numbers of variable names masks &quot;interesting&quot; variables that are used in more than once in pattern and which establish logical relationships between different parts of the query.
As a solution we introduce pointer operators.</p>
<p>
The <strong>+&gt;</strong> (pointer) operator allows referring to a property value without naming it as a variable and explicitly writing a triple pattern. We can shorten the example above to:</p>
<div>
      <pre class="programlisting">SPARQL
prefix tpch: &lt;http://www.openlinksw.com/schemas/tpch#&gt;
SELECT ?l+&gt;tpch:linestatus count(*) sum(?l+&gt;tpch:lineextendedprice)
FROM &lt;http://localhost.localdomain:8310/tpch&gt;
WHERE { ?l a tpch:lineitem }</pre>
    </div>
<p>
The <strong>?subject+&gt;propertyname</strong> notation is equivalent to having a triple pattern <strong>?subject propertyname ?aux_var</strong> binding an auxiliary variable to the mentioned property of the subject, within the group pattern enclosing the reference.
For a SELECT, the enclosing group pattern is considered to be the top level pattern of the where clause or, in the event of a union, the top level of each term of the union.
Each distinct pointer adds exactly one triple pattern to the enclosing group pattern. Multiple uses of <strong>+&gt;</strong> with the same arguments do not each add a triple pattern.
(Having multiple copies of an identical pattern might lead to changes in cardinality if multiple input graphs were being considered.
If a lineitem had multiple discounts or extended prices, then we would get the cartesian product of both.)
</p>
<p>
If a property referenced via <strong>+&gt;</strong> is absent, the variable on the left side of the operator is not bound in the enclosing group pattern because it should be bound in all triple patterns where it appears as a field, including implicitly added patterns.
</p>
<p>
The <strong>?subject*&gt;propertyname</strong> notation is introduced in order to access optional property values. It adds an OPTIONAL group <strong>OPTIONAL { ?subject propertyname ?aux_var }</strong>, not a plain triple pattern, so the binding of ?subject is not changed even if the object variable is not bound. If the property is set for all subjects in question then the results of <strong>*&gt;</strong> and <strong>+&gt;</strong> are the same. All other things being equal, the <strong>+&gt;</strong> operator produces better SQL code than <strong>*&gt;</strong> so use <strong>*&gt;</strong> only when it is really needed.</p>
<br />
<a name="rdfsparqlnesting" />
    <h4>14.3.3.3. Subqueries in SPARQL</h4>
<p>
Pure SPARQL does not allow binding a value that is not retrieved through a triple pattern.
We lift this restriction by allowing expressions in the result set and providing names for result columns.
We also allow a SPARQL SELECT statement to appear in another SPARQL statement in any place where a group pattern may appear.
The names of the result columns form the names of the variables bound, using values from the returned rows.
This resembles derived tables in SQL.</p>
<p>
For instance, the following statement finds the prices of the 1000 order lines with the biggest discounts:</p>

<div>
      <pre class="programlisting">SPARQL
define sql:signal-void-variables 1
prefix tpch: &lt;http://www.openlinksw.com/schemas/tpch#&gt;
SELECT ?line ?discount (?extendedprice * (1 - ?discount)) as ?finalprice
FROM &lt;http://localhost.localdomain:8310/tpch&gt;
WHERE
  {
    ?line a tpch:lineitem ;
    tpch:lineextendedprice ?extendedprice ;
    tpch:linediscount ?discount .
  }
ORDER BY DESC (?extendedprice * ?discount)
LIMIT 1000</pre>
    </div>

<p>
After ensuring that this query works correctly, we can use it to answer more complex questions.
Imagine that we want to find out how big the customers are who have received the biggest discounts.</p>

<div>
      <pre class="programlisting">SPARQL
define sql:signal-void-variables 1
prefix tpch: &lt;http://www.openlinksw.com/schemas/tpch#&gt;
SELECT ?cust sum(?extendedprice2 * (1 - ?discount2)) max (?bigdiscount)
FROM &lt;http://localhost.localdomain:8310/tpch&gt;
WHERE
  {
    {
      SELECT ?line (?extendedprice * ?discount) as ?bigdiscount
      WHERE {
        ?line a tpch:lineitem ;
          tpch:lineextendedprice ?extendedprice ;
          tpch:linediscount ?discount . }
      ORDER BY DESC (?extendedprice * ?discount)
      LIMIT 1000
    }
    ?line tpch:has_order ?order .
    ?order tpch:has_customer ?cust .
    ?cust tpch:customer_of ?order2 .
    ?order2 tpch:order_of ?line2 .
    ?line2 tpch:lineextendedprice ?extendedprice2 ;
      tpch:linediscount ?discount2 .
  }
ORDER BY (SUM(?extendedprice2 * (1 - ?discount2)) / MAX (?bigdiscount))</pre>
    </div>

<p>
The inner select finds the 1000 biggest (in absolute value) discounts and their order lines. For each line we find orders of it, and the customer. For each customer found, we find all the orders he made and all the lines of each of the orders (variable ?line2).</p>
<p>
Note that the inner select does not contain FROM clauses. It is not required because the inner select inherits the access permissions of all the outer queries. It is also important to note that the internal variable bindings of the subquery are not visible in the outer query; only the result set variables are bound. Similarly, variables bound in the outer query are not accessible to the subquery.</p>
<p>
Note also the declaration <strong>define sql:signal-void-variables 1</strong> that forces the SPARQL compiler to signal errors if some variables cannot be bound due to misspelt names or attempts to make joins across disjoint domains. These diagnostics are especially important when the query is long.</p>
<br />
<a name="rdfsparqlbackq" />
    <h4>14.3.3.4. Expressions in Triple Patterns</h4>
<p>In addition to expressions in filters and result sets, Virtuoso allows the use of expressions in triples of a
CONSTRUCT pattern or WHERE pattern - an expression can be used instead of a constant or a variable name for a subject, predicate or object.
When used in this context, the expression is surrounded by backquotes.</p>

<p>
      <strong>Example: With a WHERE Clause:</strong>
    </p>
<p>The following example returns all the distinct &#39;fragment&#39; parts of all subjects in all graphs that have some predicate whose value is equal to 2+2.</p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL SELECT distinct (bif:subseq (?s, bif:strchr (?s, &#39;#&#39;)))
   WHERE {
     graph ?g {
       ?s ?p `2+2` .
       FILTER (! bif:isnull (bif:strchr (?s, &#39;#&#39;) ) )
     } };

callret
VARCHAR
----------
#four
</pre>
    </div>
<p>Inside a WHERE part, every expression in a triple pattern is replaced with new variable and a filter expression is added to the enclosing group. The new filter is an equality of the new variable and the expression. Hence the sample above is identical to:</p>
<div>
      <pre class="programlisting">
SPARQL
SELECT distinct (bif:subseq (?s, bif:strchr (?s, &#39;#&#39;)))
   WHERE {
     graph ?g {
       ?s ?p ?newvariable .
       FILTER (! bif:isnull (bif:strchr (?s, &#39;#&#39;) ) )
       FILTER (?newvariable = (2+2)) .
     } }
</pre>
    </div>
<p>
      <strong>Example: With CONSTRUCT</strong>
    </p>
<div>
      <pre class="programlisting">
CONSTRUCT {
  &lt;http://bio2rdf.org/interpro:IPR000181&gt;
&lt;http://bio2rdf.org/ns/bio2rdf#hasLinkCount&gt;
`(SELECT (count(?s)) as ?countS
   WHERE { ?s ?p &lt;http://bio2rdf.org/interpro:IPR000181&gt; })` }
WHERE { ?s1 ?p1 ?o1 } limit 1
</pre>
    </div>
<p>The result should be:</p>
<div>
      <pre class="programlisting">
&lt;http://bio2rdf.org/interpro:IPR000181&gt; &lt;http://bio2rdf.org/ns/bio2rdf#hasLinkCount&gt; &quot;0&quot;^^&lt;http://www.w3.org/2001/XMLSchema#integer&gt; .
</pre>
    </div>
<p>
      <strong>Example: Inserting into a graph using an expression</strong>
    </p>
<div>
      <pre class="programlisting">
SQL&gt;SPARQL insert into graph &lt;http://MyNewGraph.com/&gt; {
&lt;http://bio2rdf.org/interpro:IPR000181&gt;
&lt;http://bio2rdf.org/ns/bio2rdf#hasLinkCount&gt;
  `(SELECT (count(?s)) as ?countS
    WHERE { ?s ?p &lt;http://bio2rdf.org/interpro:IPR000181&gt; })` }
 WHERE { ?s1 ?p1 ?o1 } limit 1  ;

callret-0
VARCHAR
_______________________________________________________________________________

Insert into &lt;http://MyNewGraph.com/&gt;, 1 triples -- done

1 Rows. -- 30 msec.
</pre>
    </div>
<br />
<br />
<table border="0" width="90%" id="navbarbottom">
    <tr>
        <td align="left" width="33%">
          <a href="rdfsparql.html" title="SPARQL">Previous</a>
          <br />SPARQL</td>
     <td align="center" width="34%">
          <a href="rdfandsparql.html">Chapter Contents</a>
     </td>
        <td align="right" width="33%">
          <a href="rdfgraphsecurity.html" title="RDF Graphs Security">Next</a>
          <br />RDF Graphs Security</td>
    </tr>
    </table>
  </div>
  <div id="footer">
    <div>Copyright© 1999 - 2009 OpenLink Software All rights reserved.</div>
   <div id="validation">
    <a href="http://validator.w3.org/check/referer">
        <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" />
    </a>
    <a href="http://jigsaw.w3.org/css-validator/">
        <img src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" height="31" width="88" />
    </a>
   </div>
  </div>
 </body>
</html>