Zorba Specific Options and Annotations

In XQuery, options and annotations can both be used to change the behavior of a particular implementation.

Options provide a way to affect the behavior of modules. Annotations can be used to declare properties associated with functions, variables, collections, and indexes. In the following, we present the Zorba specific options and annotations. Also, we describe how they can be dealt with using the C++ API and the introspection module.

Options

Options provide a way to affect the behavior of a particular XQuery module. They can be interpreted either by the XQuery processor itself or by the implementation of a particular module (i.e. an external function).

The syntax for declaring options in the prolog of an XQuery module is

  OptionDecl     ::=    "declare" "option" QName StringLiteral

where QName is the name of the option and StringLiteral is the value that is assigned to this name.

For example, the following declaration disables scripting support in the module that contains the option declaration.

  declare namespace op = "http://www.zorba-xquery.com/options/features";

  declare option op:disable "scripting";

Available Options

Zorba provides a number of options which can be used to determine the behavior of a module. The namespace for all such options starts with http://www.zorba-xquery.com/options. An error is raised (zerr:ZXQP0060) if a module declares an option with a namespace that is equal to or starts with this namespace but the local name refers to an option that is not known to Zorba.

In the following, we describe the set of options available in Zorba.

Enabling or Disabling Features

Zorba provides a couple of extensions to XQuery. For example, the scripting extension and the data definition facility are both features not defined by the W3C but available in Zorba. The user can enable or disable any of these extensions using an option declaration, respectively. The URI of the names of these options is http://www.zorba-xquery.com/options/features. The local name to enable a feature is enable and to disable a feature is disable, respectively. As a value, any of these options allows a comma separated list of feature names (QNames).

For example, to disable the scripting and data definition facility feature, the following option declaration may be used:

  declare namespace op = "http://www.zorba-xquery.com/options/features";
  declare namespace f = "http://www.zorba-xquery.com/features";

  declare option op:disable "f:scripting, f:ddl";

If a given feature doesn't specify a prefix, the name is resolved against the default feature namespace http://www.zorba-xquery.com/features. All Zorba specific features presented in the following are declared in this namespace.

Warnings in Zorba

Warnings are diagnostic messages that report constructions which are not inherently erroneous but which are risky or suggest there may have been an error. Analogous to errors, warnings are identified by QNames. Using options, the user can control whether a particular warning (or all warnings) is (are) enabled, disabled, or treated as an error.

For example, given the following prolog, all warnings are treated as errors:

  declare namespace op = "http://www.zorba-xquery.com/options/warnings";
  declare namespace w = "http://www.zorba-xquery.com/warnings";

  declare option op:error "w:all";

If a given warning doesn't specify a prefix, the name is resolved against the default warning namespace http://www.zorba-xquery.com/warnings. All Zorba specific warnings are defined in this namespace. A comprehensive list of warnings is contained at the end of the C++ header file diagnostic_list.h.

The following snippet causes the warning ZWST0002 (warn for unknown annotations) to be suppressed:

  declare namespace op = "http://www.zorba-xquery.com/options/warnings";

  declare option op:disable "ZWST0002";

Zorba Module Versioning

Zorba provides a way that allows the developer of a module to specify a version of his module without changing the target namespace. An importing module can specify restriction on the version of a module it wants to use. This allows developers to easily declare dependencies between particular versions of a module. In addition, a module can specify on which version of Zorba it depends. Details about module versioning can be found at Versioning Modules.

The options to declare the module and zorba version are listed here for completeness.

To declare version 2.5 of a module that depends on version 2.0 of Zorba, the following option declaration may be used.

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.5";
declare option ver:zorba-version "2.0";

Introspecting Options in XQuery

In a module, the introspection module of Zorba can be used to get the value of an option that is declared.

Specifically, the following function retrieves the value of an option that is declared in the prolog of the module. The function returns the empty sequence if the option is not contained in the static context.

declare function sctx:option($name as xs:QName) as xs:string? external;

Options in Host Languages and External Functions

Besides declaring an option in the prolog of a module, options can also be declared or retrieved using the StaticContext representation in any of the language bindings (i.e. C++, C, PHP, Ruby, Python, or Java).

For instance, the C++ API provides the following two functions to retrieve the value of an option declared in a query and declare options to be used in a query, respectively.

For example, the following code snippet depicts how the higher-order function feature can be enabled for all modules compiled with the given static context.

zorba::StaticContext_t lContext = zorba->createStaticContext();

zorba::Item lEnable = zorba->getItemFactory()->createQName(
  "http://www.zorba-xquery.com/options/features", "", "enable");

lContext->declareOption(lEnable, "hof");

zorba::XQuery_t lQuery = zorba->compileQuery("1+1", lContext);

Declaring and retrieving the value of an option is particularly useful in external functions. The developer of an external function can retrieve the value of an option (from the static context passed to the function). This way, she can customize the behavior of her function.

Annotations

In XQuery (starting version 3.0) annotations may be used to properties associated with functions and variables. Zorba also uses annotations for collections and indexes. Annotations are (QName, value) pairs. The prefix of the QName is resolved using the statically known namespaces. If no prefix is present, the name is the default function namespace.

Available Annotations

XQuery 3.0 Annotation

XQuery 3.0 itself defines two annotations: fn:public and fn:private. Those annotations allow the user to declare a function or a variable as public or private, respectively. A private variable or function is hidden from a module import. That is, it can not be used in the importing module.

For example, a function declared a module as follows, can not be used in a module which imports the mymodule module:

declare %private function mymodule:foo() { "foo" };

Zorba Specific Annotations

Zorba provides a couple of annotations that allow the user to define the semantics of functions, variables, collections, and indexes. All these annotations have the namespace http://www.zorba-xquery.com/annotations.

Deterministic and Nondeterministic Functions

A deterministic function is a function that always evaluates to the same result if it is invoked multiple times with the same arguments during the evaluation of a snapshot. In general, all functions defined by XQuery are deterministic. However, a module developer might develop a function (in a host language) which does not guarantee to be deterministic. For example, a function generating random numbers is clearly not deterministic. Knowing about this property is crucial for the query optimizer to retain the semantics (e.g. caching would lead to incorrect results).

For this reason, Zorba provides two annotations (nondeterministic and deterministic) that allow a developer to declare whether a function is deterministic or not.

As an example, the following snippet declares a nondeterministic random function.

declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare %ann:nondeterministic function random:random() as xs:integer external;

If not specified otherwise, all functions are being treated as deterministic. If some function invokes a nondeterministic function, the invoking function itself must also be declared as nondeterministc, otherwise zerr::ZXQP0040 is raised.

Sequential Functions

In XQuery 3.0, an expression never has any side effects other than constructing new nodes (not even updating expressions, which merely produce a pending update list). Zorba Scripting programs may have side effects. Side effects can be made with statements. An expression is sequential if it contains statements that have side effects (updating some XML, assigning a variable in scope outside of the expression) or that affect the control flow (break, continue, exit returning), or if it invokes a sequential function. Analogously to nondeterministic functions, the compiler needs to be able to infer if an expression is sequential. In order to do so, Zorba provides the ann:sequential and ann:nonsequential annotations. The ann:sequential annotation must be used to declare (external) functions that have side effects. If non of these annotations is present, the default for a function is to be annotated as ann:nonsequential. If a function invokes a sequential function but is itself not declared sequential (i.e. no annotation or ann:nonsequential), an error is raised (zerr:XSST0004).

For example, the http:post function of the http-client module is declared as sequential because invoking it might cause a side effect (e.g. a payment with paypal).

declare %ann:sequential function http:post(
  $href as xs:string,
  $body as item(),
  $content-type as xs:string) as item()+ { ... }
Assignable and Nonassignale Variables

In plain XQuery without scripting, global variables (i.e. those declared in the prolog of a module) can not be assigned a value. In scripting (i.e. if the scripting feature is enabled), however, values can be assigned to a variable.

In order to allow the developer to prevent variable assignments (even with scripting), Zorba provides the ann:nonassignable annotation.

For example, preventing a variable from being assigned in scripting mode could be done as follows:

declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare %ann:nonassignable variable $var := 3;

If a value is assigned to a nonassignable variable, the error XSST0007 in the Zorba error namespace is raised.

Variadic Functions

A function annotated with the ann:variadic annotation is a function of indefinite arity, i.e. one that accepts a variable number of arguments.

For example, the function to create an unordered map with an arbitrary number of key types (see module http://www.zorba-xquery.com/modules/store/data-structures/unordered-map) is declared as follow:

declare %ann:variadic %ann:sequential function map:create(
  $name as xs:QName,
  $key-type as xs:QName) as empty-sequence() external;
Streamable Strings

A function annotated with the streamable annotation is a function that may return an xs:string item whose content is streamed. Such a string is called a streamable string. They have the advantage that their contents does not need to be materialized in memory. If a function consuming such a string is able to process the string in a streaming fashion, this allows for processing of strings with a virtually infinite length.

For example, the following XQuery code, reads a file from disk and returns the contents to the standard output of the calling process. Because the file:read-text function is annotated using the streamable annotation, the file does not have to be materialized in memory.

import module namespace file = "http://expath.org/ns/file";

file:read-text("big_file.txt")

However, the disadvantage is that a streamable string can only be consumed exactly once. If a streamable string is consumed more than once, an error is raised. In order to enable multiple consumers of a streamable string, the materialize function of the string module (http://www.zorba-xquery.com/modules/string) should be used to materialize the entire contents in an (regular) xs:string item.

import module namespace file = "http://expath.org/ns/file";
import module namespace string = "http://www.zorba-xquery.com/modules/string";

let $x := string:materialize(file:read-text("myfile.txt")))
return ($x, $x)

In this example, the file:read-text function returns a streamable string whose contents is used twice in the query. In order to be able to use the value twice, the string:materialize function must be used to materialize the entire contents of the file myfile.txt in memory. Otherwise, the error zerr:ZSTR0055 is raised.

Annotations on Collections and Indexes

The XQuery Data Definition Facility uses annotations to assign properties to collections and indexes. For example, annotations can be used to specify that a collection is unordered or that an index is a value equality index.

The semantics of each of the annotations is given in the documentation about the XQuery Data Definition Facility. However, for completeness, we also list all of the annotations here.

Introspecting Function Annotations

Analog to options, the introspection module of that comes with Zorba allows you to retrieve all annotations declared for a particular function.

declare function sctx:function-annotations(
  $name as xs:QName,
  $arity as xs:integer) as xs:QName* external;
blog comments powered by Disqus