Professional Documents
Culture Documents
Table of Contents
4.3.3. Configuration
4.3.4. Notes and Hints
4.4. Change Tracking
5. The web interface
5.1. Logging in
5.2. Adding data to a repository
6. The SeRQL query language (revision 1.2)
6.1. Revisions
6.1.1. revision 1.1
6.1.2. revision 1.2
6.2. Introduction
6.3. URIs, literals and variables
6.3.1. Variables
6.3.2. URIs
6.3.3. Literals
6.3.4. Blank Nodes (R1.2)
6.4. Path expressions
6.4.1. Basic path expressions
6.4.2. Path expression short cuts
6.4.3. Optional path expressions
6.5. Select- and construct queries
6.6. Select queries
6.7. Construct queries
6.8. The WHERE clause
6.8.1. Boolean constants
6.8.2. Value (in)equality
6.8.3. Numerical comparisons
6.8.4. The LIKE operator (R1.2)
6.8.5. isResource() and isLiteral()
6.8.6. isURI() and isBNode() (R1.2)
6.8.7. AND, OR, NOT
6.8.8. Nested WHERE clauses (R1.2)
6.9. Other functions
6.9.1. label(), lang() and datatype()
6.9.2. namespace() and localName() (R1.2)
6.10. The LIMIT and OFFSET clauses
6.11. The USING NAMESPACE clause
6.12. Built-in predicates
6.13. Set combinatory operations
6.13.1. UNION (R1.2)
6.13.2. INTERSECT (R1.2)
6.13.3. MINUS (R1.2)
6.14. NULL values
6.15. Query Nesting
6.15.1. The IN operator (R1.2)
6.15.2. ANY and ALL (R1.2)
6.15.3. EXISTS (R1.2)
6.16. Example SeRQL queries
6.16.1. Query 1
6.16.2. Query 2
6.16.3. Query 3
6.17. Comments/feedback
6.18. References
6.19. SeRQL grammar
A.10. TERMINATION
A.11. FUTURE REVISIONS OF THIS LICENSE
A.12. How to use this License for your documents
openrdf-model.jar.
openrdf-util.jar.
These archives (which are located in the lib/ directory) contain Java classes ready for use in your
own application. In Chapter 7, The Sesame API, you can find instructions and examples on how to
use Sesame in your own code: how to do queries, how to add and remove data, etc.
In Chapter 2, Installing Sesame, you will find detailed information on how to install Sesame as a
server.
Starting at the bottom, the Storage And Inference Layer, or SAIL API, is an internal Sesame API that
abstracts from the storage format used (i.e. whether the data is stored in an RDBMS, in memory, or
in files, for example), and provides reasoning support. SAIL implementations can also be stacked on
top of each other, to provide functionality such as caching or concurrent access handling. Each
Sesame repository has its own SAIL object to represent it.
On top of the SAIL, we find Sesame's functional modules, such as the SeRQL, RQL and RDQL query
engines, the admin module, and RDF export. Access to these functional modules is available through
Sesame's Access APIs, consisting of two seperate parts: the Repository API and the Graph API. The
Repository API provides high-level access to Sesame repositories, such as querying, storing of rdf
files, extracting RDF, etc. The Graph API provides more fine-grained support for RDF manipulation,
such as adding and removing individual statements, and creation of small RDF models directly from
code. The two APIs complement each other in functionality, and are in practice often used together.
The Access APIs provide direct access to Sesame's functional modules, either to a client program
(for example, a desktop application that uses Sesame as a library), or to the next component of
Sesame's architecture, the Sesame server. This is a component that provides HTTP-based access to
Sesame's APIs. Then, on the remote HTTP client side, we again find the access APIs, which can
again be used for communicating with Sesame, this time not as a library, but as a server running on a
remote location.
While each part of the Sesame code is publicly available and extensible, most developers will be
primarily interested in the Access APIs, for communicating with a Sesame RDF model or a Sesame
repository from their application. In Chapter 7, The Sesame API, these APIs are described in more
detail, through several code examples.
openrdf-model.jar.
openrdf-util.jar.
These files can be found in the lib directory of the binary download. Simply including them in your
classpath will allow you to use the functionality of Sesame in your own Java application.
Sesame requires Java 2, version 1.4 or newer, to function properly.
If you intend to use client/server communication over HTTP, then you will additionally need the
following third-party libraries:
Jakarta Commons FileUpload, release 1.2.
Jakarta Commons IO, release 1.3.
6
These third-party libraries can be found in the ext/ directory of the source distribution of Sesame,
and are also included in the library directory of the Sesame Web Archive ( sesame.war). More
information about these libraries, including license information, can be found in the file
doc/thirdparty.txt.
For more information on how to use Sesame as a library, see Chapter 7, The Sesame API
Sesame itself
A Java servlet container (running Java 2, version 1.4 or newer) for running
the Sesame servlets
Sesame should be able to run on any Java servlet container that supports the Servlet 2.2 and JSP
1.1 specifications, or newer. So far, it has been tested with Tomcat and, in the case of Oracle, with
OC4J. It has also been reported to work without problems on BEA WebLogic 8.1 SP2 and Jetty.
Please post any reports about compatibility with other servlet containers to our forums.
Sesame has several options for storage of RDF data: it can store data in main-memory (optionally
with a dump to file for persistence), it can store data on disk in a dedicated file structure, or it can
store data in a relational database. See section More on the RDBMS for more info about the last
option.
4. In case you are planning to use a database with Sesame, copy the
appropriate JDBC-driver file(s) to the directory [SESAME_DIR]/WEB-INF/lib/.
5. Copy
the
file
to
of
Sesame, if you are upgrading you will already have a config file, and
copying the example over it will destroy your existing configuration. The
example file contains some repository entries for different Sails and
databases, and one user account. The file may require some modifications
in order to work on your machine. Please check out Server administration if
you want to learn how to do this.
[SESAME_DIR]/WEB-INF/system.conf.example
[SESAME_DIR]/WEB-INF/system.conf. NOTE: only do this for a fresh install
6. (Re)start your Tomcat server and Sesame should now be up and running.
You
can
access
the
Sesame
web
interface
at
http://
[MACHINE_NAME]:8080/sesame.
Add
the
following
line
to
[OC4J_HOME]/j2ee/home/config/http-web-
site.xml:
<webappapplication="default"name="sesame"root="/sesame"/>
You should also test whether the Sesame servlets are running correctly, and whether Sesame can
talk to the RDBMS (if applicable). Select one of the repositories that you have configured and press
'Go>>'. Click on the 'Add (www)' link in the toolbar at the top of the window, and try to upload the
test.rdf
file
from
Sesame's
admin
directory
(e.g.
http://
[MACHINE_NAME]:8080/sesame/admin/test.rdf). You can do this by typing this URL in the first text
field and by clicking on the 'Add data' button after that.
If the data-upload was successful, you should also be able to extract the uploaded data. Click on the
'Extract' link in the toolbar and press the 'Extract' button. This should yield an RDF document
describing all classes and properties in the repository.
Sesame has been successfully installed if all of this works. You can remove or reconfigure the test
user account and repository if you want. If you haven't done so already, you can take a look at the
next chapter for information on how to add and remove user accounts and repositories to/from
Sesame.
Recent versions of PostgreSQL are a lot faster than the 7.1 version that
Sesame was originally developed against. The most recents tests have
been done using version 8.1.4. If possibly, you should use the newest
possible (stable) version of PostgreSQL that is available.
JDBC-drivers for PostgreSQL can be found at http://jdbc.postgresql.org, but
these also come bundled with (some of) the PostgreSQL installation
packages.
Make sure that the PostgreSQL server is running with the TCP/IP
connections enabled. If TCP/IP is not enabled, the JDBC-driver will not be
able to talk to the server.
The RDBMS Sail will need an (empty) database on the PostgreSQL server,
as well as a user account that has access to (or owns) that database. You
need to create these manually, for example by using the pgAdmin tool
mentioned above. In most cases, the encoding of the new database should
be set to 'UTF8'. The RDBMS Sail will take care of creating the required
tables and indexes when first run. We'll assume that the user account is
called 'sesame' in the rest of this document.
Several people have reported problems with 4.x and early 5.0.x version of
MySQL, especially with versions that came pre-installed with Linux
distributions. So far, all these problems were resolved by installing the most
recent stable version of MySQL and its JDBC-driver. Please try this before
reporting problems when using unstable/beta releases.
The RDBMS Sail will need an (empty) database on the MySQL server, as
well as a user account that has access to that database. You need to create
these manually, for example by using the MySQL Administrator tool
mentioned above. In most cases, the encoding of the new database should
be set to 'UTF8'. The RDBMS Sail will take care of creating the required
tables and indexes when first run. We'll assume that the user account is
called 'sesame' in the rest of this document.
The RDBMS Sail has been tested with Oracle 9i and newer, Oracle 8i does
not work due to lack of support for left (outer) joins. Oracle 9.2.0.1.0 has a
bug affecting ANSI-style left (outer) joins which makes it incompatible with
Sesame. This bug has been fixed in version 9.2.0.4.0.
The
Oracle
JDBC
driver
can
be
found
at
[ORACLE_HOME]/jdbc/lib/classes12.jar or at http://otn.oracle.com/.
You will have to create a user with appropriate rights (resource + connect).
Table of Contents
When you have started Configure Sesame! (Figure 3.1, Configure Sesame!), load the file
system.conf. If you want to configure a running Sesame server, you can do this by loading the file
directly from the server (menu option [File]-->[Load from server...], see Figure 3.2, Loading the
configuration from a running server). If the server is not running, you can open the file from disk
(menu option [File]-->[Open file...]).
If this is a fresh installation of Sesame, the admin password is still the default password. In this case,
you will need to enter "admin" as the Current admin password to load the configuration. If this is not a
fresh installation of Sesame you will need to enter the admin password that you have specified
earlier.
2. Click the "Add user" icon on the bottom of the window. A new entry is added
to the overview.
3. Enter the credentials for the new user, hitting Enter to go to the next column.
To remove a user account, simply select the user you wish to remove and click the "Remove user"
button in the bottom right of the window.
The Repository details window also allows you to change the access rights of users to a repository.
To change the access rights, click the "Access rights" tab, where you can edit the rights of existing
users or add new users (Figure 3.8, The "access rights" tab). The entry anonymous is a special
entry that represents users who do not log in. Giving this entry access rights means that anybody can
access the repository.
Figure 3.8. The "access rights" tab
The easiest way to add a new repository is to "clone" an existing repository. Use the "Clone" button
on the repository tab (Figure 3.6, The "Repository" tab) to do this. This creates a copy of the
currently selected repository configuration, which you can then edit. Take special care to change
details such as the jdbcUrl or file attributes of the Sail (see Chapter 4, Advanced repository
configuration).
Alternatively, you can add a new repository by using the "Add" button and filling in all the information
by yourself.
The most important part of the repository configuration is the sail stack, which can be found in the
"repository details" screen (Figure 3.7, The "Repository details" window). Here, you configure where
the actual repository storage resides, whether or not inferencing, security and versioning, etc. should
be used, and what additional options are needed.
The sail stack is represented top-to-bottom. In the example, we see two sail declarations:
org.openrdf.sesame.sailimpl.sync.SyncRdfSchemaRepository
and
org.openrdf.sesame.sailimpl.rdbms.RdfSchemaRepository. The first sail is stacked on top of the
second one (which means that it operates by calling methods on the Sail underneath it). The second
sail is the base sail: it is the lowest of the stack and does not operate on another sail, but directly on
the actual data source. In this example, the base sail is an RDF Schema-aware driver for a relational
database that supports (currently) MySQL (3.23.47 and higher), PostgreSQL (7.0.2 and higher) and
Oracle 9i.
The SyncRdfSchemaRepository is optional, but we strongly recommend using it. This Sail handles
concurrent access issues, without it Sesame would behave unpredictably when several users access
the repository simultaneously.
Other base sails to choose from include:
org.openrdf.sesame.sailimpl.rdbms.RdfRepository:
an non-inferencing
org.openrdf.sesame.sailimpl.omm.versioning.VersioningRdbmsSail:
an
inferencing driver for relational database storage that supports change
tracking.
org.openrdf.sesame.sailimpl.memory.RdfRepository:
non-inferencing
org.openrdf.sesame.sailimpl.memory.RdfSchemaRepository:
an
inferencing driver for storage in main memory that support RDF and RDF
Schema entailment.
org.openrdf.sesame.sailimpl.nativerdf.NativeRdfRepository:
non-
user
password
compressFile
syncDelay
specifies the directory that can be used by the native sail to store its
files.
dir
The native sail also has an optional triple-indexes parameter, with which one can specify the
indexing strategy the native sail should take. We will explain this in more detail in the next section.
The subject-, predicate- and object fields are represented by the characters 's', 'p' and 'o',
respectively. Indexes can be specified by creating 3-letter words from these three characters. Multiple
indexes can be specified by separating these words with comma's, spaces and/or tabs. For example,
the string "spo, pos" specifies two indexes; a subject-predicate-object index and a predicate-objectsubject index.
Of course, creating multiple indexes speeds up querying, but there is a cost factor to take into
account as well: adding and removing data will become more expensive, because each index will
have to be updated. Also, each index takes up additional disk space.
The native store automatically creates/drops indexes upon (re)initialization, so the parameter can be
adjusted and upon the first refresh of the configuration the native store will change its indexing
strategy, without loss of data.
Sesame
release
0.95,
we
provide
an
Support for inter-rule dependency is also added to the customizable inferencer. Now we can state
explicitly which rules are triggered if a rule infers a new statement. This information is given within an
additional tag within the 'rule' one - 'triggers_rule'. It consists of several 'rule' tags with a name
attribute specifying the rules affected.
<!ELEMENTsubjectEMPTY>
<!ATTLISTsubject
varCDATA#IMPLIED
uriCDATA#IMPLIED
patternCDATA#IMPLIED
escapeCDATA#IMPLIED
type(resource)#IMPLIED>
<!ELEMENTpredicateEMPTY>
<!ATTLISTpredicate
varCDATA#IMPLIED
uriCDATA#IMPLIED
patternCDATA#IMPLIED
escapeCDATA#IMPLIED
type(resource)#IMPLIED>
<!ELEMENTobjectEMPTY>
<!ATTLISTobject
varCDATA#IMPLIED
uriCDATA#IMPLIED
patternCDATA#IMPLIED
escapeCDATA#IMPLIED
type(resource)#IMPLIED>
]>
If a 'uri' attribute is present within the 'subject', 'predicate' or 'object' tags, its value is assumed to be a
name of a resource.
The value of the 'var' attribute of the above tags gives the name of that variable. This attribute cannot
be used within an 'axiom' tag.
For example, here are two of the axiomatic triples, as they are defined in the RDF(S) MT semantics.
They appear in the configuration file like this:
<axiom>
<subjecturi="&rdfs;subPropertyOf"/>
<predicateuri="&rdfs;domain"/>
<objecturi="&rdf;Property"/>
</axiom>
<axiom>
<subjecturi="&rdfs;subPropertyOf"/>
<predicateuri="&rdfs;range"/>
<objecturi="&rdf;Property"/>
</axiom>
An example of an inference rule (one stating that - if a resource is used as predicate then it is of 'type'
'Property') looks like:
<rulename="rdfs1">
<premise>
<subjectvar="xxx"/>
<predicatevar="aaa"/>
<objectvar="yyy"/>
</premise>
<consequent>
<subjectvar="aaa"/>
<predicateuri="&rdf;type"/>
<objecturi="&rdf;Property"/>
</consequent>
<triggers_rule>
<rulename="rdfs2"/>
<rulename="rdfs3"/>
<rulename="rdfs4a"/>
<rulename="rdfs5b"/>
<rulename="rdfs6"/>
<rulename="rdfs9"/>
</triggers_rule>
</rule>
In the above example 'xxx', 'aaa' and 'yyy' are variables and 'rdf:type' and 'rdf:Property' are exact
resource URIs.
A 'pattern' attribute with conjunction with an 'escape' attribute is used to define a pattern for matching
resource names. They both can appear only in a triple component denoting variables, e.g. with 'var'
attribute specified. Use '?' to denote any single character and '*' to match any character combination
with length greater than 0.
Use a character declared in 'escape' attribute to escape '?' or '*' characters within pattern. You need
to specify 'pattern' and 'escape' attributes for a given variable only once per rule (note that pattern
and escape are used only once for variable 'id'.
An example of rule using pattern matching:
<rulename="rdfsXI">
<premise>
<subjectvar="xxx"/>
<predicatevar="id"pattern="&rdf;_*"escape="\"/>
<objectvar="yyy"/>
</premise>
<consequent>
<subjectvar="id"/>
<predicateuri="&rdf;type"/>
<objecturi="&rdfs;ContainerMembershipProperty"/>
</consequent>
<triggers_rule>
<rulename="rdfs2"/>
<rulename="rdfs3"/>
<rulename="rdfs6"/>
<rulename="rdfs9"/>
<rulename="rdfs10"/>
</triggers_rule>
</rule>
Note that you can match these triple templates by the values to the variables used in them and the
specified resources used as subjects, predicates or objects of a triple.
4.3.2. Example
Consider the property URI is http://somewhere.org#partOf. In our example domain, we wish to
ensure that this resource is always inserted in the repository, so we add the axiomatic triple stating
that it is a property:
<axiom>
<subjecturi="http://somewhere.org#partOf"/>
<predicateuri="&rdf;type"/>
<objecturi="&rdf;Property"/>
</axiom>
<rulename="userPartOf">
<premise>
<subjectvar="xxx"/>
<predicateuri="http://somewhere.org#partOf"/>
<objectvar="yyy"/>
</premise>
<premise>
We also wish to define that the property is transitive. To this end, we add a single inference rule:
<subjectvar="yyy"/>
<predicateuri="http://somewhere.org#partOf"/>
<objectvar="zzz"/>
</premise>
<consequent>
<subjectvar="xxx"/>
<predicateuri="http://somewhere.org#partOf"/>
<objectvar="zzz"/>
</consequent>
<triggers_rule>
<rulename="rdfs2"/>
<rulename="rdfs3"/>
<rulename="rdfs6"/>
<rulename="userPartOf"/>
</triggers_rule>
</rule>
If the repository has these two triples: T1 - (finger.1, partOf, Hand.Left) and T2 - (Hand.Left, partOf,
Human.1) and if they match the condition (since the same 'yyy' variable is used in both 'premise'
tags) T1.object = T2.subject, a triple corresponding to the 'consequent' tag is added to the repository,
using the current variable bindings and will have the form TInfer = (T1.subject, partOf, T2.object) e.g.
Tinfer=(Finger.1, partOf, Human.1).
4.3.3. Configuration
The
inferencer
repository
based
on
org.openrdf.sesame.sailimpl.rdbms.RdfSchemaRepository sail is defined by a parameter passed to
it during the initialization. To start using the custom inferencer on a repository, add the following extra
parameter to the configuration of that repository:
used
by
custom
The dependency information used by the TMS system is also affected by the rules. The default
inferencer uses dependency database table, that can handle cases where up to two triples leads to
the inference of a new one. Since there can exist inference rules involving arbitrary number of
'premise' tags in the configuration file - the structure of the default dependency table cannot handle
them. To avoid loss of data, the structure of that table is not altered and it is created only if it not exist.
This check is performed during repository initialization phase. So it is better to apply new/modified
inference rules on a completely clean datastorage (database).
5.1. Logging in
If you installed Sesame according to the guidelines in Chapter 2, Installing Sesame, the Sesame
entry page is located at http://[MACHINE_NAME]:8080/sesame/. If you point your browser to this
address, it should display the Sesame entry page shown in Figure 5.1, The Sesame entry page.
Figure 5.1. The Sesame entry page
The screen provides you with a choice of repositories to work on. Since you are not yet logged in,
and no publicly accessible repositories are available, you get a notification that no repositories can be
accessed.
To log in to Sesame, click the "log in" link and provide user name and password (see Figure 5.2, The
Sesame login page).
After you have logged in, you are returned to the entry page, which now shows that you are logged in
and gives you a choice of repositories that you have access on.
Figure 5.3. The Sesame entry page when logged in
After selecting a repository, you come to the actual Sesame function interface (see Figure 5.4, The
repository function screen).
The toolbar at the top of the screen shows user and repository information, and allows the selection
of different actions on the repository. The actions are divided in read actions (such as queries) and
write actions (adding and removing data).
6.3.2. URIs
6.3.3. Literals
6.3.4. Blank Nodes (R1.2)
6.4. Path expressions
6.4.1. Basic path expressions
6.4.2. Path expression short cuts
6.4.3. Optional path expressions
6.5. Select- and construct queries
6.6. Select queries
6.7. Construct queries
6.8. The WHERE clause
6.8.1. Boolean constants
6.8.2. Value (in)equality
6.8.3. Numerical comparisons
6.8.4. The LIKE operator (R1.2)
6.8.5. isResource() and isLiteral()
6.8.6. isURI() and isBNode() (R1.2)
6.8.7. AND, OR, NOT
6.8.8. Nested WHERE clauses (R1.2)
6.9. Other functions
6.9.1. label(), lang() and datatype()
6.9.2. namespace() and localName() (R1.2)
6.10. The LIMIT and OFFSET clauses
6.11. The USING NAMESPACE clause
6.12. Built-in predicates
6.13. Set combinatory operations
6.13.1. UNION (R1.2)
6.13.2. INTERSECT (R1.2)
6.13.3. MINUS (R1.2)
6.14. NULL values
6.15. Query Nesting
6.15.1. The IN operator (R1.2)
6.15.2. ANY and ALL (R1.2)
6.15.3. EXISTS (R1.2)
6.16. Example SeRQL queries
6.16.1. Query 1
6.16.2. Query 2
6.16.3. Query 3
6.17. Comments/feedback
6.18. References
6.19. SeRQL grammar
6.1. Revisions
6.1.1. revision 1.1
SeRQL revision 1.1 is a syntax revision (see issue tracker item SES-75). This document describes
the revised syntax. From Sesame release 1.2-RC1 onwards, the old syntax is no longer supported.
Case sensitive string matching (Section 6.8.4, The LIKE operator (R1.2)).
ANY and ALL keywords (Section 6.15.2, ANY and ALL (R1.2)).
New operations have been marked with (R1.2) where appropriate in this document.
6.2. Introduction
SeRQL ("Sesame RDF Query Language", pronounced "circle") is a new RDF/RDFS query language
that is currently being developed by Aduna as part of Sesame. It combines the best features of other
(query) languages (RQL, RDQL, N-Triples, N3) and adds some of its own. This document briefly
shows all of these features. After reading through this document one should be able to write SeRQL
queries.
Some of SeRQL's most important features are:
Graph transformation.
RDF Schema support.
6.3.1. Variables
Var1
Variables are identified by names. These names must start with a letter or an underscore ('_') and
can be followed by zero or more letters, numbers, underscores, dashes ('-') or dots ('.'). Examples
variable names are:
_var2
unwise.var-name_isnt-it
SeRQL keywords are not allowed to be used as variable names. Currently, the following keywords
are used or reserved for future use in SeRQL: select, construct, from, where, using, namespace, true,
false, not, and, or, like, label, lang, datatype, null, isresource, isliteral, sort, in, union, intersect, minus,
exists, forall, distinct, limit, offset.
Keywords in SeRQL are all case-insensitive, this in contrast to variable names; these are casesensitive.
6.3.2. URIs
There are two ways to write down URIs in SeRQL: either as full URIs or as abbreviated URIs. Full
URIs must be surrounded with "<" and ">". Examples of this are:
<http://www.openrdf.org/index.html>
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
<mailto:sesame@openrdf.org>
<file:///C:\rdffiles\test.rdf>
As URIs tend to be long strings with the first part being shared by several of them (i.e. the
namespace), SeRQL allows one to use abbreviated URIs (or QNames) by defining (short) names for
these namespaces which are called "prefixes". A QName always starts with one of the defined
prefixes and a colon (":"). After this colon, the part of the URI that is not part of the namespace
follows. The first part, consisting of the prefix and the colon, is replaced by the full namespace by the
query engine. Some example QNames are:
sesame:index.html
rdf:type
foaf:Person
6.3.3. Literals
RDF literals consist of three parts: a label, a language tag, and a datatype. The language tag and the
datatype are optional and at most one of these two can accompany a label (a literal can not have
both a language tag and a datatype). The notation of literals in SeRQL has been modelled after their
notation in N-Triples; literals start with the label, which is surrounded by double quotes, optionally
followed by a language tag with a "@" prefix or by a datatype URI with a "^^" prefix. Example literals
are:
"foo"
"foo"@en
"<foo/>"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral>
"<foo/>"^^rdf:XMLLiteral
The SeRQL notation for abbreviated URIs can also be used. When the prefix rdf is mapped to the
namespace http://www.w3.org/1999/02/22-rdf-syntax-ns#, the last example literal could also have
been written down like:
SeRQL has also adopted the character escapes from N-Triples; special characters can be escaped
by prefixing them with a backslash. One of the special characters is the double quote. Normally, a
double quote would signal the end of a literal's label. If the double quote is part of the label, it needs
to be escaped. For example, the sentence John said: "Hi!" can be encoded in a SeRQL literals as:
"John said: \"Hi!\"".
As the backslash is a special character itself, it also needs to be escaped. To encode a single
backslash in a literal's label, two backslashes need to be written in the label. For example, a Windows
directory would be encoded as: "C:\\Program Files\\Apache Tomcat\\".
SeRQL has functions for extracting each of the three parts of a literal. These functions are label, lang,
and datatype. label("foo"@en) extracts the label "foo", lang("foo"@en) extracts the language tag "en",
and datatype("foo"^^rdf:XMLLiteral) extracts the datatype rdf:XMLLiteral. The use of these functions
is explained later.
_:bnode1
This identifies the blank node with internal identifier "bnode1". These blank node identifiers can be
used in the same way that normal URIs or QNames can be used.
Caution: It is important to realize that addressing blank nodes in this way makes SeRQL queries nonportable across repositories. There is no guarantee that in two repositories, even if they contain
identical datasets, the blank node identifiers will be identical. It may well be that "bnode1" in
repository A is a completely different blank node than "bnode1" in repository B. Even in the same
repository, it is not guaranteed that blank node identifiers are stable over updates: if certain
statements are added to or removed from a repository, it is not guaranteed "bnode1" still identifies the
same blank node that it did before the update operation.
Imagine that we want to query an RDF graph for persons who work for companies that are IT
companies. Querying for this information comes down to finding the following pattern in the RDF
graph (gray nodes denote variables):
Figure 6.1. A basic path expression
The SeRQL notation for path expressions resembles the picture above; it is written down as:
{Person}ex:worksFor{Company}rdf:type{ex:ITCompany}
The parts surrounded by curly brackets represent the nodes in the RDF graph, the parts between
these nodes represent the edges in the graph. The direction of the arcs (properties) in SeRQL path
expressions is always from left to right.
In SeRQL queries, multiple path expressions can be specified by seperating them with commas. For
example, the path expression show before can also be written down as two smaller path expressions:
{Person}ex:worksFor{Company},
{Company}rdf:type{ex:ITCompany}
The nodes and edges in the path expressions can be variables, URIs and literals. Also, a node can
be left empty in case one is not interested in the value of that node. Here are some more example
path expressions to illustrate this:
A built-in constraint on this construction is that each value for the variables in the multi-value node is
unique (i.e. they are pairwise disjoint). Therefore, this path expression is equivalent to the following
combination of path expressions and boolean constraints:
FROM
{subj1}pred1{obj1},
{subj1}pred1{obj2},
{subj1}pred1{obj3}
WHEREobj1!=obj2ANDobj1!=obj3ANDobj2!=obj3
Or graphically:
Figure 6.2. Multi-value nodes
Multi-value nodes can also be used when statements share the predicate and object, e.g.:
{subj1,subj2,subj3}pred1{obj1}
When used in a longer path expression, multi-value nodes apply to both the part left of the node and
the part right of the node. The following path expression:
{first}pred1{middle1,middle2}pred2{last}
When using variables in multi-value nodes, a constraint on its values is implicitly added: the variable's
value is not allowed to be equal to any other value in the multi-value node. So, in the first example,
the variables obj1, obj2 and obj3 will not match identical values at the same time. This prevents the
path from matching a single triple three times.
6.4.2.2. Branches
One of the shorts cuts that is likely going to be used most, is the notation for branches in path
expressions. There are lots of situations where one wants to query multiple properties of a single
subject. Instead of repeating the subject over and over again, one can use a semi-colon to attach a
predicate-object combination to the subject of the last part of a path expression, e.g.:
{subj1}pred1{obj1};
pred2{obj2}
Or graphically:
Note that an anonymous variable is used in the middle of the path expressions.
6.4.2.3. Reified statements
The last short cut is a short cut for reified statements. A path expression representing a single
statement (i.e. {node} edge {node}) can be written between the curly brackets of a node, e.g.:
{{reifSubj}reifPred{reifObj}}pred{obj}
This would be equivalent to querying (using "rdf:" as a prefix for the RDF namespace, and
"_Statement" as a variable for storing the statement's URI):
{_Statement}rdf:type{rdf:Statement},
{_Statement}rdf:subject{reifSubj},
{_Statement}rdf:predicate{reifPred},
{_Statement}rdf:object{reifObj},
{_Statement}pred{obj}
Again, graphically:
Figure 6.6. A reification path expression
Optional path expressions differ from 'normal' path expressions in that they do not have to be
matched to find query results. The SeRQL query engine will try to find paths in the RDF graph
matching the path expression, but when it cannot find any paths it will skip the expression and leave
any variables in it uninstantiated (they will have the value null).
Consider an RDF graph that contains information about people that have names, ages, and
optionally e-mail addresses. This is a situation that is likely to be very common in RDF data. A logical
query on this data is a query that yields all names, ages and, when available, e-mail addresses of
people, e.g.:
{Person}ex:name{Name};
ex:age{Age};
ex:email{EmailAddress}
However, using normal path expressions like in the query above, people without e-mail address will
not be returned by the SeRQL query engine. With optional path expressions, one can indicate that a
specific (part of a) path expression is optional. This is done using square brackets, i.e.:
{Person}ex:name{Name};
ex:age{Age};
[ex:email{EmailAddress}]
Or alternatively:
{Person}ex:name{Name};
ex:age{Age},
[{Person}ex:email{EmailAddress}]
In contrast to the first path expressions, this expression will also match with people without an e-mail
address. For these people, the variable EmailAddress will not be assigned a value.
Optional path expressions can also be nested. This is useful in situations where the existence of a
specific path is dependent on the existence of another path. For example, the following path
expression queries for the titles of all known documents and, if the author of the document is known,
the name of the author (if it is known) and his e-mail address (if it is known):
{Document}ex:title{Title};
[ex:author{Author}[ex:name{Name}];
[ex:email{Email}]]
With this path expression, the SeRQL query engine will not try to find the name and e-mail address of
an author when it cannot even find the resource representing the author.
A SeRQL query is typically built up from one to six clauses. For select queries these clauses are:
SELECT, FROM, WHERE, LIMIT, OFFSET and USING NAMESPACE. One might recognize the first
five clauses from SQL, but their usage is slightly different. For construct queries the clauses are the
same with the exception of the first; construct queries start with a CONSTRUCT clause instead of a
SELECT clause.
The first clause (i.e. SELECT or CONSTRUCT) determines what is done with the results that are
found. In a SELECT clause, one can specify which variable values should be returned and in what
order. In a CONSTRUCT clause, one can specify which triples should be returned.
The FROM clause is optional and always contains path expressions, which were explained in the
previous section. It defines the paths in an RDF graph that are relevant to the query. Note that when
the FROM clause is not specified, the query will simply return the constants specified in the SELECT
or CONSTRUCT clause.
The WHERE clause is optional and can contain additional (Boolean) constraints on the values in the
path expressions. These are constraints on the nodes and edges of the paths, which cannot be
expressed in the path expressions themselves.
The LIMIT and OFFSET clauses are also optional. These clauses can be used separately or
combined in order to get a subset of all query answers. Their usage is very similar to the LIMIT and
OFFSET clauses in SQL queries. The LIMIT clause determines the (maximum) amount of query
answers that will be returned. The OFFSET clause determines which query answer will be returned
as the first result, skipping as many query results as specified in this clause.
Finally, the USING NAMESPACE clause is also optional and it can contain namespace declarations;
these are the mappings from prefixes to namespaces that were referred to in one of previous
sections about (abbreviated) URIs.
The WHERE, LIMIT, OFFSET and USING NAMESPACE clauses will be explained in one of the next
sections. The following section will explain the SELECT and FROM clause.
It is also possible to use a '*' in the SELECT clause. In that case, all variable values will be returned
in the order in which they appear in the query, e.g.:
SELECT*
FROM{S}rdfs:label{O}
This query will return the values of the variables S and O, in that order. If a different order is
preferred, one needs to specify the variables in the select clause, e.g.:
SELECTO,S
FROM{S}rdfs:label{O}
SELECTDISTINCT*
FROM{Country1}ex:borders{}ex:borders{Country2}
By default, the results of a select query are not filtered for duplicate rows. Because of the nature of
the above queries, these queries will never return duplicates. However, more complex queries might
result in duplicate result rows. These duplicates can be filtered out by the SeRQL query engine. To
enable this functionality, one needs to specify the DISTINCT keyword after the select keyword. For
example:
USINGNAMESPACE
ex=<http://example.org/things#>
This query defines the inverse of the property foo:hasParent to be foo:hasChild. This is just one
example of a query that produces information that is derived from the original information. Here is
one more example:
CONSTRUCT
{Artist}rdf:type{ex:Painter};
ex:hasPainted{Painting}
FROM
{Artist}rdf:type{ex:Artist};
ex:hasCreated{Painting}rdf:type{ex:Painting}
USINGNAMESPACE
ex=<http://example.org/things#>
This query derives that an artist who has created a painting, is a painter. The relation between the
painter and the painting is modelled to be art:hasPainted.
Instead of specifying a path expression in the CONSTRUCT clause, one can also use a '*'. In that
case, the CONSTRUCT clause is identical to the FROM clause. This allows one to extract a
subgraph from a larger graph, e.g.:
CONSTRUCT*
FROM{SUB}rdfs:subClassOf{SUPER}
The third clause in a query is the WHERE clause. This is an optional clause in which one can specify
Boolean constraints on variables.
The following sections will explain the available Boolean expressions for use in the WHERE clause.
Section 6.8.8, Nested WHERE clauses (R1.2) will explain how WHERE clauses can be nested
inside optional path expressions.
is true if the variable Var contains the URI <foo:bar>, and the expression
Var1!=Var2
SeRQL is currently restricted to numerical comparisons between values with identical datatypes. This
means that e.g. xsd:int values cannot (yet) be compared to xsd:byte values.
If only one of the parameters of a comparison has a datatype, SeRQL will try to assign the other
parameter the same datatype. This means that the above query can still be used when the population
literals don't have any datatype. SeRQL will try to interpret the literal as a positive integer and
compare it to the one million constant.
The LIKE operator can check whether a value matches a specified pattern of characters. '*'
characters can be used as wildcards, matching with zero or more characters. The rest of the
characters are compared lexically. The pattern is surrounded with double quotes, just like a literal's
label.
SELECTCountry
FROM{Country}ex:name{Name}
WHERENameLIKE"Belgium"
USINGNAMESPACE
ex=<http://example.org/things#>
By default, the LIKE operator does a case-sensitive comparison: in the above query, the operator
fails is the variable Name is bound to the value "belgium" instead of "Belgium". Optionally, one can
specify that the operator should perform a case-insensitive comparison:
SELECTCountry
FROM{Country}ex:name{Name}
WHERENameLIKE"belgium"IGNORECASE
USINGNAMESPACE
ex=<http://example.org/things#>
In this query, the operator will succeed for "Belgium", "belgium", "BELGIUM", etc.
The '*' character can be used as a wildcard to indicate substring matches, for example:
SELECTCountry
FROM{Country}ex:name{Name}
WHERENameLIKE"*Netherlands"
USINGNAMESPACE
ex=<http://example.org/things#>
This query will match any country names that end with the string "Netherlands", for example "The
Netherlands".
Boolean constraints and functions can be combined using the AND and OR operators, and negated
using the NOT operator. The NOT operator has the highest presedence, then the AND operator, and
finally the OR operator. Parentheses can be used to override the default presedence of these
operators. The following query is a (kind of artifical) example of this:
SELECT*
FROM{X}Prop{Y}rdfs:label{L}
WHERENOTLLIKE"*FooBar*"AND
(Y=<foo:bar>ORY=<bar:foo>)AND
isLiteral(L)
In query 1, a normal WHERE clause specifies that the EmailAddress found by the optional
expression must begin with the letter "g". The result of this query will be:
Name
EmailAddress
Giancarlo "giancarlo@example.work"
Despite the fact that the match on EmailAddress is defined as optional, the persons named "Michael"
and "Rubens" are not returned. The reason is that the WHERE clause explicitly says that the value
bound to the optional variable must start with the letter "g". For Michael, no value is found, hence the
variable is equal to NULL, and the comparison operator fails on this. For Rubens, a value is found,
but it does not start with the letter "g".
In query 2, however, a nested WHERE-clause is used. This specifies that any binding the optional
expression does must begin with the letter "g", otherwise NULL is returned. The result of this query is:
Name
EmailAddress
Michael
Rubens
Giancarlo "giancarlo@example.work"
The person "Michael" is returned without a result for his email address because there is no email
address known for him at all. The person "Rubens" is returned without a result for his email address
because, although he does have an email address, it does not start with the letter "g".
A query can contain at most one nested WHERE-clause per optional path expression, and at most
one 'normal' WHERE-clause.
The following query retrieves all properties of foaf:Person instances that are in the FOAF namespace.
Notice that as a shorthand for the full URI, we can use a namespace prefix (followed by a colon) as
an argument.
Data:
@prefixfoaf:<http://xmlns.com/foaf/0.1/>.
@prefixex:<http://example.org/>.
_:ardf:typefoaf:Person.
_:amy:nick"Schumi".
_:afoaf:firstName"Michael".
_:afoaf:knows_:b.
_:brdf:typefoaf:Person.
_:bfoaf:firstName"Rubens".
_:bfoaf:nick"Rubinho".
Query:
SELECTfoafProp,Value
FROM{}foafProp{Value}
WHEREnamespace(foafProp)=foaf:
USINGNAMESPACE
foaf=<http://xmlns.com/foaf/0.1/>
Result:
foafProp
Value
<http://xmlns.com/foaf/0.1/firstName "Michael"
<http://xmlns.com/foaf/0.1/knows
_:b
<http://xmlns.com/foaf/0.1/firstName "Rubens"
<http://xmlns.com/foaf/0.1/nick
"Rubinho"
In the following example, the localName() function is used to match two equivalent properties from
different namespaces (using the above data).
Query:
SELECTnick
FROM{}rdf:type{foaf:Person};
nickProp{nick}
WHERElocalName(nickProp)LIKE"nick"
USINGNAMESPACE
foaf=<http://xmlns.com/foaf/0.1/>
Result:
nick
"Schumi"
"Rubinho"
LIMIT and OFFSET allow you to retrieve just a portion of the results that are generated by the query.
If a limit count is given, no more than that many results will be returned (but possibly less, if the query
itself yields less results).
OFFSET says to skip that many results before beginning to return results. OFFSET 0 is the same as
omitting the OFFSET clause. If both OFFSET and LIMIT appear, then OFFSET rows are skipped
before starting to count the LIMIT results that are returned.
The query engine will replace every occurence of rdf: in an abbreviated URI with
http://www.w3.org/1999/02/22-rdf-syntax-ns#, and art: with http://example.org/arts/. So art:hasPainted
will be resolved to the URI http://example.org/arts/hasPainted.
Four namespaces that are used very frequently have been assigned prefixes by default:
Table 6.1. Default namespaces
Prefix Namespace
rdf
http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs
http://www.w3.org/2000/01/rdf-schema#
xsd
http://www.w3.org/2001/XMLSchema#
owl
http://www.w3.org/2002/07/owl#
serql
http://www.openrdf.org/schema/serql#
These prefixes can be used without declaring them. If either of these prefixes is declared explicitly in
a query, this declaration will override the default mapping.
2. X != Y.
3. There is no class Z (Z != Y and Z != X) such that X rdfs:subClassOf Z
and Z rdfs:subClassOf Y.
{X}serql:directSubPropertyOf{Y}
{X}serql:directType{Y}
Query:
SELECTtitle
FROM{book}dc10:title{title}
UNION
SELECTtitle
FROM{book}dc11:title{title}
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>
Result:
title
"The SeRQL Query Language"
"The SeRQL Query Language (revision 1.2)"
"SeRQL"
"SeRQL (updated)"
The union operator matches the projection items in order without taking the name of the projection
item into account:
SELECTtitle,"1.0"AS"version"
FROM{book}dc10:title{title}
UNION
SELECTy,NULL
FROM{x}dc11:title{y}
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>
Result:
title
"The SeRQL Query Language"
version
"1.0"
"1.0"
"SeRQL (updated)"
SeRQL will use the names of the variables in the first operand of the union in the query result.
Data:
@prefixdc10:<http://purl.org/dc/elements/1.0/>.
@prefixdc11:<http://purl.org/dc/elements/1.1/>.
_:adc10:creator"George".
_:adc10:creator"Ringo".
_:bdc11:creator"George".
_:bdc11:creator"Ringo".
_:cdc10:creator"Paul".
_:cdc11:creator"PaulC.".
Query:
SELECTcreator
FROM{album}dc10:creator{creator}
INTERSECT
SELECTcreator
FROM{album}dc11:creator{creator}
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>
Result:
creator
"George"
"Ringo"
Query:
SELECTtitle
FROM{album}dc10:title{title}
MINUS
SELECTtitle
FROM{album}dc10:title{title};
dc10:creator{creator}
WHEREcreatorlike"Paul"
USINGNAMESPACE
dc10=<http://purl.org/dc/elements/1.0/>,
dc11=<http://purl.org/dc/elements/1.1/>
Result:
title
"Sergeant Pepper"
SELECTname
Query:
FROM{}rdf:type{ex:Person};
ex:name{name}
WHEREnameIN(SELECTn
FROM{}rdf:type{ex:Author};
ex:name{n}
)
USINGNAMESPACE
ex=<http://example.org/things#>
Result:
name
"John"
Query:
SELECThighestValue
FROM{node}ex:value{highestValue}
WHEREhighestValue>=ALL(SELECTvalue
FROM{}ex:value{value}
)
USINGNAMESPACE
ex=<http://example.org/things#>
Result:
highestValue
"14"^^xsd:int
In the following example, we use EXIST to determine whether any authors are known that share a
name with a person, and if so, to retrieve that person's names and hobbies.
Data:
@prefixex:<http://example.org/things#>.
_:ardf:typeex:Person.
_:aex:name"John".
_:aex:hobby"Stampcollecting".
_:brdf:typeex:Person.
_:bex:name"Ringo".
_:bex:hobby"Crosswordpuzzles".
_:crdf:typeex:Author.
_:cex:name"John".
_:cex:authorOf"Letitbe".
Query:
SELECTname,hobby
FROM{}rdf:type{ex:Person};
ex:name{name};
ex:hobby{hobby}
WHEREEXISTS(SELECTn
FROM{}rdf:type{ex:Author};
ex:name{n};
ex:authorOf{}
WHEREn=name
)
USINGNAMESPACE
ex=<http://example.org/things#>
Result:
name
hobby
Depicted as a graph, this query searches through the RDF graph for all subgraphs matching the
following template:
6.16.2. Query 2
Description: Find all artefacts whose English title contains the string "night" and the museum where
they are exhibited. The artefact must have been created by someone with first name "Rembrandt".
The artefact and museum should both be represented by their titles.
SELECTDISTINCT
label(ArtefactTitle),MuseumName
FROM
{Artefact}arts:created_by{}arts:first_name{"Rembrandt"},
{Artefact}arts:exhibited{}dc:title{MuseumName},
{Artefact}dc:title{ArtefactTitle}
WHERE
isLiteral(ArtefactTitle)AND
lang(ArtefactTitle)="en"AND
label(ArtefactTitle)LIKE"*night*"
USINGNAMESPACE
dc=<http://purl.org/dc/elements/1.0/>,
arts=<http://example.org/arts/>
Note that this figure only shows the path expressions from the from clause. The where clause poses
additional constraints on the values of the variables which can't be as easily depicted graphically.
6.16.3. Query 3
Description: Find all siblings of class foo:bar.
SELECTDISTINCT
Sibling
FROM
{Sibling,<foo:bar>}rdfs:subClassOf{ParentClass}
Or graphically:
Note that the URI foo:bar is not returned as a result (there is an implicit constraint that doesn't allow
Sibling to be equal to values that occur in the same multi-value node).
6.17. Comments/feedback
Feedback on this document and/or the SeRQL language is highly appreciated and can be posted on
the forum at www.openrdf.org.
6.18. References
RQL
RQL tutorial
RDQL
N-Triples
Turtle
N3
Set_operator::="union"|"minus"|"intersect"
Select_query::="select"("distinct")?Projection
("from"Graph_pattern)?
("limit"<POS_INTEGER>)?
("offset"<POS_INTEGER>)?
Projection::="*"
|Projection_elem(","Projection_elem)*
Projection_elem::=Var_or_value("as"<STRING>)?
Construct_query::="construct"("distinct")?Construct_clause
("from"Graph_pattern)?
("limit"<POS_INTEGER>)?
("offset"<POS_INTEGER>)?
Construct_clause::="*"
|Path_expr_list
Graph_pattern::=Path_expr_list("where"Boolean_expr)?
Path_expr_list::=Path_expr(","Path_expr)*
Path_expr::=Path_expr_head((";")?Path_expr_tail)?
|"["Graph_pattern"]"
Path_expr_head::=NodeEdgeNode
Path_expr_tail::=EdgeNode((";")?Path_expr_tail)?
|"["EdgeNode((";")?Path_expr_tail)?("where"Boolean_expr)?"]"
(";"Path_expr_tail)?
Edge::=Var
|Uri
Node::="{"(Node_elem_list)?"}"
Node_elem_list::=Node_elem(","Node_elem)*
Node_elem::=Var
|Uri
|BNode
|Literal
|Reified_stat
Reified_stat::=NodeEdgeNode
Boolean_expr::=And_expr("or"Boolean_expr)?
And_expr::=Boolean_elem("and"And_expr)?
Boolean_elem::="("Boolean_expr")"
|"true"
|"false"
|"not"Boolean_elem
|Var_or_valueComp_opVar_or_value
|Var_or_valueComp_op("any"|"all")"("Table_query_set")"
|Var_or_value"like"<STRING>
|Var_or_value"in""("Table_query_set")"
|"exists""("Table_query_set")"
|"isResource""("Var")"
|"isURI""("Var")"
|"isBNode""("Var")"
|"isLiteral""("Var")"
Comp_op::="="|"!="|"<"|"<="|">"|">="
Var::=<NC_NAME>
Value::=Uri
|BNode
|Literal
|"null"
|"datatype""("Var")"
Var_or_value::=Var|Value
|"lang""("Var")"
|"label""("Var")"
|"namespace""("Var")"
|"localname""("Var")"
Uri::=<FULL_URI>
|<QNAME>
BNode::=<BNODE>
Literal::=(*ASeRQLliteral,seesectiononliterals*)
|<POS_INTEGER>
|<NEG_INTEGER>
|<DECIMAL>
<FULL_URI>::="<"(*alegalURI,seehttp://www.ietf.org/rfc/rfc2396.txt*)">"
<QNAME>::=<PREFIX_NAME>":"<NC_NAME_CHAR>*
<BNODE>::="_:"<NC_NAME>
<POS_INTEGER>::="+"?[09]+
<NEG_INTEGER>::=""[09]+
<DECIMAL>::=("+"|"")?[09]*"."[09]+
<STRING>::='"'(*zeroormore(encoded)characters*)'"'
<PREFIX_NAME>::=<LETTER><NC_NAME_CHAR>*
|"_"<NC_NAME_CHAR>+
<NC_NAME>::=(<LETTER>|"_")<NC_NAME_CHAR>*
<NC_NAME_CHAR>::=(*seehttp://www.w3.org/TR/RECxmlnames/#NTNCNameChar*)
<LETTER>::=(*seehttp://www.w3.org/TR/RECxml/#NTLetter*)
Note: all keywords are assumed to be case-insensitive. Whitespace characters between tokens are
not significant other than for separating the tokens. Production rules with a head that is surrounded
by angular brackets define tokens (aka "terminals").
Starting at the bottom, the Storage And Inference Layer, or SAIL API, is an internal Sesame API that
abstracts from the storage format used (i.e. whether the data is stored in an RDBMS, in memory, or
in files, for example), and provides reasoning support. SAIL implementations can also be stacked on
top of each other, to provide functionality such as caching or concurrent access handling.
On top of the SAIL, we find Sesame's functional modules, such as the SeRQL, RQL and RDQL query
engines, the admin module, and RDF export. Access to these functional modules is available through
Sesame's Access APIs, consisting of two seperate parts: the Repository API and the Graph API. The
Repository API provides high-level access to Sesame repositories, such as querying, storing of rdf
files, extracting RDF, etc. The Graph API provides more fine-grained support for RDF manipulation,
such as adding and removing individual statements, and creation of small RDF models directly from
code. The two APIs complement each other in functionality, and are in practice often used together.
The Access APIs provide direct access to Sesame's functional modules, either to a client program
(for example, a desktop application that uses Sesame as a library), or to the next component of
Sesame's architecture, the Sesame server. This is a component that provides HTTP- and RMI-based
access to Sesame's APIs. Then, on the remote HTTP/RMI client side, we again find the access APIs,
which can again be used for communicating with Sesame, this time not as a library, but as a server
running on a remote location.
While each part of the Sesame code is publicly available and extensible, most developers will be
primarily interested in the Access APIs, for communicating with a Sesame RDF model or a Sesame
repository from their application. In the next sections, these APIs are described in more detail,
through several code examples.
The Repository API is the central access point for Sesame repositories. It can be used to query and
update the contents of both local and remote repositories. The Repository API handles all the details
of client-server communication, allowing you to handle remote repositories as easily as local ones.
The main interfaces for the repository API can be found in package org.openrdf.sesame.repository.
The implementations of these interface for local and remote repositories can be found in
subpackages of this package.
In the following sections, the repository API is explained in more detail. We will show how one
connects to an existing repository, how to configure a new (local or remote) Sesame repository, and
how to perform queries or other actions.
This creates a local repository that uses main memory for storing its data. The boolean parameter
inferencing indicates whether the repository should do RDF Schema inferencing. Note that the
created repository is volatile: its contents are lost when the object is garbage collected or when the
program is shut down.
For many purposes, the above way of creating a repository is convenient and sufficient. Sometimes,
however, you may want to have a little more control over the exact configuration of a repository. For
example, you may want to have a repository that dumps its contents to file. In such cases, you can
create a RepositoryConfig object, configure it to your liking and pass that object to the
createRepository() method of class LocalRepository.
In the following example, we again create a local repository, but this time we specify that it should use
a file for persistence. First, we need to create a RepositoryConfig object that specifies the
configuration of our required repository. In this example, we create a specification for a repository
with ID "myCustomRep" that uses a stack of two Sails -- a main-memory Sail with schema support,
and a synchronization Sail on top -- and which uses the file C:\TEMP\myCustomRep.rdf as a dump file
for persistent storage.
RepositoryConfigrepConfig=newRepositoryConfig("myCustomRep");
SailConfigsyncSail=new
SailConfig("org.openrdf.sesame.sailimpl.sync.SyncRdfSchemaRepository");
SailConfigmemSail=neworg.openrdf.sesame.sailimpl.memory.RdfSchemaRepositoryConfig(
"C:\\tmp\\myCustomRep.rdf",
RDFFormat.RDFXML);
repConfig.addSail(syncSail);
repConfig.addSail(memSail);
repConfig.setWorldReadable(true);
repConfig.setWorldWriteable(true);
As you can see, by using the SailConfig and RepositoryConfig classes, we can fine-tune the
configuration of our repository. We specify the types of Sails that are to be used, any paramaters for
those Sails (these are the same parameters as described in Chapter 4, Advanced repository
configuration), and read and write permissions. Note that we use the utility class
RdfSchemaRepositoryConfig from package org.openrdf.sesame.sailimpl.memory in this example.
This class is a subclass of SailConfig with main-memory specific methods for easy configuration.
Utility classes like these are available for most Sail implementations.
Now that we have created the repository specification, creating a repository object for it is a snap:
LocalRepositorymyCustomRepository=service.createRepository(repConfig);
The resulting LocalRepository object can then be used to add RDF data, to query the added data,
etc. We will briefly illustrate this in one of the following sections.
7.2.1.2. Remote repositories
When we are using a remote Sesame server, we need to set up a connection with the remote server
and identify the repository that we want to use. The code example below sets up a remote connection
to
a
Sesame
server
over
HTTP. The
server
is
running
at
the
location
http://HOSTNAME/SESAME_DIR/ and we are authenticating ourselves using the username
USERNAME and the password PASSWORD.
java.net.URLsesameServerURL=newjava.net.URL("http://HOSTNAME/SESAME_DIR/");
SesameServiceservice=Sesame.getService(sesameServerURL);
service.login("USERNAME","PASSWORD");
Please note that we are using a URL object in the HTTP example and a URI object in the RMI
example.
The next step is to connect to a specific repository on this server. Assuming that we want to connect
to the repository that is identified by the string remoteRepositoryID:
SesameRepositorymyRepository=service.getRepository("remoteRepositoryID");
Of course, all of the above may not succeed for a number of reasons, such as the user not being
known, having passed an erroneous password, or perhaps the server is not available. You will need
to handle the exceptions thrown for all these cases. These exceptions are all documented in the
Javadoc documentation. For the sake of keeping the examples simple, we will ignore these
exceptions here.
7.2.1.3. Local manipulation of server repositories
In the previous examples, we have seen how to quickly create a local repository on the spot, or how
to connect through a remote communication protocol (like HTTP or RMI) to a running Sesame server.
In this section, we describe a special use case of the repository API, namely one where we want to
extend the functionality of a Sesame server. An example of this is the creation of a new JSP page for
the server. Of course, one can communicate with the local server through the remote access method
shown earlier, but Sesame also allows us to use the local access method on a running server, which
is much more efficient because the data does not need to beserialized and deserialized.
Using this object we can get to the available repositories in an identical fashion as in the local
repository scenario.
Note: this method of accessing the server locally only works if the code that executes the
getLocalService() method is executed within the same Java Virtual Machine as the one on which
the server itself runs. For example, this can be used if you wish to add JSP pages to your website,
and these JSP pages are hosted on the same server as the Sesame server. It will not work, however,
if you are programming a standalone program that happens to be executed on the same machine as
the Sesame server.
A large variety of operations can be performed on repositories in a similar way as the above example.
Of course, all such operations are only allowed if you have sufficient prilileges to perform the
operation. This may require you to log in to the SesameService prior to obtaining the repository object.
For example, if you do not have read acccess on myRepository, the above example will throw an
AccessDeniedException.
Adding RDF to a repository can be done in several ways: the RDF can be in the form of a local file, a
location on the Web, or a java String object. Individual RDF statements can not be added through the
repository API. For that purpose, use the Graph API (see the next section).
The method in the Repository API for adding data is named addData() and it takes several
parameters. The first parameter is the data source. This can be either a java String that contains the
actual RDF, a java.net.URL that specifies the location of an RDF file on the Web, a java.io.File, or
an java.io.InputStream. We will use a URL in the next example.
The addData() method takes several other parameters. The parameter baseURI specifies the base
URI that any relative URIs in the data should be resolved against. format specifies the format of the
data (RDF/XML, N-Triples or Turtle). verifyData is a boolean flag that specifies whether the data
should be checked for syntactic correctness before attempting upload. Finally, listener specifies an
AdminListener object to which status updates during upload, and possible errors and warnings, are
reported.
There are several types of AdminListener available. The AdminMsgCollector collects all messages
and offers convenience methods for checking e.g. whether any errors were reported.
StdOutAdminListener simply prints all messages to StdOut. For other purposes, it can be useful or
necessary to implement your own AdminListener. We will use the StdOutAdminListener in the
following example.
java.net.URLmyRDFData=newjava.net.URL("http://www.foo.com/bar/myRdfFile.rdf");
StringbaseURI="http://my.base.uri#";
booleanverifyData=true;
AdminListenermyListener=newStdOutAdminListener();
myRepository.addData(myRDFData,baseURI,RDFFormat.RDFXML,verifyData,myListener);
To add new statements to this graph, we have to create the building blocks of these statements (the
subject, predicate, and object) first. This can be done using a ValueFactory object, which can be
obtained from the graph, as is shown in the following example:
ValueFactorymyFactory=myGraph.getValueFactory();
Stringnamespace="http://www.foo.com/bar#";
URImySubject=myFactory.createURI(namespace,"actor1");
URImyPredicate=myFactory.createURI(namespace,"hasName");
LiteralmyObject=myFactory.createLiteral("TomHanks");
myGraph.add(mySubject,myPredicate,myObject);
We have now added a single statement to the graph, namely that actor1 has a property hasName
with the value "Tom Hanks".
More statements can be added in the same manner, but sometimes it is more convenient to use the
URIs directly to add properties to it:
URIactorClass=myFactory.createURI(namespace,"Actor");
URIrdfType=myFactory.createURI(org.openrdf.vocabulary.RDF.TYPE);
mySubject.addProperty(rdfType,actorClass);
The above code adds a new statement to the graph that produced the ValueFactory that was used to
create mySubject. This code is equivalent to the following:
URIactorClass=myFactory.createURI(namespace,"Actor");
URIrdfType=myFactory.createURI(org.openrdf.vocabulary.RDF.TYPE);
myGraph.add(mySubject,rdfType,actorClass);
We can remove the graph from the repository in the same way:
myRepository.removeGraph(myGraph);
The produced Graph object allows you to use all of its convenience methods for manipulating the
RDF graph. All changes that are made on the Graph object are directly passed on to the underlying
repository.
A graph created in this fashion will be independent from the repository it was extracted from: changes
to the graph will not be passed on to the repository.
What happens here is the following: the first query derives new statements from the existing
NumberOfWheels statements, changing the object of these statements from "3" to "4". These new
statements are then added to the repository.
The second query selects all NumberOfWheels statements with the object "3" and removes them
from the repository.
Note that in this particular example the order in which the add and remove operation are executed is
important: the add operation uses a query that selects all resource that have a property
NumberOfWheels with value "3". If we had removed all of the matching statements first, the add
operation would not have had any effect.
Ideally, one would have the posibility to use SQL-like INSERT and REPLACE queries to perform this
kind of operations. Extending SeRQL with these types of queries is on the TODO list.
In the previous chapter, we have seen how a Java application can communicate remotely with
Sesame through the API. It is also possible to bypass this API (for example, when the client
application is not a Java app) and communicate with a remote Sesame server directly through the
HTTP protocol. In the first section of this chapter, the available actions and parameters for HTTP
communication are explained.
8.1.1. Logging in
8.1.1.1. Request
In order to get access to non-public repositories on a Sesame server, one needs to log in to it. To do
this, a request should be sent to http://HOSTNAME/SESAME_DIR/servlets/login, supplying the
following parameters:
Table 8.1. Parameters for login
Parameter Required? Description
user
yes
password
no
The user's password. The password is only required in case the concerning
user has a non-empty password.
8.1.1.2. Response
If the log in attempt succeeded, Sesame will respond with HTTP-code 200 ("OK") and will supply a
cookie with a session ID that should be supplied for authentication in subsequent requests. The
name of this cookie is sesame_sid.
8.1.1.3. Errors
If an invalid request is sent (e.g. the username is missing or the password was incorrect) Sesame will
respond with an HTTP error code and a free format error message.
8.1.2.1. Request
To
log
out
from
Sesame
server, one
needs
to
send
a
request
to
http://HOSTNAME/SESAME_DIR/servlets/logout, supplying a session ID cookie that has been
received earlier while logging in. Duplicate log out requests or log out requests for non-existing
sessions are silently ignored.
8.1.2.2. Response
Sesame will respond with HTTP-code 200 ("OK") and a free format text telling you that you have
been logged out.
The following is an example output with two repositories, one read-write and one read-only.
<?xmlversion="1.0"encoding="UTF8"?>
<repositorylist>
<repositoryid="repository1"readable="true"writeable="true">
<title>Publicrepository</title>
</repository>
<repositoryid="repository2"readable="true"writeable="false">
<title>Repository2</title>
</repository>
</repositorylist>
The value of the id attribute is the identifier of the repository. This identifier can be used in
consecutive requests to Sesame to specify which repository that request is about.
SeRQL-select, RQL and RDQL queries are all queries that return, in some way or another, sets of
variable bindings or table-like results. SeRQL-construct queries are a different type of queries that
return free-form RDF documents. Details about SeRQL-construct queries can be found in Evaluating
a SeRQL-construct query.
SeRQL-select,
RQL
and
RDQL
queries
can
be
sent
to
http://HOSTNAME/SESAME_DIR/servlets/evaluateTableQuery. The multipart/form-data encoded
HTTP-POST method is the preferred method. HTTP-GET is also supported but can only be used if all
parameter values consists of ASCII characters only. All requests can or must include the following
parameters:
Table 8.2. Parameters for evaluateTableQuery
Parameter
Required? Description
repository
yes
query
yes
queryLanguage
yes
The query's language. Legal values are SeRQL, RQL and RDQL.
resultFormat
no
Determines the format of the result. Legal values are xml (the default
value) for an XML-representation of the query result, html for a humanreadable HTML-table presentation and rdf for an RDF-representation of
the variable bindings.
serialization
no
8.1.4.2. Response
If all went well, Sesame responds with HTTP-code 200 ("OK") and the results of the query evaluation.
The resultFormat and serialization parameters determine the format of the results and the
Content-Type header of the response:
Table 8.3. Response formats for SeRQL-select, RQL and RDQL queries
xml
html
rdf
rdfxml
text/xml
text/html
Result
An XML
representatio This is the default format and is the best
n of the
format for processing by other applications.
results table.
An HTML
document
An XMLapplication/rdf+x encoded
ml
RDF
document
rdf
ntriples
text/plain
rdf
turtle
application/xturtle
Comments
resultForma serializatio
Content-type
t
n
resultForma serializatio
Content-type
t
n
Result
Comments
document
http://www.ilrt.bris.ac.uk/discovery/2004/01/t
urtle/ for more information about Turtle.
If the selected result format is xml, the output will look something like this:
<?xmlversion="1.0"encoding="UTF8"?>
<tableQueryResult>
<header>
<columnName>X</columnName>
<columnName>Y</columnName>
</header>
<tuple>
<uri>http://www.foo.com/schema.rdf#change</uri>
<literal>Change</literal>
</tuple>
<tuple>
<bNode>node001</bNode>
<literaldatatype="http://www.w3.org/2001/XMLSchema#int">256</literal>
</tuple>
</tableQueryResult>
The document starts with a header listing the names of all result columns. The names of these
columns often represent variable names, but this is not guaranteed. Some query languages also
allow you to use constants or functions in a query's projection. In that case, the name of the column
will be the constant and the function, respectively.
Following the header, zero or more tuple-elements will follow, one for each query result (or row in the
table). Each result consists of a sequence of URIs, bNodes (blank nodes, also know as anonymous
nodes), and/or literals. The values appear in the order in which they were specified in the query,
which is the same as the order in the header.
The example output above shows how URIs, bNodes and literals (with their optional language
encoding or datatype) are exported. Next to these three, there is a fourth type of value that is only
exported by the RQL engine: intersections of classes. If a query asks for a domain or range of a
property, then this domain or range can consist of the intersection of zero or more classes. These
intersections are exported in intersection elements containing zero or more URIs and bNodes:
<?xmlversion="1.0"encoding="UTF8"?>
<tableQueryResult>
<tuple>
<uri>http://www.icom.com/schema1.rdf#creates</uri>
<intersection>
<uri>http://www.icom.com/schema1.rdf#Artifact</uri>
<uri>http://www.schemas.org/general#Stuff</uri>
</intersection>
</tuple>
</tableQueryResult>
When a property doesn't have any range restrictions, its range will be an empty intersection element.
Domains or ranges that consist of exactly one class are exported as normal resources (see first
example), and not as intersections.
8.1.4.3. Errors
If an error occurred while the request was being processed, Sesame will send back an HTTP error
code (i.e. not 200) and a free format error message.
queries
can
be
sent
to
The multipart/form-data encoded
HTTP-POST method is the preferred method. HTTP-GET is also supported but can only be used if all
parameter values consists of ASCII characters only. All requests can or must include the following
parameters:
http://HOSTNAME/SESAME_DIR/servlets/evaluateGraphQuery.
Required? Description
repository
yes
query
yes
queryLanguage
yes
serialization
no
8.1.5.2. Response
If all went well, Sesame responds with HTTP-code 200 (i.e. "OK") and the results of the query
evaluation. The serialization parameter determines the encoding of the returned RDF document
and the Content-Type header of the response:
Table 8.5. RDF encodings for SeRQL-construct queries
Serialization Content-type
RDF
Comments
encoding
rdfxml
XMLapplication/rdf+xml encoded
RDF.
ntriples
text/plain
turtle
application/x-turtle Turtle
What follows are three examples of one and the same RDF document (a possible query result) in
different encodings.
XML-encoded RDF:
<?xmlversion="1.0"encoding="UTF8"?>
<rdf:RDFxml:lang="en"
xmlns:rdf="http://www.w3.org/1999/02/22rdfsyntaxns#"
xmlns:cult="http://www.icom.com/schema.rdf#">
<cult:Cubistrdf:about="http://www.europeanhistory.com/picasso.html">
<cult:paints>
<cult:Paintingrdf:about="http://www.europeanhistory.com/jpg/guernica03.jpg">
<cult:technique>oiloncanvas</cult:technique>
</cult:Painting>
</cult:paints>
<cult:first_name>Pablo</cult:first_name>
<cult:last_name>Picasso</cult:last_name>
</cult:Cubist>
</rdf:RDF>
N-Triples:
<http://www.europeanhistory.com/picasso.html><http://www.w3.org/1999/02/22rdfsyntax
ns#type><http://www.icom.com/schema.rdf#Cubist>.
<http://www.europeanhistory.com/picasso.html><http://www.icom.com/schema.rdf#paints>
<http://www.europeanhistory.com/jpg/guernica03.jpg>.
<http://www.europeanhistory.com/jpg/guernica03.jpg><http://www.w3.org/1999/02/22rdf
syntax#type><http://www.icom.com/schema.rdf#Painting>.
<http://www.europeanhistory.com/jpg/guernica03.jpg>
<http://www.icom.com/schema.rdf#technique>"oiloncanvas"@en.
<http://www.europeanhistory.com/picasso.html><http://www.icom.com/schema.rdf#first_name>
"Pablo"@en.
<http://www.europeanhistory.com/picasso.html><http://www.icom.com/schema.rdf#last_name>
"Picasso"@en.
Turtle:
@prefixcult:<http://www.icom.com/schema.rdf#>.
@prefixrdf:<http://www.w3.org/1999/02/22rdfsyntaxns#>.
<http://www.europeanhistory.com/jpg/guernica03.jpg>acult:Painting;
cult:technique"oiloncanvas"@en.
<http://www.europeanhistory.com/picasso.html>acult:Cubist;
cult:paints<http://www.europeanhistory.com/jpg/guernica03.jpg>;
cult:first_name"Pablo"@en;
cult:last_name"Picasso"@en.
8.1.5.3. Errors
If an error occurred while the request was being processed, Sesame will send back an HTTP error
code (i.e. not 200) and a free format error message.
and
data
can
be
extracted
from
Sesame
by
sending
request
to
http://HOSTNAME/SESAME_DIR/servlets/extractRDF. This operation supports both multipart/formdata encoded HTTP-POST requests as well as HTTP-GET requests. Note that the latter can not be
Parameter
Required? Description
repository
yes
Parameter
Required? Description
schema
no
RdfExport will export the schematical data if the value of this parameter is
on. The schematical data will not be exported if this parameter is missing
or if it has any other value.
no
RdfExport will export the non-ontological data if the value of this parameter
is on. This data will not be exported if this parameter is missing or if it has
any other value.
no
RdfExport will only export the explicitly added statements if the value of
this parameter is on. If this parameter is missing or if it has any other
value, all relevant statements (both explicit and inferred) will be exported.
niceOutput
no
RdfExport will invest extra effort into making the exported data more
readable to humans (e.g. by sorting statements by their subject) if the
value of this parameter is on. If this parameter is missing or if it has any
other value, no such effort is made, allowing RdfExport to export the data
as efficiently as possible.
serialization
no
data
explicitOnly
So, to extract the ontological data only (both explicit and inferred) from a repository test-db on host
www.openrdf.org
you
can
send
an
HTTP-GET
request
to
the
url
http://www.openrdf.org/sesame/servlets/extractRDF?repository=testdb&serialization=rdfxml&onto=on.
8.1.6.2. Response
If all went well, Sesame responds with HTTP-code 200 ("OK"). The body of the response contains the
requested data. The serialization parameter determines the encoding and the Content-Type
header of the response identically to what is described in Table 8.5, RDF encodings for SeRQLconstruct queries.
8.1.6.3. Errors
If an invalid request is sent (e.g. the repository does not exist) Sesame will respond with an HTTP
error code and a free format error message.
can
be
uploaded
to
http://HOSTNAME/SESAME_DIR/servlets/uploadData,
Sesame
by
sending
supplying the following parameters:
it
to
repository
yes
data
yes
The RDF data that should be added to the repository. The format of the
data should match the value of the dataFormat parameter.
dataFormat
no
The format of the data that is uploaded to Sesame. Legal values are rdfxml
(the default value), ntriples and turtle.
6
Parameter
Parameter
Required? Description
baseURI
no
Specifies the base URI of the data for resolving any relative URIs. This
parameter defaults to foo:bar, which is fine if the uploaded data does not
contain any relative URIs.
verifyData
no
resultFormat
no
Determines the response format. Legal values are xml (the default value)
and html.
8.1.7.2. Response
The response is always an HTTP-code 200 ("OK"). Streaming feedback is given on the progress, and
warnings and errors are given if the data contains errors. If the selected format was html, then this
feedback will be formatted in human-readable HTML (when displayed in a browser). If the selected
format was xml, then the feedback will adhere to the following DTD:
<!ELEMENTtransaction(status|notification|warning|error)*>
<!ELEMENTstatus(msg,line?,column?)>
<!ELEMENTnotification(msg,line?,column?,statement?)>
<!ELEMENTwarning(msg,line?,column?,statement?)>
<!ELEMENTerror(msg,line?,column?,statement?)>
<!ELEMENTmsg(#PCDATA)>
<!ELEMENTline(#PCDATA)>
<!ELEMENTcolumn(#PCDATA)>
<!ELEMENTstatement((uri|bNode),uri,(uri|bNode|literal))>
<!ELEMENTuri(#PCDATA)>
<!ELEMENTbNode(#PCDATA)>
<!ELEMENTliteral(#PCDATA)>
<!ATTLISTliteral
xml:langCDATA#IMPLIED
datatypeCDATA#IMPLIED>
<?xmlversion="1.0"encoding="UTF8"?>
<transaction>
<status>
<msg>Loadingdata</msg>
</status>
<status>
<msg>Dataloaded(756bytes)</msg>
</status>
<status>
<msg>Checkingdataforerrors</msg>
</status>
<error>
<msg>Notalegalinteger:HelloWorld!</msg>
<line>483</line>
<column>42</column>
<statement>
<bNode>node1234</bNode>
<uri>http://example.org/schema.rdf#age</uri>
<literaldatatype="http://www.w3.org/2001/XMLSchema#int">HelloWorld!</literal>
The following is a simple example of what the feedback might look like when incorrect data is
uploaded to Sesame:
</statement>
</error>
</transaction>
8.1.7.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors in the data are expressed in the
streaming feedback.
Required? Description
repository
yes
url
yes
A URL pointing at the RDF data that should be added to the repository. The
format of the data at the specified location should match the value of the
dataFormat parameter.
dataFormat
no
The format of the data that is at the specified URL. Legal values are rdfxml
(the default value), ntriples and turtle.
baseURI
no
Specifies the base URI of the data for resolving any relative URIs. This
parameter defaults to the value of url.
verifyData
no
The data at the specified URL will be verified before it is actually added to a
repository if the value of this parameter is on. If this parameter is missing or
if it has any other value, the data will be added directly to the repository.
Verification of the data should only be disabled if the data to upload is
guaranteed to be correct.
resultFormat
no
Determines the response format. Legal values are xml (the default value)
and html.
8.1.8.2. Response
The response format is identical to what is described in Data upload response format.
8.1.8.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors in the data are expressed in the
streaming feedback.
be
removed
from
Sesame
http://HOSTNAME/SESAME_DIR/servlets/clearRepository.
clearing a repository:
by
sending
a
request
to
The following parameters are relevant to
6
Data
Required? Description
repository
yes
resultFormat
no
Determines the response format. Legal values are xml (the default value)
and html.
8.1.9.2. Response
Identical to the reponse when adding data to a repository. See See Data upload response format. for
more information.
8.1.9.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors that occured while clearing the
repository are expressed in the streaming feedback.
can
be
removed
from
Sesame
by
sending
a
requests
to
Currently, Sesame only support removing
of statements using statement patterns: one can specify a subject, predicate and/or object and all
statements that match that pattern will be removed. The following parameters are relevant to the
removal of statements:
http://HOSTNAME/SESAME_DIR/servlets/removeStatements.
Required? Description
repository
yes
subject
no
predicate
no
object
no
resultFormat
no
Determines the result format. Legal values are xml (the default value) and
html.
8.1.10.2. Response
Identical to the reponse when adding data to a repository. See Data upload response format for more
information.
8.1.10.3. Errors
Errors in the requests are signaled using HTTP error codes. Errors that occured while removing
statements from the repository are expressed in the streaming feedback.
If you can't find any relevant information for your problem anywhere, feel free to report a bug or post
a comment on the forum.
You can let us know of your need, explaining why it is crucial, through the
web forum or issue tracker (by adding a new item or by voting for an
existing issue). Of course, there is no guarantee that we will immediately
move it to the top of our ToDo pile.
You can implement it yourself. Yes, that's right: Sesame is open source, and
we thrive on community feedback, not just in the form of comments and bug
reports, but also of code contributions. If you need some feature or
improvement real bad, consider implementing it yourself and sharing the
result with the rest of the Sesame community. We'd be overjoyed to receive
your contribution and include it in Sesame.
You can pay Aduna to implement it for you. Aduna offers commercial
support contracts for Sesame, and if special features are something you
need, we can provide that as part of such support. Contact info@adunasoftware.com for detailed information.
If you want to keep up-to-date on Sesame developments in more detail, consider joining the web
forum. The forum also provides an RSS feed that will provide you with the most recent topics of
discussion. Ideal for staying in touch with the community!
9.2. Troubleshooting
In this section, we identify some commonly encountered problems with the installation, configuration
and use of Sesame, and possible solutions.
Of course, not all possible problems can be found here. If you have a problem that is not described
here, you can get feedback on how to deal with it by posting a message to the openRDF.org forum.
Include as many relevant details as possible, for example, which version of Sesame you are using,
possible java exceptions, log error messages, and so forth.
Other less common problems may also cause this error. In general, take a good look at the detailed
error message or the repository log file (in [SESAME_DIR]/WEB-INF/logs/repositories/) to find out
the cause of the problem.
The root cause here indicates that the JSP page is not correctly compiled: it can not find a particular
Java method.
The cause is that Apache Tomcat sometimes fails to recompile JSP pages after they have been
updated. The compiled JSP pages still refer to methods in the old version of Sesame, which may not
be present anymore in your new version (this is most likely to occur when upgrading to 1.0 from an
earlier release, since a lot of API changes were made for that version).
The solution is to empty Tomcat's JSP compile cache. For Tomcat 4 this cache can be found in
[TOMCAT_DIR]\work\Standalone\localhost\sesame,
for
Tomcat
5
in
[TOMCAT_DIR]\work\Catalina\localhost\sesame. Simply delete all files and folders contained in this
directory and re-load the web interface.
9.2.3. I get "error while adding new triples: Invalid byte 2 of 3-byte UTF-8 sequence"
This is a parser error that can occur during upload of RDF/XML documents to Sesame. The most
likely cause is that the document you are uploading specifies that it is in UTF-8 encoding, but that it
contains non-UTF-8 characters. As UTF-8 is the default character set for XML, it might also be the
case that the document does not specify a character set at all.
The solution is to change the encoding specification of the XML file to the appropriate type. For
example, if the used character set is ISO-8859-1 (this is one of the most common character sets for
"Western" documents), the header of the XML file should be changed to:
<?xmlversion="1.0"encoding="iso88591"?>
9.2.4. I get a warning: "Unable to set namespace prefix 'foo' for namespace ..."
This happens when you try to upload data to a repository which already contains a namespace
declaration with the prefix 'foo', but which maps it to a different namespace URL. In such cases, a
conflict occurs. Sesame handles these cases by assigning a non-conflicting namespace prefix to the
namespace in the new document (for example, 'ns1').
Most of the time, you can safely ignore this warning. Sometimes it indicates a problem with your RDF
document: it may have a mistake in its namespace declarations. In such cases, examine the
namespace declarations in your RDF document and fix any errors before attempting another upload.
For more information on Tomcat memory reservation, see the Tomcat FAQ.
This indicates that the repository you are trying to evaluate this query on is an RDF repository, not an
RDF Schema repository. The former does not have inferencing capabilities.
SeRQL needs an inferencing repository for evaluating queries with built-in operators, because these
operators work on the class hierarchy. Without inferencing support, the results of these operators
would become random and unpredictable.
The solution is to either reformulate your query, removing all use of SeRQL built-in operators, or
create a new repository that does have inferencing capabilities (an RdfSchemaRepository), transfer
your RDF data to it, and use this new repository for your queries.
A.1. PREAMBLE
The purpose of this License is to make a manual, textbook, or other written document "free" in the
sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without
modifying it, either commercially or noncommercially. Secondarily, this License preserves for the
author and publisher a way to get credit for their work, while not being considered responsible for
modifications made by others.
This License is a kind of "copyleft", which means that derivative works of the document must
themselves be free in the same sense. It complements the GNU General Public License, which is a
copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software
needs free documentation: a free program should come with manuals providing the same freedoms
that the software does. But this License is not limited to software manuals; it can be used for any
textual work, regardless of subject matter or whether it is published as a printed book. We
recommend this License principally for works whose purpose is instruction or reference.
A "Secondary Section" is a named appendix or a front-matter section of the Document that deals
exclusively with the relationship of the publishers or authors of the Document to the Document's
overall subject (or to related matters) and contains nothing that could fall directly within that overall
subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section
may not explain any mathematics.) The relationship could be a matter of historical connection with
the subject or with related matters, or of legal, commercial, philosophical, ethical or political position
regarding them.
The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those
of Invariant Sections, in the notice that says that the Document is released under this License.
The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or BackCover Texts, in the notice that says that the Document is released under this License.
A "Transparent" copy of the Document means a machine-readable copy, represented in a format
whose specification is available to the general public, whose contents can be viewed and edited
directly and straightforwardly with generic text editors or (for images composed of pixels) generic
paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to
text formatters or for automatic translation to a variety of formats suitable for input to text formatters.
A copy made in an otherwise Transparent file format whose markup has been designed to thwart or
discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is
called "Opaque".
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo
input format, LaTeX input format, SGML or XML using a publicly available DTD, and standardconforming simple HTML designed for human modification. Opaque formats include PostScript, PDF,
proprietary formats that can be read and edited only by proprietary word processors, SGML or XML
for which the DTD and/or processing tools are not generally available, and the machine-generated
HTML produced by some word processors for output purposes only.
The "Title Page" means, for a printed book, the title page itself, plus such following pages as are
needed to hold, legibly, the material this License requires to appear in the title page. For works in
formats which do not have any title page as such, "Title Page" means the text near the most
prominent appearance of the work's title, preceding the beginning of the body of the text.
If you publish printed copies of the Document numbering more than 100, and the Document's license
notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all
these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover.
Both covers must also clearly and legibly identify you as the publisher of these copies. The front
cover must present the full title with all words of the title equally prominent and visible. You may add
other material on the covers in addition. Copying with changes limited to the covers, as long as they
preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in
other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones
listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must
either include a machine-readable Transparent copy along with each Opaque copy, or state in or with
each Opaque copy a publicly-accessible computer-network location containing a complete
Transparent copy of the Document, free of added material, which the general network-using public
has access to download anonymously at no charge using public-standard network protocols. If you
use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque
copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an Opaque copy (directly or through
your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before
redistributing any large number of copies, to give them a chance to provide you with an updated
version of the Document.
A.5. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under the conditions of sections 2
and 3 above, provided that you release the Modified Version under precisely this License, with the
Modified Version filling the role of the Document, thus licensing distribution and modification of the
Modified Version to whoever possesses a copy of it. In addition, you must do these things in the
Modified Version:
A. Use in the Title Page (and on the covers, if any) a title distinct from that of
the Document, and from those of previous versions (which should, if there
were any, be listed in the History section of the Document). You may use the
same title as a previous version if the original publisher of that version gives
permission.
B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified Version,
together with at least five of the principal authors of the Document (all of its
principal authors, if it has less than five).
C. State on the Title page the name of the publisher of the Modified Version, as
the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications adjacent to the
other copyright notices.
F. Include, immediately after the copyright notices, a license notice giving the
public permission to use the Modified Version under the terms of this
License, in the form shown in the Addendum below.
G. Preserve in that license notice the full lists of Invariant Sections and
required Cover Texts given in the Document's license notice.
I. Preserve the section entitled "History", and its title, and add to it an item
stating at least the title, year, new authors, and publisher of the Modified
Version as given on the Title Page. If there is no section entitled "History" in
the Document, create one stating the title, year, authors, and publisher of
the Document as given on its Title Page, then add an item describing the
Modified Version as stated in the previous sentence.
J. Preserve the network location, if any, given in the Document for public
access to a Transparent copy of the Document, and likewise the network
locations given in the Document for previous versions it was based on.
These may be placed in the "History" section. You may omit a network
location for a work that was published at least four years before the
Document itself, or if the original publisher of the version it refers to gives
permission.
K. In any section entitled "Acknowledgements" or "Dedications", preserve the
section's title, and preserve in the section all the substance and tone of
each of the contributor acknowledgements and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document, unaltered in their text
and in their titles. Section numbers or the equivalent are not considered part
of the section titles.
M. Delete any section entitled "Endorsements". Such a section may not be
included in the Modified Version.
N. Do not retitle any existing section as "Endorsements" or to conflict in title
with any Invariant Section.
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary
Sections and contain no material copied from the Document, you may at your option designate some
or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the
Modified Version's license notice. These titles must be distinct from any other section titles.
You may add a section entitled "Endorsements", provided it contains nothing but endorsements of
your Modified Version by various parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words
as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage
of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made
by) any one entity. If the Document already includes a cover text for the same cover, previously
added by you or by arrangement made by the same entity you are acting on behalf of, you may not
add another; but you may replace the old one, on explicit permission from the previous publisher that
added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their
names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms
defined in section 4 above for modified versions, provided that you include in the combination all of
the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant
Sections of your combined work in its license notice.
The combined work need only contain one copy of this License, and multiple identical Invariant
Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same
name but different contents, make the title of each such section unique by adding at the end of it, in
parentheses, the name of the original author or publisher of that section if known, or else a unique
number. Make the same adjustment to the section titles in the list of Invariant Sections in the license
notice of the combined work.
In the combination, you must combine any sections entitled "History" in the various original
documents, forming one section entitled "History"; likewise combine any sections entitled
"Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled
"Endorsements."
A.9. TRANSLATION
Translation is considered a kind of modification, so you may distribute translations of the Document
under the terms of section 4. Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include translations of some or all Invariant
Sections in addition to the original versions of these Invariant Sections. You may include a translation
of this License provided that you also include the original English version of this License. In case of a
disagreement between the translation and the original English version of this License, the original
English version will prevail.
A.10. TERMINATION
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for
under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void,
and will automatically terminate your rights under this License. However, parties who have received
copies, or rights, from you under this License will not have their licenses terminated so long as such
parties remain in full compliance.
_______________________________________________