Versa Query Structure
Versa defines queries. A query is a combination of literals, traversals and filters, variable references and function calls. Traversala and filters are expressions that match patterns in the RDF model by selecting sets of starting resources and arc resources, and conditions for selecting end-points from the RDF model.
Declaration
Versa allows you to specify namespace and variable declarations before each query. These declarations are superceded by any declarations passed to the implementation via other means (see the variable and namespace section).
Scope (or "Active Graph")
All queries can be expressed within a scope. This is similar to the concept of the Active Graph as defined in SPARQL. The default scope if unspecified is the entire RDF model. If specified, a scope is a query that returns a collection of statements, a subgraph of the RDF model, that was created by a previous query. The subsequent query is then executed using the subgraph as the only set of statements. If the scope query returns any result type besides a collection of statements, then the results of the query is the empty set.
Context
Many Versa constructs are evaluated with regard to a context. The context is a value of any data type, and it can always be referred to explicitloy in an expression using the token "."
Note that there are always a set of variable bindings in effect, and a set of function definitions in scope, but these are not formally considered part of the context, as they are in XPath. Variables and functions are discussed below.
Grouping
Any expression can be grouped using the grouping symbols '(' and ')'. The results if this expression are the same as the result of the nested expression. Grouping is required to specify precedence of a expression when nested in another expression.
Slice Operator
Any expression can be sliced. To perform the slice, the expression is converted to a list, then the slice operator is applied. Below are examples of slice operators:
expression[1] The item at index 1 (the second item) in the list expression[-1] The last item in the list. expression[2:] A list containing all items after the third item. expression[-2:] A list containing the last two items. expression[:2] A list containing the first two items. expression[:-2] A list containing all but the last two items. expression[1:3] A list containing the second and third items. expression[-4:-2] A list containing the second and third to last items.
This is at most syntactic sugar which is already covered by the list operator functions. The current resolution is to "Stick to the functions for list manip: member, item, rest, tail, and slice, etc. and wait on new syntax for a while". Per Versa/2.0 Scratchpad#1007 -- Chimezie
Resource Query
Resource queries define the lowest level of query and are the building blocks for more complex queries. All resource queries return a set, and most sets are of size one (see string queries below for the exception).
Node Query
A node query is a query to retrieve a specific node from the scope. If the node specified exists in the scope, then the results of the query are the set containing that node. If the node does not exist in the scope, then the results are an empty set.
There are two different forms of resource query, the first is an absolute URI queryand is specified using the "<" and ">" tokens surronding the URI. In addition, an implementation may support the deprecated uri query of the form @"URI".
The second form of resource query is using a qname. The prefix of the qname is resolved using the set of in scope namespaces mappings (see the section below on variables and namespaces) and converted to a absolute URI query. If the specified prefix is not defined then the results of the query are the empty set.
The following are examples of node queries:
<http://rdfinference.org> The node with URI http://rdfinference.org @"http://rdfinference.org" Same as above but with the optional old uri ref syntax. spam:eggs if the prefix spam is mapped to the URI http://python.org/, the node with the the URI http://python.org/eggs. myobj:oute66 if the prefix myobj is mapped to the URI urn:oid:this.is.not.really.a.valid.oid.r, the node with the URI urn:oid:this.is.not.really.a.valid.oid.route66.
Note that the lexical rules of XML QNames may limit the situations in they may be used in Versa. For instance, if the URIs are UUIDs in URN form. The full form can always be used to express any valid URI.
Absolute URIs support the escaping of unicode characters. See the section on string escaping for more details.
Literal Query
Similar to node queries, literal queries return a list of zero or more literals from the scope. If the specified literal is not in the scope then the results are an empty set. A literal query allows you to specify a string value and an optinal language or datatype to match against.
As a shortcut, queries for boolean and number values can use the simplified syntax. The processor will convert the short-cut value into an appropriate literal (by the conversion rules) and use that for the query.
When used are arguments to function calls, literals are interpreted as literal values, not as queries. If you would like to pass the results of a literal query to a function, see the query method.
Below are some examples of literal queries.
"foo" All literals with the value of "foo" regardless of language or datatype. "foo"@en_US The literal with the value of "foo" in the language of en_US. "foo"@* All literals with the value of "foo" in any language (but it must have a language). "foo"@!* The literal with the value of "foo" without any language. "foo"^^xsd:string The literal with the value of "foo" in the datatype xsd:string. "foo"^^* All literals with the value of "foo" with any data type (but it must have a datatype). "foo"@!* The literal with the value of "foo" without any datatype. 'foo' Same as first query, apostrophe can be used interchangable with quotes. """ foo ' and " allowed """ A literal query that does not require escaping. 10 translated into the query "10"^^xsd:int. 10.0 translated into the query "10.0"^^xsd:float. true translated into the query "true"^^xsd:boolean.
String Escaping
Strings support the following escape characters to allow embedding of various content within the strings.
"\\" becomes '\' "\"" becomes '"' "\'" becomes '\'' "\n" becomes '\n' "\r" becomes '\r' "\t" becomes '\t' "\uXXYY" becomes unicode character XXYY "\xXX" becomes character XX
Traversal and filter expressions
Traversal and filter expressions are the core of Versa. They provide a system for matching patterns in an RDF model by specifying desired nodes and arcs in the graph representing the model. The traversal and filter operators are the bases of the respective expression, and result in a list.
Note: <uri1> - <uri2> -> <uri3> is equiv. to set(ground(<uri1>)) - set(ground(<uri2>)) -> member(set(ground(<uri3>)),.)
Forward traversal and filter expressions
The forward traversal operator matches patterns based on given sets of subjects and predicates. It returns a list of resulting objects. It takes the following form:
set-expression - set-expression -> filter-expression
The forward filter operator matches patterns based on given sets of subjects and predicates. In contrast to the forward traversal operator, it returns a list of the subjects that result from the patterns rather than the objects. It takes the following form:
set-expression |- set-expression -> filter-expression
In both cases the first set-expression is a evaluated to obtain list (cast if need be) which are the subjects of statements. Each of these resources is set as the context for evaluating the second set-expression, which is treated as a list of predicates(cast if need be). All statements in the model with these subjects and predicates are marked as candidate statements. The object of each of the candidate statements is evaluated as the context of the filter-expression.
In the case of forward traversal, if the result, after conversion to boolean type, of evaluating the filter-expression is true, the object is added to the list of results. In the case of forward filtering, if the result, after conversion to boolean type, of evaluating the filter-expression is true, the subject of the corresponding statement is added to the list of results.
Unless an ordering aggregate function (see below) is used, the order of the resulting elements in the list is undefined in Versa, and is determined by the underlying model.
Backward traversal and filter expression
The backward traversal operator is similar to the forward traversal operator, but it is used to match patterns using the inverses of predicates. A backward traversal expression takes the following form:
filter-expression <- set-expresion - set-expression
The backward filter operator is similar to the forward filter operator, but it is used to match patterns using the inverses of predicates. A backward filter expression takes the following form:
filter-expression <- set-expression -| set-expression
In both cases, the first set is a set of resources which are the objects of statements, the predicates of which are given by the resources in the second set expression. In the case of traversal, the results are a list of matching statements, and the subject of each statement is evaluated as the context of the boolean expression. If the result, after conversion to boolean type, is true, the subject is added to the list of results. Conversions are automatically applied, as with forward traversal expressions. In the case of filter, the results are the objects of the original statements.
Aggregate functions
Versa provides a set of special functions which are designed to be used within traversal operations to transform partial results within the context of the traversal.
sortq
sortq(set, expression [, vsort:number | vsort:string [, vsort:ascending | vsort:descending ] ])
Editor's note: How to express multi-key sorting?
Editor's note: Are there any others that cannot be expressed as operations on the result list? Grouping primitives, perhaps.
Existenstial expressions
Existential expressions are away to all optimizers signal that ahe source expression is over the set of all resources in the model. In all four cases, the expression could be rewritten by addind all() as the missing expression. So the exitensial expression
[ - rdf:type -> rdfs:Class ]
is evaluated as
all() - rdf:type -> rdfs:Class
