# 14. RDF Database and SPARQL

Chapter Contents | Prev | Next
Keyword Search:
www.openlinksw.com
docs.openlinksw.com
Book Home
Contents
Preface
RDF Database and SPARQL
Data Representation
RDF and SPARQL API and SQL
IRI Dereferencing
RDF Views -- Mapping Relational Data to RDF
SPARQL Implementation
SPARQL and XQuery
RDF Inference in Virtuoso
Using Full Text Search in SPARQL
Aggregates in SPARQL
Virtuoso SPARQL Query Service

## 14.5. SPARQL Implementation

Virtuoso's RDF support is at an early implementation stage. The SPARQL language is fairly complete but none of the support functions such as data loading or triple storage are optimized. Many pieces of the present implementation that are written in Virtuoso/PL will be rewritten in C for performance.

Also, the triple store has no specific security model. Thus access rights of the tables and stored procedures involved in the process dictate who can access these features.

All triples of all graphs are stored in a single default system table called DB.DBA.RDF_QUAD. This will change in the next release, where a complex meta-schema system will be introduced for allowing graphs to be stored in different tables, potentially having different index structures, optionally also full text index on long object values. The meta-schema support will also make it possible to map native SQL tables into the RDF SPARQL-queriable space, as well as introduce finer-grained security.

Hence the RDF subsystem is offered for review but is not a productized whole. Benchmark results obtained with it are tentative and reflect a non-optimized state.

The current implementation does not support some SPARQL features.

- Unicode characters in names are not supported.
- Comments inside SPARQL query are not supported when the query is inlined in SQL code.

On the other hand, Virtuoso implements some extensions to SPARQL. One extension, DEFINE ... clause, e.g., define output:valmode "LONG" is described above.

Virtuoso also allows use of expressions in some places where SPARQL only allows constant expressions or variables. For example, the values list of SELECT may contain arbitrary expressions in parenthesis as well as variable names. Expressions may also appear in triples of CONSTRUCT pattern or WHERE pattern: an expression can be used instead of constant or variable name for subject, predicate or object. In this case, an expression is surrounded by backquotes.

The following return all distinct 'fragment' parts of all subjects in all graphs that have some predicate whose value is equal to 2+2.

    SQL>sparql select distinct (bif:subseq (?s, bif:strchr (?s, '#')))
       where {
         graph ?g {
           ?s ?p `2+2` .
           filter (! bif:isnull (bif:strchr (?s, '#') ) )
         } };

    callret
    VARCHAR
    ----------
    #four

This is BNF grammar of SPARQL with all Virtuoso extensions, but without rules for syntax of lexems. Rule numbers in square brackets are from W3C normative SPARQL grammar, asterick means that the rule differs from W3C grammar due to Virtuoso extensions, [Virt] means that the rule is Virtuoso-specific. [DML] stands for data manipulation language extensions from SPARUL.

    [1]*	Query		 ::=  Prolog ( QueryBody | SparulAction* | ( QmStmt ('.' QmStmt)* '.'? ) )
    [1]	QueryBody	 ::=  SelectQuery | ConstructQuery | DescribeQuery | AskQuery
    [2]*	Prolog		 ::=  Define* BaseDecl? PrefixDecl*
    [Virt]	Define		 ::=  'DEFINE' QNAME (QNAME | Q_IRI_REF | String )
    [3]	BaseDecl	 ::=  'BASE' Q_IRI_REF
    [4]	PrefixDecl	 ::=  'PREFIX' QNAME_NS Q_IRI_REF
    [5]*	SelectQuery	 ::=  'SELECT' 'DISTINCT'? ( ( Retcol ( ','? Retcol )* ) | '*' )
    			DatasetClause* WhereClause SolutionModifier
    [6]	ConstructQuery	 ::=  'CONSTRUCT' ConstructTemplate DatasetClause* WhereClause SolutionModifier
    [7]*	DescribeQuery	 ::=  'DESCRIBE' ( VarOrIRIrefOrBackquoted+ | '*' ) DatasetClause* WhereClause? SolutionModifier
    [8]	AskQuery	 ::=  'ASK' DatasetClause* WhereClause
    [9]	DatasetClause	 ::=  'FROM' ( DefaultGraphClause | NamedGraphClause )
    [10]*	DefaultGraphClause	 ::=  SourceSelector SpongeOptionList?
    [11]*	NamedGraphClause	 ::=  'NAMED' SourceSelector SpongeOptionList?
    [Virt]	SpongeOptionList	 ::=  'OPTION' '(' ( SpongeOption ( ',' SpongeOption )* )? ')'
    [Virt]	SpongeOption	 ::=  QNAME PrecodeExpn
    [Virt]	PrecodeExpn	 ::=  Expn	(* Only global variables can occur in Expn, local can not *)
    [13]	WhereClause	 ::=  'WHERE'? GroupGraphPattern
    [14]	SolutionModifier	 ::=  OrderClause? LimitClause? OffsetClause?
    [15]	OrderClause	 ::=  'ORDER' 'BY' OrderCondition+
    [16]*	OrderCondition	 ::=  ( 'ASC' | 'DESC' )? ( FunctionCall | Var | ( '(' Expn ')' ) | ( '[' Expn ']' ) )
    [17]	LimitClause	 ::=  'LIMIT' INTEGER
    [18]	OffsetClause	 ::=  'OFFSET' INTEGER
    [19]	GroupGraphPattern	 ::=  '{' GraphPattern '}'
    [20]	GraphPattern	 ::=  Triples? ( GraphPatternNotTriples '.'? GraphPattern )?
    [21]	GraphPatternNotTriples	 ::=  OptionalGraphPattern | GroupOrUnionGraphPattern | GraphGraphPattern | Constraint
    [22]	OptionalGraphPattern	 ::=  'OPTIONAL' GroupGraphPattern
    [23]	GraphGraphPattern	 ::=  'GRAPH' VarOrBlankNodeOrIRIref GroupGraphPattern
    [24]	GroupOrUnionGraphPattern	 ::=  GroupGraphPattern ( 'UNION' GroupGraphPattern )*
    [25]*	Constraint	 ::=  'FILTER' ( ( '(' Expn ')' ) | BuiltInCall | FunctionCall )
    [26]*	ConstructTemplate	 ::=  '{' ConstructTriples '}'
    [27]	ConstructTriples	 ::=  ( Triples1 ( '.' ConstructTriples )? )?
    [28]	Triples		 ::=  Triples1 ( '.' Triples? )?
    [29]	Triples1	 ::=  VarOrTerm PropertyListNotEmpty | TriplesNode PropertyList
    [30]	PropertyList	 ::=  PropertyListNotEmpty?
    [31]	PropertyListNotEmpty	 ::=  Verb ObjectList ( ';' PropertyList )?
    [32]*	ObjectList	 ::=  ObjGraphNode ( ',' ObjectList )?
    [Virt]	ObjGraphNode	 ::=  GraphNode TripleOptions?
    [Virt]	TripleOptions	 ::=  'OPTION' '(' TripleOption ( ',' TripleOption )? ')'
    [Virt]	TripleOption	 ::=  'INFERENCE' ( QNAME | Q_IRI_REF | SPARQL_STRING )
    [33]	Verb		 ::=  VarOrBlankNodeOrIRIref | 'a'
    [34]	TriplesNode	 ::=  Collection | BlankNodePropertyList
    [35]	BlankNodePropertyList	 ::=  '[' PropertyListNotEmpty ']'
    [36]	Collection	 ::=  '(' GraphNode+ ')'
    [32]	ObjectList	 ::=  GraphNode ( ',' ObjectList )?
    [37]	GraphNode	 ::=  VarOrTerm | TriplesNode
    [38]	VarOrTerm	 ::=  Var | GraphTerm
    [39]*	VarOrIRIrefOrBackquoted	 ::=  Var | IRIref | Backquoted
    [40]*	VarOrBlankNodeOrIRIrefOrBackquoted	 ::=  Var | BlankNode | IRIref | Backquoted
    [Virt]	Retcol	 ::=  ( Var | ( '(' Expn ')' ) | RetAggCall ) ( 'AS' ( VAR1 | VAR2 ) )?
    [Virt]	RetAggCall	 ::=  AggName '(', ( '*' | ( 'DISTINCT'? Var ) ) ')'
    [Virt]	AggName	 ::=  'COUNT' | 'AVG' | 'MIN' | 'MAX' | 'SUM'
    [41]*	Var	 ::=  VAR1 | VAR2 | GlobalVar
    [Virt]	GlobalVar	 ::=  QUEST_COLON_PARAMNAME | DOLLAR_COLON_PARAMNAME | QUEST_COLON_PARAMNUM | DOLLAR_COLON_PARAMNUM
    [42]*	GraphTerm	 ::=  IRIref | RDFLiteral | ( '-' | '+' )? NumericLiteral | BooleanLiteral | BlankNode | NIL | Backquoted
    [Virt]	Backquoted	 ::=  '`' Expn '`'
    [43]	Expn		 ::=  ConditionalOrExpn
    [44]	ConditionalOrExpn	 ::=  ConditionalAndExpn ( '||' ConditionalAndExpn )*
    [45]	ConditionalAndExpn	 ::=  ValueLogical ( '&&' ValueLogical )*	[46]	ValueLogical	 ::=  RelationalExpn
    [47]*	RelationalExpn	 ::=  NumericExpn ( ( ('='|'!='|'<'|'>'|'<='|'>='|'LIKE') NumericExpn ) | ( 'IN' '(' Expns ')' ) )?
    [49]	AdditiveExpn	 ::=  MultiplicativeExpn ( ('+'|'-') MultiplicativeExpn )*
    [50]	MultiplicativeExpn	 ::=  UnaryExpn ( ('*'|'/') UnaryExpn )*
    [51]	UnaryExpn	 ::=   ('!'|'+'|'-')? PrimaryExpn
    [58]	PrimaryExpn	 ::=
    			BracketedExpn | BuiltInCall | IRIrefOrFunction
    			| RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | Var
    [55]	IRIrefOrFunction	 ::=  IRIref ArgList?
    [52]*	BuiltInCall	 ::=
    			( 'STR' '(' Expn ')' )
    			| ( 'IRI' '(' Expn ')' )
    			| ( 'LANG' '(' Expn ')' )
    			| ( 'LANGMATCHES' '(' Expn ',' Expn ')' )
    			| ( 'DATATYPE' '(' Expn ')' )
    			| ( 'BOUND' '(' Var ')' )
    			| ( 'isIRI' '(' Expn ')' )
    			| ( 'isURI' '(' Expn ')' )
    			| ( 'isBLANK' '(' Expn ')' )
    			| ( 'isLITERAL' '(' Expn ')' )
    			| RegexExpn
    [53]	RegexExpn	 ::=  'REGEX' '(' Expn ',' Expn ( ',' Expn )? ')'
    [54]	FunctionCall	 ::=  IRIref ArgList
    [56]*	ArgList	 ::=  ( NIL | '(' Expns ')' )
    [Virt]	Expns	 ::=  Expn ( ',' Expn )*
    [59]	NumericLiteral	 ::=  INTEGER | DECIMAL | DOUBLE
    [60]	RDFLiteral	 ::=  String ( LANGTAG | ( '^^' IRIref ) )?
    [61]	BooleanLiteral	 ::=  'true' | 'false'
    [63]	IRIref		 ::=  Q_IRI_REF | QName
    [64]	QName		 ::=  QNAME | QNAME_NS
    [65]*	BlankNode	 ::=  BLANK_NODE_LABEL | ( '[' ']' )
    [DML]	SparulAction	 ::=
    			CreateAction | DropAction | LoadAction
    			| InsertAction | DeleteAction | ModifyAction | ClearAction
    [DML]*	CreateAction	 ::=  'CREATE' 'SILENT' ? 'GRAPH' ( 'IDENTIFIED' 'BY' )? PrecodeExpn
    [DML]*	InsertAction	 ::=
    			'INSERT' ( ( 'IN' | 'INTO ) 'GRAPH' ( 'IDENTIFIED' 'BY' )? )? PrecodeExpn
    			ConstructTemplate ( DatasetClause* WhereClause SolutionModifier )?
    [DML]*	DeleteAction	 ::=
    			'DELETE' ( 'FROM' 'GRAPH' ( 'IDENTIFIED' 'BY' )? )? PrecodeExpn
    			ConstructTemplate ( DatasetClause* WhereClause SolutionModifier )?
    [DML]*	ModifyAction	 ::=
    			'MODIFY' ( 'GRAPH' ( 'IDENTIFIED' 'BY' )? PrecodeExpn?
    			'DELETE' ConstructTemplate 'INSERT' ConstructTemplate
    			( DatasetClause* WhereClause SolutionModifier )?
    [DML]*	ClearAction	 ::=  'CLEAR' ( 'GRAPH' ( 'IDENTIFIED' 'BY' )? PrecodeExpn )?
    [DML]*	LoadAction	 ::=  'LOAD' PrecodeExpn ( ( 'IN' | 'INTO' ) 'GRAPH' ( 'IDENTIFIED' 'BY' )? PrecodeExpn )?
    [DML]*	DropAction	 ::=  'DROP' 'SILENT'? ( 'GRAPH' ( 'IDENTIFIED' 'BY' )? PrecodeExpn )?
    [Virt]	QmStmt		 ::=  QmSimpleStmt | QmCreateStorage | QmAlterStorage
    [Virt]	QmSimpleStmt	 ::=
    			QmCreateIRIClass | QmCreateLiteralClass | QmDropIRIClass | QmDropLiteralClass
    			| QmCreateIRISubclass | QmDropQuadStorage | QmDropQuadMap
    [Virt]	QmCreateIRIClass	 ::=  'CREATE' 'IRI' 'CLASS' QmIRIrefConst
    			( ( String QmSqlfuncArglist )
    			| ( 'USING' QmSqlfuncHeader ',' QmSqlfuncHeader ) )
    [Virt]	QmCreateLiteralClass	 ::=  'CREATE' 'LITERAL' 'CLASS' QmIRIrefConst
    			'USING' QmSqlfuncHeader ',' QmSqlfuncHeader QmLiteralClassOptions?
    [Virt]	QmDropIRIClass	 ::=  'DROP' 'IRI' 'CLASS' QmIRIrefConst
    [Virt]	QmDropLiteralClass	 ::=  'DROP' 'LITERAL' 'CLASS' QmIRIrefConst
    [Virt]	QmCreateIRISubclass	 ::=  'IRI' 'CLASS' QmIRIrefConst 'SUBCLASS' 'OF' QmIRIrefConst
    [Virt]	QmIRIClassOptions	 ::=  'OPTION' '(' QmIRIClassOption (',' QmIRIClassOption)* ')'
    [Virt]	QmIRIClassOption	 ::=
    			'BIJECTION'
    			| 'RETURNS' STRING ('UNION' STRING)*
    [Virt]	QmLiteralClassOptions	 ::=  'OPTION' '(' QmLiteralClassOption (',' QmLiteralClassOption)* ')'
    [Virt]	QmLiteralClassOption	 ::=
    			( 'DATATYPE' QmIRIrefConst )
    			| ( 'LANG' STRING )
    			| ( 'LANG' STRING )
    			| 'BIJECTION'
    			| 'RETURNS' STRING ('UNION' STRING)*
    [Virt]	QmCreateStorage	 ::=  'CREATE' 'QUAD' 'STORAGE' QmIRIrefConst QmSourceDecl* QmMapTopGroup
    [Virt]	QmAlterStorage	 ::=  'ALTER' 'QUAD' 'STORAGE' QmIRIrefConst QmSourceDecl* QmMapTopGroup
    [Virt]	QmDropStorage	 ::=  'DROP' 'QUAD' 'STORAGE' QmIRIrefConst
    [Virt]	QmDropQuadMap	 ::=  'DROP' 'QUAD' 'MAP' 'GRAPH'? QmIRIrefConst
    [Virt]	QmDrop	 ::=  'DROP' 'GRAPH'? QmIRIrefConst
    [Virt]	QmSourceDecl	 ::=
    			( 'FROM' QTABLE 'AS' PLAIN_ID QmTextLiteral* )
    			| ( 'FROM' PLAIN_ID 'AS' PLAIN_ID QmTextLiteral* )
    			| QmCondition
    [Virt]	QmTextLiteral	 ::=  'TEXT' 'XML'? 'LITERAL' QmSqlCol ( 'OF' QmSqlCol )? QmTextLiteralOptions?
    [Virt]	QmTextLiteralOptions	 ::=  'OPTION' '(' QmTextLiteralOption ( ',' QmTextLiteralOption )* ')'
    [Virt]	QmMapTopGroup	 ::=  '{' QmMapTopOp ( '.' QmMapTopOp )* '.'? '}'
    [Virt]	QmMapTopOp	 ::=  QmMapOp | QmDropQuadMap | QmDrop
    [Virt]	QmMapGroup	 ::=  '{' QmMapOp ( '.' QmMapOp )* '.'? '}'
    [Virt]	QmMapOp		 ::=
    			( 'CREATE' QmIRIrefConst 'AS' QmMapIdDef )
    			| ( 'CREATE' 'GRAPH'? QmIRIrefConst 'USING' 'STORAGE' QmIRIrefConst QmOptions? )
    			| ( QmNamedField+ QmOptions? QmMapGroup )
    			| QmTriples1
    [Virt]	QmMapIdDef	 ::=  QmMapTriple | ( QmNamedField+ QmOptions? QmMapGroup )
    [Virt]	QmMapTriple	 ::=  QmFieldOrBlank QmVerb QmObjField
    [Virt]	QmTriples1	 ::=  QmFieldOrBlank QmProps
    [Virt]	QmNamedField	 ::=  ('GRAPH'|'SUBJECT'|'PREDICATE'|'OBJECT') QmField
    [Virt]	QmProps		 ::=  QmProp ( ';' QmProp )?
    [Virt]	QmProp		 ::=  QmVerb QmObjField ( ',' QmObjField )*
    [Virt]	QmObjField	 ::=  QmFieldOrBlank QmCondition* QmOptions?
    [Virt]	QmIdSuffix	 ::=  'AS' QmIRIrefConst
    [Virt]	QmVerb		 ::=  QmField | ( '[' ']' ) | 'a'
    [Virt]	QmFieldOrBlank	 ::=  QmField | ( '[' ']' )
    [Virt]	QmField		 ::=
    			NumericLiteral
    			| RdfLiteral
    			| ( QmIRIrefConst ( '(' ( QmSqlCol ( ',' QmSqlCol )* )? ')' )? )
    			| QmSqlCol
    [Virt]	QmCondition	 ::=  'WHERE' ( ( '(' SQLTEXT ')' ) | String )
    [Virt]	QmOptions	 ::=  'OPTION' '(' QmOption ( ',' QmOption )* ')'
    [Virt]	QmOption	 ::=  'EXCLUSIVE' | ( 'ORDER' INTEGER ) | ( 'USING' PLAIN_ID )
    [Virt]	QmSqlfuncHeader	 ::=  'FUNCTION' SQL_QTABLECOLNAME QmSqlfuncArglist 'RETURNS' QmSqltype
    [Virt]	QmSqlfuncArglist	 ::=  '(' ( QmSqlfuncArg ( ',' QmSqlfuncArg )* )? ')'
    [Virt]	QmSqlfuncArg	 ::=  ('IN' | QmSqlId) QmSqlId QmSqltype
    [Virt]	QmSqltype	 ::=  QmSqlId ( 'NOT' 'NULL' )?
    [Virt]	QmSqlCol	 ::=  QmSqlId | spar_qm_sql_id
    [Virt]	QmSqlId		 ::=  PLAIN_ID | 'TEXT' | 'XML'
    [Virt]	QmIRIrefConst	 ::=  IRIref | ( 'IRI' '(' String ')' )

### 14.5.1. SPARQL and XQuery

In the current implementation, the XQuery Function Library is not available from SPARQL .

As a temporary workaround, string parsing functions are made available, because they are widely used in W3C DAWG examples and the like. They are:

    xsd:boolean (in strg any) returns integer
    xsd:dateTime (in strg any) returns datetime
    xsd:double (in strg varchar) returns double precision
    xsd:float (in strg varchar) returns float
    xsd:integer (in strg varchar) returns integer

(assuming that the query contains declaration 'PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>')

Previous RDF Views -- Mapping Relational Data to RDF | Chapter Contents | Next RDF Inference in Virtuoso