As Semantic Web technologies are getting mature, there is a growing need for RDF applications to access the content of huge, live, non-RDF, legacy databases without having to replicate the whole database into RDF. This document describes D2RQ V0.3, a declarative mapping language for treating non-RDF relational databases as virtual RDF graphs within the Jena Semantic Web development toolkit.
This document describes D2RQ V0.3, a declarative mapping language for treating non-RDF, relational databases as virtual, read-only RDF graphs within the Jena toolkit [Jena]. D2RQ offers a flexible access mechanism to the content of huge, non-RDF databases without having to replicate the database into RDF. Thus, it allows the integration of legazy databases into the data access architecture currently standardized by the W3C Data Access Working Group [DAWG].
Using D2RQ you can:
D2RQ is implemented as a Jena graph, the basic information representation object within the Jena framework. A D2RQ graph wraps one or more local relational databases into a virtual, read-only RDF graph. It rewrites Jena API calls, find() and RDQL queries to application-data-model specific SQL queries. The result sets of these SQL queries are transformed into RDF triples which are passed up to the higher layers of the Jena framework.
For using D2RQ within your applications, you just have to include the d2rq.jar file into your class path and write a D2RQ mapping between the ontology used by your application and your local database.
D2RQ consists of:
D2RQ Example
We are using an example database which stores information about conferences, papers, authors and topics through this manual. The database is mapped to the International Semantic Web Community (ISWC) Ontology.
The examples below show:
D2RQ is a declarative mapping language for describing the relation between relational database schemata and OWL/RDFS ontologies. A D2RQ map is an RDF document.
The language is formally defined by the D2RQ RDF-S Schema.
The D2RQ namespace is http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#
An ontology is mapped to a database schema using d2rq:ClassMaps, d2rq:DatatypePropertyBridges and d2rq:ObjectPropertyBridges. The central object within D2RQ and also the object to start with when writing a new D2RQ map is the ClassMap. A ClassMap represents a class or a group of similar classes of the ontology. A ClassMap specifies how instances of the class are identified. It has a set of PropertyBridges, which specify how the properties of an instance are created. D2RQ maps have the following general structure:
The D2RQ map below relates the table conferences in a database to the class conference in an ontology. You can use it as a template for writing your own maps.
# D2RQ Namespace @prefix d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#> . # Namespace of the ontology @prefix : <http://annotation.semanticweb.org/iswc/iswc.daml#> . # Namespace of the database @prefix db1: <http://www.example.org/dbserver01/db01#> . # Other namespaces @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . # ----------------------------------------------- # Database db1:Database1 rdf:type d2rq:Database; d2rq:odbcDSN "IswcDB"; d2rq:numericColumn "Conferences.ConfID"; d2rq:textColumn "Conferences.Name"; d2rq:textColumn "Conferences.Location" . # ----------------------------------------------- # Conference table / class # # CREATE TABLE Conferences ( # ConfID int(11) default NULL, # Name text, # Location text #) TYPE=MyISAM; db1:Conference rdf:type d2rq:ClassMap ; d2rq:class :Conference ; d2rq:uriPattern "http://conferences.org/comp/confno@@Conferences.ConfID@@" ; d2rq:dataStorage db1:Database1 . db1:eventTitle rdf:type d2rq:DatatypePropertyBridge ; d2rq:property :eventTitle ; d2rq:column "Conferences.Name" ; d2rq:belongsToClassMap db1:Conference ; d2rq:datatype xsd:string . db1:location rdf:type d2rq:DatatypePropertyBridge ; d2rq:property :location ; d2rq:column "Conferences.Location" ; d2rq:belongsToClassMap db1:Conference ; d2rq:datatype xsd:string .
The D2RQ language constructs are described in detail below:
A d2rq:Database defines an ODBC or JDBC connection to a local relational database and specifies the type of the database columns used by D2RQ. A D2RQ map can contain several d2rq:Databases for accessing different local databases.
Properties
d2rq:odbcDSN | The ODBC data source name of the database. |
d2rq:jdbcDriver | The JDBC driver for the database. Used together with d2rq:jdbcDSN. |
d2rq:jdbcDSN | The JDBC data source name of the database. |
d2rq:username | A username if required by the database. |
d2rq:password | A password if required by the database. |
d2rq:textColumn | Specifies that a database column contains text values. D2RQ will use ' quotes around values from this column in SQL statements. |
d2rq:numericColumn | Specifies that a database column contains numeric values. D2RQ will not quote values from this column in SQL statements. |
d2rq:dateColumn | Specifies that a database column contains dates. D2RQ will use # quotes around values from this column in SQL statements. |
d2rq:allowDistinct | Specifies the databases ability to handle DISTINCT correctly. Value: "true" or "false". For example MSAccess cuts fields longer than 256 chars. |
d2rq:expressionTranslator | Specifies a Java class that can translate Jena RDQL expression objects into SQL expressions that are understood by the database. "null" means: no expression translation. Otherwise full SQL 92 is assumed. For Example MySQL is not completely SQL 92 conform (string concatenation ...). |
d2rq:numericColumn, d2rq:textColumn, d2rq:dateColumn define the quoting style used within SQL WHERE clauses. You must define the column type for all columns that are used in d2rq:column, d2rq:pattern, d2rq:uriColumn, d2rq:uriPattern and d2rq:bNodeIdColumns statements. You don't have to define the type for columns that are only used in d2rq:join or d2rq:condition statements.
Example
db1:Database1 rdf:type d2rq:Database; d2rq:odbcDSN "IswcDB"; d2rq:username="joseki"; d2rq:password="*****"; d2rq:numericColumn "Conferences.ConfID"; d2rq:textColumn "Conferences.URI"; d2rq:textColumn "Conferences.Name"; d2rq:textColumn "Conferences.Location"; d2rq:dateColumn "Conferences.Date".
A note on using multiple databases within a single D2RQ map: You cannot link from one database by having a property bridge with d2rq:belongsToClassMap in one database and d2rq:refersToClassMap in the other. Instead, define class maps in both databases that create the same URIs or blank node IDs.
A d2rq:ClassMap represents a class or a group of similar classes of an OWL ontology or RDFS schema. A class map defines how instances of the class are identified. Instances can be identified using URIrefs or blank nodes. URIrefs can be created with d2rq:uriColumn and d2rq:uriPattern. Blank nodes are created with d2rq:bNodeIdColumns. A ClassMap has a set of d2rq:PropertyBridges and is connected to a d2rq:Database which represents the database where instance data is stored.
Properties
d2rq:class | An RDF-S or OWL class. All resources generated by this ClassMap are instances of this class. |
d2rq:uriPattern | Pattern used for URIref construction and reversing. A Pattern is a string containing database column names separated by the rest of the pattern by @@ deliminators. Column names are replaced by values from the database in the mapping process. A uriPattern has to contain the primary key column or columns for identifying a class instance. Database column names have to be given in the form "TableName.ColumnName". If a pattern contains more than one column, then a separating string, which must not occur in the column values, has to be used to separate the column names, in order to allow D2RQ reversing given URIrefs into column values. Example pattern: |
d2rq:uriColumn | Database column containing URIrefs for identifying instances. The database column name have to be given in the form "TableName.ColumnName". |
d2rq:bNodeIdColumns | bNodeIdColumns is used if instances are identified using bNodes. The bNodeIdColumns property specifies a column name or a list of columns separated by commas, which contain the primary key information for identifying instances. The primary key values are used together with the ClassMap name to generate bNode labels. Database column names have to be given in the form "TableName.ColumnName". |
d2rq:translateWith | Assigns a d2rq:TranslationTable to the class map. Values from the d2rq:uriColumn or d2rq:uriPattern will be translated by the table before a resource is generated. See section 3.5 for details. |
d2rq:dataStorage | Reference to a d2rq:Database where the instance data is stored. |
d2rq:containsDuplicates | Must be specified if a class map uses information from tables that are not fully normalized. If the d2rq:containsDuplicates property value is set to "true", then D2RQ adds a DISTINCT clause to all queries using this classMap. "False" is the default value, which doesn't have to be explicitly declared. Adding this property to class maps based on normalized database tables degrades query performance, but doesn't affect query results. |
d2rq:additionalProperty | Adds an AdditionalProperty to all instances of this class. This might be useful for adding rdf:seeAlso properties or other fixed statements to all instances of the class. |
d2rq:condition | Specifies an SQL WHERE condition. An instance of this class will only be generated for database rows that satisfy the condition. Conditions can be used to hide parts of the database from D2RQ, e.g. deny access to data which is older or newer than a certain date. See section Conditional Mappings for details. |
ClassMap property:
d2rq:classMap | Inverse of d2rq:class and unnecessary if d2rq:class is used. Specifies that a d2rq:classMap is used to create instances of an OWL or RDF-S class. |
Example: ClassMap where instances are identified using an URI pattern
:InProceedings rdf:type rdfs:Class ; rdfs:comment "The class Inproceedings (Papers) in the RDF-S schema." . db1:InProceedingsClassMap rdf:type d2rq:ClassMap ; d2rq:uriPattern "http://www.conference.org/conf02004/paper#Paper@@Papers.PaperID@@" ; d2rq:class :InProceedings ; d2rq:dataStorage db1:Database1 .
The d2rq:class property is used to state that all resources generated by the d2rq:ClassMap are instances of an RDFS or OWL class. D2RQ automatically creates the necessary rdf:type triples.
Example: ClassMap where instances are identified using blank nodes
db1:Topic rdf:type d2rq:ClassMap ; d2rq:bNodeIdColumns "Topics.TopicID" ; d2rq:class :Topic ; d2rq:dataStorage db1:Database1 .
In order to recognize bNodes across several find() calls and to be able to map bNodes to instance data in the database, D2RQ encodes the classMap name together with the primary key values in the bNode label. The map above could produce the bNode label "http://www.example.org/dbserver01/db01#Topic@@6", where the number "6" is a primary key value and "http://www.example.org/dbserver01/db01#Topic" is the ClassMap name.
Example: ClassMap for a group of classes with the same properties
If you want to use one ClassMap for a group of classes with the same properties (like Person, Professor, Researcher, Student) that all come from the same table, you must create the rdf:type statements with an object property bridge instead of using d2rq:class.
db1:PersonsClassMap rdf:type d2rq:ClassMap ; d2rq:uriColumn "Persons.URI" ; d2rq:dataStorage db1:Database1 . db1:PersonsType rdf:type d2rq:ObjectPropertyBridge ; d2rq:property rdf:type ; d2rq:pattern "http://annotation.semanticweb.org/iswc/iswc.daml#@@Persons.Type@@" ; d2rq:belongsToClassMap db1:PersonsClassMap .
Here, the class of each person is obtained by prefixing the values of the Persons.Type column with an ontology namespace. If the class names within the ontology can't be constructed directly from values of the Persons.Type column, then a TranslationTable could be used for aligning class names and database values.
Property Bridges relate database table columns to RDF properties. They are used to construct URIs, blank nodes and literals from database values and to reverse given RDF constructs back to database values. There are two types of property bridges:
Common properties
d2rq:belongsToClassMap | Specifies that the property bridge belongs to a d2rq:ClassMap. Must be specified for every property bridge. |
d2rq:property | The RDF property that connects the ClassMap with the object or literal created by the bridge. Must be specified for every property bridge. |
d2rq:join | If the columns used to create the literal value or object are not from the database table(s) that contains the ClassMap's columns, then the tables have to be joined together using one or more d2rq:join properties. See example below. |
d2rq:alias | Aliases are used to join a table with itself. This can be used to express a "works for" or "is child of" property. |
d2rq:condition | Specifies an SQL WHERE condition. The bridge will only generate a statement if the condition holds. A common usage is to suppress triples with empty literal values: d2rq:condition "Table.Column <> ''". See section Conditional Mappings for details. |
d2rq:translateWith | Assigns a d2rq:TranslationTable to the property bridge. Values from the d2rq:column or d2rq:pattern will be translated by the table. See section TranslationTables for details. |
d2rq:valueMaxLength | Asserts that all values of this bridge are not longer than a number of characters. This allows D2RQ to speed up queries. See section Performance Optimization for details. |
d2rq:valueContains | Asserts that all values of this bridge always contain a given string. This allows D2RQ to speed up queries. Most useful in conjunction with d2rq:column. See section Performance Optimization for details. |
d2rq:valueRegex | Asserts that all values of this bridge match a given regular expression. This allows D2RQ to speed up queries. Most useful in conjunction with d2rq:column on columns whose values are very different from other columns in the database. See section Performance Optimization for details. |
PropertyBridge property:
d2rq:propertyBridge | Inverse of d2rq:property and not needed if d2rq:property is used. The d2rq:propertyBridge property specifies which property bridge is used for an RDF property. If the same RDF property is used by several RDF classes, then several property bridges are used to relate the RDF property to the different class maps. |
Example
:title rdf:type rdf:Property . db1:inProceedingsTitle rdf:type d2rq:DatatypePropertyBridge; d2rq:belongsToClassMap db1:InProceedings ; d2rq:property :title ; d2rq:column "Papers.Title" .
This generates RDF triples whose subjects come from the db1:InProceedings ClassMap, the predicate is :title, and the objects are taken from the Papers.Title column.
Datatype property bridges are used to construct literal property values from database values.
Properties
d2rq:column | Database column that contains the literal value. Column names have to be given in the form "TableName.ColumnName". |
d2rq:pattern | Pattern to create the property value. Patterns can be used to extend column values before they are used as property values. Patterns can also be used to merge several column values to one property value. If a pattern contains more than one column, then a separating string, which cannot occur in the column values, has to be used between the column names, in order to allow D2RQ reversing given literals into column values. |
d2rq:datatype | Specifies the datatype of the literal. |
d2rq:lang | Specifies the language of the literal. |
Example: Datatype property bridge using a column from the same table as the class map
:abstract rdf:type rdf:Property . db1:inProceedingsAbstract rdf:type d2rq:DatatypePropertyBridge ; d2rq:belongsToClassMap db1:InProceedings ; d2rq:property :abstract ; d2rq:column "Papers.Abstract" ; d2rq:lang "en" .
The values of the column "Papers.Abstract" is used to create the property abstract. The language is set to English and the property bridge belongs to the class map db1:InProceedings.
Example: Datatype property bridge using information from different database tables
:authorName rdf:type rdf:Property . db1:authorNameBridge rdf:type d2rq:DatatypePropertyBridge ; d2rq:belongsToClassMap db1:Papers ; d2rq:property :authorName ; d2rq:column "Persons.Name"; d2rq:join "Papers.PaperID = Rel_Person_Paper.PaperID" ; d2rq:join "Rel_Person_Paper.PersonID = Persons.PerID" ; d2rq:datatype xsd:string .
This property bridge adds the names of authors to papers. If a paper has several authors, then several authorName properties are added. Because of the n:m relation between InProceedings and Persons, the d2rq:join clauses join the tables Papers and Persons over the table Rel_Person_Paper.
Object property bridges are used to construct URIs and to refer to instances of other class maps.
Properties
d2rq:column | Database column that contains URIs. Column names have to be given in the form "TableName.ColumnName". |
d2rq:pattern | Pattern to create the property value. If a pattern that contains more than one column, then a separating string, which cannot occur in the column values, has to be used between the column names, in order to allow D2RQ reversing given URIs into column values. |
d2rq:refersToClassMap | Reference to a d2rq:ClassMap. d2rq:refersToClassMap has to be used together with d2rq:join when a property refers to instances created by other classMaps. D2RQ uses the uriPattern, uriColumn or bNodeIdColumn properties of the referred class map to construct the property value. See example below. |
Example: Object property bridge using a column from the same table as the class map
:eMail rdf:type rdf:Property , db1:PersonsClassEmail rdf:type d2rq:ObjectPropertyBridge ; d2rq:belongsToClassMap db1:PersonsClassMap ; d2rq:property :email ; d2rq:pattern "mailto:@@Persons.Email@@" .
The pattern "mailto:@@Persons.Email@@" is used together with the values of the column "Persons.Email" to create email property values. The property bridge belongs to the class map db1:PersonsClassMap.
Example: Object property bridge using information from two database tables
:conference rdf:type rdf:Property . db1:conferenceBridge rdf:type d2rq:ObjectPropertyBridge ; d2rq:belongsToClassMap db1:Papers ; d2rq:property :conference ; d2rq:refersToClassMap db1:Conference ; d2rq:join "Papers.Conference = Conferences.ConfID" .
There is a 1:n relation between conferences and papers, which is expressed by the d2rq:join property. The :conference property refers to instances of the class map db1:Conference. D2RQ uses the uriPattern of this class map to construct the property values.
A d2rq:AdditionalProperty can be used to add a fixed statement to all instances generated by a class map. The statement is added to the result sets, if patterns like (ANY, ANY, ANY), (URI, ANY, ANY) or (URI, additionalPropertyName, ANY) are used. The d2rq:additionalProperty property is used to link from the class map to the d2rq:AdditionalProperty definition.
Properties
d2rq:propertyName | The RDF property to be used as the predicate of all fixed statements. |
d2rq:propertyValue | The value to be used as the object of all fixed statements. |
Example:
db1:PersonsClassMap rdf:type d2rq:ClassMap; d2rq:class :Person; d2rq:additionalProperty db1:SeeAlsoStatement. db1:SeeAlsoStatement rdf:type d2rq:AdditionalProperty; d2rq:propertyName rdfs:seeAlso; d2rq:propertyValue <http://annotation.semanticweb.org/iswc2003/>.
This adds an rdfs:seeAlso statement with a fixed URL object to every instance of the class map.
A d2rq:TranslationTable is an additional layer between the database and the RDF world. It translates back and forth between values taken from the database and RDF URIs or literals. A translation table can be attached to a class map or a property bridge using the d2rq:translateWith property. TranslationTables can be used only for mappings that are unique in both directions (1:1).
Properties
d2rq:translation | Adds a d2rq:Translation to the table. |
d2rq:href | Links to a CSV file containing translations. Each line of the file is a translation and contains two strings separated by a comma. The first one is the DB value, the second the RDF value. |
d2rq:javaClass | The qualified name of a Java class that performs the mapping. The class must implement the Translator interface. Custom Translators might be useful for encoding and decoding values, but are limited to 1:1 translations. Further datails can be found in the D2RQ javadocs. |
A d2rq:Translation is a single entry in a d2rq:TranslationTable.
Properties
d2rq:dbValue | A value that might appear in a database column or might be generated by a d2rq:pattern. |
d2rq:rdfValue | A translation of that value to be used in RDF constructs. |
Example: Translating color codes
A typical application are database columns containing type codes or similar enumerated values. A translation table can be used to turn them into RDF resources. In this example, the column ShinyObject.Color contains a color code: "R" for red, "G" for green etc. These codes must be translated into RDF resources: :red, :green etc.
:red rdf:type :Color; :green rdf:type :Color; # ... more colors omitted ... :blue rdf:type :Color; db1:ColorBridge rdf:type d2rq:ObjectPropertyBridge; d2rq:belongsToClassMap db1:ShinyObjectMap; d2rq:property :color; d2rq:column "ShinyObject.Color"; d2rq:translateWith db1:ColorTable. db1:ColorTable rdf:type d2rq:TranslationTable; d2rq:translation [ d2rq:dbValue "R"; d2rq:rdfValue :red; ]; d2rq:translation [ d2rq:dbValue "G"; d2rq:rdfValue :green; ]; # ... more translations omitted ... d2rq:translation [ d2rq:dbValue "B"; d2rq:rdfValue :blue; ].
The d2rq:translateWith statement tells D2RQ to look up database values in the db1:ColorTable. There, a translation must be given for each possible value. If the database contains values which are not in the translation table, D2RQ will not generate a :color statement for that :ShinyObject instance.
Note that the type of the resulting node is determined by the type of the bridge and not by the node type of the rdfValues. db1:ColorBridge is a d2rq:ObjectPropertyBridge. Thus, the translation will create resources. If it would be a d2rq:DatatypePropertyBridge then literals would be created.
Sometimes only certain information from a database should be accessible, because parts of the database might be confidential or outdated. Using d2rq:condition you can specify conditions, which must be satisfied by all accessible data.
You can use d2rq:condition on class map and property bridge level. The d2rq:condition value is added as an additional SQL WHERE clause to all queries generated using the class map or property bridge. If the condition evaluates to FALSE for a SQL result set row, then no triples will be generated from that row.
Example: Using d2rq:condition on a d2rq:ClassMap
db1:InProceedings rdf:type d2rq:ClassMap; d2rq:class :InProceedings; d2rq:uriPattern "http://www.conference.org/conf02004/paper#Paper@@Papers.PaperID@@"; d2rq:condition "Papers.Publish = 1"; d2rq:dataStorage db1:Database1.
Only those papers with a value of 1 in the Papers.Publish column will be accessible. All other papers are ignored.
Example: Filtering zero-length strings
Usually, the special value NULL is used in a database to indicate that some field has no value, or that the value is unknown. Some databases, however, are using a zero-length string ("") instead. D2RQ doesn't generate RDF statements from NULL values, but it doesn't recognize zero-length strings and will generate statements like :Person123 :firstName "". if the person's first name is a zero-length string. In oder to suppress these statements, a d2rq:condition can be added to the property bridge:
db1:PersonsClassFirstName rdf:type d2rq:DatatypePropertyBridge; d2rq:property :firstName; d2rq:column "Persons.FirstName"; d2rq:belongsToClassMap db1:PersonsClassMap; d2rq:condition "Persons.FirstName <> ''".
Example: Relationship type codes
Imagine a table Rel_Paper_Topic that associates rows from a Papers table with rows from a Topics table. The Rel_Paper_Topic table contains a PaperID column to reference the papers, a TopicID to reference the topics, and a RelationshipType column which contains 1 if the topic is a primary topic of the paper, and 2 if it is a secondary topic.
For primary topic relationships, the :primaryTopic property shall be used, and for others the :secondaryTopic property.
We can build a map for this scenario by creating two property bridges. One for :primaryTopic, one for :secondaryTopic. We add a d2rq:condition to both bridges to suppress those statements where the RelationshipType column doesn't have the correct value.
db1:primaryTopic rdf:type d2rq:ObjectPropertyBridge; d2rq:belongsToClassMap db1:InProceedings; d2rq:property :primaryTopic; d2rq:refersToClassMap db1:Topic; d2rq:join "Papers.PaperID = Rel_Paper_Topic.PaperID"; d2rq:join "Rel_Paper_Topic.TopicID = Topics.TopicID"; d2rq:condition "Rel_Paper_Topic.RelationType = 1". db1:secondaryTopic rdf:type d2rq:ObjectPropertyBridge; d2rq:belongsToClassMap db1:InProceedings; d2rq:property :secondaryTopic; d2rq:refersToClassMap db1:Topic; d2rq:join "Papers.PaperID = Rel_Paper_Topic.PaperID"; d2rq:join "Rel_Paper_Topic.TopicID = Topics.TopicID"; d2rq:condition "Rel_Paper_Topic.RelationType = 2".
This section covers hint properties that can be added to property bridges in order to speed up queries: d2rq:valueMaxLength, d2rq:valueRegex and d2rq:valueContains.
Example: Providing a maximum length
db1:PersonsClassFirstName rdf:type d2rq:DatatypePropertyBridge; d2rq:property :firstName; d2rq:column "Persons.FirstName"; d2rq:belongsToClassMap db1:PersonsClassMap; d2rq:valueMaxLength "15".
The d2rq:valueMaxLength property can be used to tell D2RQ that the length of Persons.FirstName values is limited to 15 characters. Using this information, D2RQ doesn't have to look in the database anymore to figure out, that a given FirstName which is longer than 15 characters isn't fitting.
Example: Providing a regular expression
db1:inProceedingsYear rdf:type d2rq:DatatypePropertyBridge; d2rq:property :year; d2rq:column "Papers.Year"; d2rq:belongsToClassMap db1:InProceedings; d2rq:datatype xsd:gYear; d2rq:valueRegex "^[0-9]{4}$".
Here, the d2rq:valueRegex property is used to provide a regular expression for the Papers.Year column. The statement asserts that all values match the regular expression (or are NULL). The expression ^[0-9]{4}$ matches every four-digit number. If you don't want to use the full regular expression machinery, you can use d2rq:valueContains to assert that all values generated by the property bridge contain a certain phrase.
You are geting the largest performance gain by providing hints for property bridges which are using d2rq:column. You should define hints on columns of large tables and on columns that are not indexed by the database. These are the cases where a well-placed optimization hint can result in an order-of-magnitude improvement for some queries. Don't bother to provide hints for property bridges based on d2rq:pattern. These can be optimized very well without hints. In general, the biggest payoff is expected for hints on large tables. If you have a few very large tables with non-indexed columns in your database, that's where you should focus your efforts.
Please keep in mind that hint properties are not intended for filtering of unwanted database values. They are only performance hints. Values that do not fulfill the criteria will still appear in query results if find patterns like (URI, ANY, ANY) are used. In oder to filter values, use d2rq:condition or a translation table with a custom Java class that returns null for unwanted database values.
To configure the D2RQ mapping by modifying the source code is one option. A better one for most of the users is to specify a configuration within the D2RQ map.
Example: Specifying a different query handler
:ProcessingInstructions1 rdf:type d2rq:ProcessingInstructions; d2rq:queryHandler "com.hp.hpl.jena.graph.query.SimpleQueryHandler".
The d2rq:queryHandler property can be used to specify a query handler that is different from the default query handler which in V0.3 is D2RQQueryHandler. So if You wonder wether the bug is in the new features of V0.3, switch back to the slow but highly tested SimpleQueryHandler.
This section describes how D2RQ is used within the Jena 2 Semantic Web framework.
Download
Jena 2 can be downloaded from http://jena.sourceforge.net/downloads.html
D2RQ can be downloaded from http://sourceforge.net/projects/d2rq-map/
Installation
You have to add the "d2rq.jar" file from the "bin" directory of the D2RQ distribution together with the Jena2 jar files to your classpath.
If you want to see how D2RQ translates Jena graph API calls into SQL statements, you can switch into debug mode by calling enableDebug on the D2RQ model or graph object.
The following example shows how the Jena model API is used to check if the paper with the URI "http://www.conference.org/conf02004/paper#Paper1" has an iswc:author property.
import com.hp.hpl.jena.rdf.model.* ; import de.fuberlin.wiwiss.d2rq.*; ... String D2RQMap = "file:///C:/D2RQ/maps/ISWC-d2rq.n3";
ModelD2RQ d2rqModel = null;
// Create D2RQ Model try {
d2rqModel = new ModelD2RQ(D2RQMap);
} catch (D2RQException ex) {
System.out.println(ex.toString());
} // Get the ressource Paper 1 String paperURI = "http://www.conference.org/conf02004/paper#Paper1";
Resource paperRessource = d2rqModel.getResource(paperURI);
// Check if Paper 1 has an auhor property Property author = d2rqModel.createProperty("http://annotation.semanticweb.org/iswc/iswc.daml#author");
if (paperRessource.hasProperty(author)) System.out.println("The paper has an author.");
The following example shows how the Jena graph API is used to get all papers which have been published in 2003.
import com.hp.hpl.jena.graph.* ; import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import com.hp.hpl.jena.datatypes.*; import de.fuberlin.wiwiss.d2rq.*; ... String D2RQMap = "file:///C:/D2RQ/maps/ISWC-d2rq.n3";
GraphD2RQ d2rqGraph = null;
// Create D2RQ Graph try {
d2rqGraph = new GraphD2RQ(D2RQMap);
} catch (D2RQException ex) {
System.out.println(ex.toString());
} // Create a find(spo) pattern Node subject = Node.ANY;
Node predicate = Node.createURI("http://annotation.semanticweb.org/iswc/iswc.daml#year");
RDFDatatype dtYear = TypeMapper.getInstance().getSafeTypeByName("http://www.w3.org/2001/XMLSchema#gYear");
Node object = Node.createLiteral("2003", null, dtYear);
Triple pattern = new Triple(subject, predicate, object);
// Query the graph ExtendedIterator resultiterator = d2rqGraph.find(pattern);
// Output the query results while (resultiterator.hasNext()) {
System.out.println("Result Triple :" + ((Triple) resultiterator.next()).toString());
}
The following example shows how RDQL is used to get all information about the paper with the URI "http://www.conference.org/conf02004/paper#Paper1". The results are displayed using a QueryResultsFormatter.
import com.hp.hpl.jena.rdf.model.* ; import com.hp.hpl.jena.rdql.*; import java.io.PrintWriter; import de.fuberlin.wiwiss.d2rq.*; ... String D2RQMap = "file:///C:/D2RQ/maps/ISWC-d2rq.n3";
ModelD2RQ d2rqModel = null;
// Create D2RQ Model try {
d2rqModel = new ModelD2RQ(D2RQMap);
} catch (D2RQException ex) {
System.out.println(ex.toString());
} // Query the model String rdql = "SELECT ?x, ?y WHERE (<http://www.conference.org/conf02004/paper#Paper1>, ?x, ?y)";
Query query = new Query(rdql);
query.setSource(d2rqModel);
QueryExecution qe = new QueryEngine(query) ;
QueryResults results = qe.exec() ;
// Output the query results using a QueryResultsFormatter QueryResultsFormatter fmt = new QueryResultsFormatter(results) ;
PrintWriter pw = new PrintWriter(System.out) ;
fmt.printAll(pw, " | ") ;
pw.flush() ;
fmt.close() ;
results.close() ;