Wilbur Query Language Comparison
Ora Lassila
Nokia Research Center
$Id: 11-comparison.shtml,v 1.2 2004/05/13 03:20:50 ora Exp $
Introduction
This document is the first draft of an attempt to compare the Wilbur Query Language (WQL, the query language of the Nokia Research Center's "Wilbur" Semantic Web toolkit) to other RDF query languages. The comparison is based on the recently published comparison of some RDF query languages.
Summary of Comparison Results
Two query languages are discussed:
- "Plain" WQL is understood to be anything that can be achieved with a call to one of Wilbur's three query invocation functions: ALL-VALUES, VALUE, RELATEDP (the query API is described in Wilbur's documentation).
- WQL+CL is understood to be "Plain" WQL plus (simple) Common Lisp expressions.
Combining the "plain" query language with Common Lisp makes sense, since WQL was originally designed to be integrated with the programming language, and to be used for providing more expressive data access for programmers. Since Common Lisp can be dynamically interpreted at run time (via the standard function EVAL), it is not unreasonable to think of using CL as parts of queries. Think of it as a scripting language...
Test |
"Plain" WQL |
WQL+CL |
Path Expression |
Yes |
Yes |
Optional Path |
No |
Yes |
Union |
No |
Yes |
Difference |
No |
Yes |
Quantification |
No |
Yes |
Aggregation |
No |
Yes |
Recursion |
Yes |
Yes |
Reification |
Restricted |
Yes |
"Plain" WQL case restricted just like RDQL etc. |
Collections and Containers |
Yes |
Yes |
Namespace |
No |
Yes |
Language |
No |
Restricted |
Will work after a bug in xml:lang support is fixed |
Lexical Space |
No |
Yes |
Value Space |
No |
Restricted |
Will work w/ inference once datatype support is completed |
Entailment |
Yes |
Yes |
Query Details
Note that many "Plain" WQL and WQL+CL queries contain a path expression (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))). This is because Wilbur, out-of-the-box, does not support inference/entailment, and the particular query expression allows one to reach all instances of all subclasses of a class. Because of this, we have added query expressions for something called WQL+CL+inference; this language is basically the same as WQL+CL except that the queries are run against a tuple store that supports the "hidden inference" as described in our paper in ISWC 2002.
Also note that the correct treatment of sub-properties is not included in queries for "Plain" WQL or WQL+CL (although it would be possible, using a similar technique as described above). WQL+CL+inference supports sub-properties without any additional attention from the programmer.
In the following query examples, "plain" queries and "buggy" features (that is, features not functioning properly in the current release) are highlighted in color. It is also assumed that the following Common Lisp forms are evaluated prior to issuing any of the test queries:
(setf *db* (make-instance 'db))
(load-db (make-url "http://www.aifb.uni-karlsruhe.de/WBS/pha/rdf-query/queries/sample.rdf")
:locator "http://www.aifb.uni-karlsruhe.de/WBS/pha/rdf-query/sample.rdf")
(add-namespace "q" "http://www.aifb.uni-karlsruhe.de/WBS/pha/rdf-query/sample.rdf")
Wilbur "harvests" (during the execution of LOAD-DB) all the other namespace prefixes used.
1. Path Expression
"Plain" WQL: |
(all-values !q:Paper '(:seq !q:author :members)) |
WQL+CL: |
same as "Plain" WQL |
WQL+CL+inference: |
same as "Plain" WQL |
2. Optional Path
"Plain" WQL: |
n/a |
WQL+CL: |
(mapcar #'(lambda (author)
(cons author (value author !q:email)))
(all-values !q:Paper '(:seq !q:author :members))) |
WQL+CL+inference: |
same as WQL+CL |
3. Union
"Plain" WQL: |
n/a |
WQL+CL: |
(union (all-values !acm:Topic
'(:seq (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))) !rdfs:label))
(all-values !q:Publication
'(:seq (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))) !q:title))
:test #'literal=) |
WQL+CL+inference: |
(union (all-values !acm:Topic '(:seq (:inv !rdf:type) !rdfs:label))
(all-values !q:Publication '(:seq (:inv !rdf:type) !q:title))
:test #'literal=) |
4. Difference
"Plain" WQL: |
n/a |
WQL+CL: |
(difference (all-values !acm:Topic
'(:seq (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))) !rdfs:label))
(all-values !q:Publication
'(:seq (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))) !q:title))
:test #'literal=) |
WQL+CL+inference: |
(difference (all-values !acm:Topic '(:seq (:inv !rdf:type) !rdfs:label))
(all-values !q:Publication '(:seq (:inv !rdf:type) !q:title))
:test #'literal=) |
5. Quantification
"Plain" WQL: |
n/a |
WQL+CL: |
(let ((pubs (all-values !q:Publication '(:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))))))
(remove-if-not #'(lambda (person)
(every #'(lambda (pub)
(relatedp pub '(:seq !q:author :members) person))
pubs))
(all-values !q:Publication
'(:seq (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf)))
!q:author :members)))) |
WQL+CL+inference: |
(let ((pubs (all-values !q:Publication '(:inv !rdf:type))))
(remove-if-not #'(lambda (person)
(every #'(lambda (pub)
(relatedp pub '(:seq !q:author :members) person))
pubs))
(all-values !q:Publication '(:seq (:inv !rdf:type) !q:author :members)))) |
6. Aggregation
"Plain" WQL: |
n/a |
WQL+CL: |
(length (all-values !q:Paper '(:seq !q:author :members))) |
WQL+CL+inference: |
same as WQL+CL |
7. Recursion
"Plain" WQL: |
(all-values
!"http://www.aifb.uni-karlsruhe.de/WBS/pha/rdf-query/sample.rdf#ACMTopic/Information_Systems"
'(:rep* !acm:SubTopic)) |
WQL+CL: |
same as "Plain" WQL |
WQL+CL+inference: |
same as "Plain" WQL |
8. Reification
"Plain" WQL: |
(all-values !q:Paper '(:seq (:inv !rdf:subject) !dc:creator)) |
WQL+CL: |
(mapcan #'(lambda (statement)
(when (eq (value statement !rdf:predicate) !q:isAbout)
(list (value statement !dc:creator))))
(all-values !q:Paper '(:inv !rdf:subject))) |
WQL+CL+inference: |
same as WQL+CL |
9. Collections and Containers
"Plain" WQL: |
(value !q:Paper '(:seq !q:author :members)) |
WQL+CL: |
same as "Plain" WQL |
WQL+CL+inference: |
same as "Plain" WQL |
10. Namespace
"Plain" WQL: |
n/a |
WQL+CL: |
(dictionary-apropos-list *nodes* "http://aifb.uni-karlsruhe.de/") |
WQL+CL+inference: |
same as "Plain" WQL |
The Wilbur API includes the function dictionary-apropos-list which can be used for satisfying this test. The current implementation is not particularly efficient.
11. Language
"Plain" WQL: |
n/a |
WQL+CL: |
(dolist (topic (all-values !acm:Topic (:inv (:seq !rdf:type (:rep* !rdfs:subClassOf)))))
(let ((labels (all-values topic !rdfs:label)))
(when (find-if #'(lambda (label)
(and (string= (literal-language label) "en")
(string= (literal-string label) "Database Management")))
labels)
(return (find "de" labels :test #'string= :key #'literal-language))))) |
WQL+CL+inference: |
(dolist (topic (all-values !acm:Topic (:inv !rdf:type)))
(let ((labels (all-values topic !rdfs:label)))
(when (find-if #'(lambda (label)
(and (string= (literal-language label) "en")
(string= (literal-string label) "Database Management")))
labels)
(return (find "de" labels :test #'string= :key #'literal-language))))) |
These examples are cumbersome, as they require linear searches and string comparisons, but they illustrate that even this test can be satisfied.
12. Lexical Space
"Plain" WQL: |
n/a |
WQL+CL: |
(remove-if-not #'(lambda (resource)
(string= (literal-string (value resource !q:pages)) "08"))
(all-values !q:Publication
'(:inv (:seq !rdf:type (:rep* !rdfs:subClassOf))))) |
WQL+CL+inference: |
(remove-if-not #'(lambda (resource)
(string= (literal-string (value resource !q:pages)) "08"))
(all-values !q:Publication '(:inv !rdf:type))) |
13. Value Space
"Plain" WQL: |
n/a |
WQL+CL: |
n/a |
WQL+CL+inference: |
(remove-if-not #'(lambda (resource)
(= (literal-value (value resource !q:pages)) 8))
(all-values !q:Publication '(:inv !rdf:type))) |
14. Entailment
"Plain" WQL: |
(all-values !q:Publication '(:inv (:seq !rdf:type (:rep* !rdfs:subClassOf)))) |
WQL+CL: |
same as "Plain" WQL |
WQL+CL+inference: |
(all-values !q:Publication '(:inv !rdf:type)) |
Bibliography
Wilbur: Copyright
Nokia
2004-05-13