Extensions to the XQuery Processing Model


To support updates, DataDirect XQuery extends the XQuery processing model, as discussed in this section.


Extension to Function Declaration

The syntax of an XQuery function declaration is extended to include an optional keyword, updating, as shown in the following BNF syntax for a function declaration:

FunctionDecl := "declare" "updating"? "function" QName
  "(" ParamList? ") ("as" SequenceType)?
   (EnclosedExpr | "external")  

If the keyword "updating" is not specified, the semantics are as specified in XQuery 1.0. If the keyword "updating" is specified, the semantics are as follows:

  • The XQuery expression must be an updating expression.
  • The function declaration must be declared without "as SequenceType" or the sequence type must be an empty sequence. This means that an updating function cannot return a value.
  • The function declaration cannot be declared as external (except for the built-in functions).

Here is an example of a declaration for a user-defined updating function:

declare updating function local:delete($rows as element()*) 
{ 
ddtek:sql-delete($rows) 
}; 
local:delete(collection(’test’)/test)  

Extensions to XQuery Expressions

The basic building block of XQuery is an expression. Because of the update capability of DataDirect XQuery, two types of expressions exist for XQueries when using DataDirect XQuery:

  • Updating expressions, which can modify the state of an existing node
  • Non-updating expressions, which cannot modify the state of an existing node

An expression is either updating or non-updating; therefore, an XQuery does either an update or returns a result, not both. The following is an example of an updating expression in the Return clause of a FLWOR expression:

for $u in collection("users")//users 
return 
 ddtek:sql-insert ("users2", "userid", $u/userid, name", $u/name)  

Updating expressions can occur only in the following XQuery expressions:

  • FLWOR expressions
  • Typeswitch expressions
  • Conditional expressions
  • Comma expressions
  • Parenthesized expressions

All other XQuery expressions cannot contain an operand that is an updating expression; if it does, a static error is raised.

FLWOR Expressions

To support updates of relational databases, DataDirect XQuery extends the semantics of a FLWOR expression in the following ways:

  • The For, Let, Where, and Order By clauses of a FLWOR expression cannot contain updating expressions.
  • If the Return clause contains a non-updating expression, the FLWOR expression is a non-updating expression.
  • If the Return clause contains an updating expression, the FLWOR expression is an updating expression.

The following example shows a FLWOR expression that is an updating expression:

for $u in collection("USERS")//USERS 
return 
 ddtek:sql-insert ("USERS2", "USERID", $u/USERID, "NAME", $u/NAME)  

Typeswitch Expressions

To support updates of relational databases, DataDirect XQuery extends the semantics of a typeswitch expression in the following ways:

  • The operand of a typeswitch expression cannot contain an updating expression.
  • If any branch contains an updating expression, the typeswitch expression is an updating expression. In this case, all of its branches must contain either:
    • An updating expression
    • An empty expression ()
    • A call to fn:error()

The following example shows a Typeswitch expression that is an updating expression:

typeswitch($node) 
case $a as element() return ddtek:sql-insert("holdings", "userid",
 $a/name, "stockticker", $a/ticker, "shares", $a/amount) 
default return ddtek:sql-insert("holdings", "userid", $node, "stockticker",
 "PRGS", "shares", 200)  

Conditional Expressions

To support updates of relational databases, DataDirect XQuery extends the semantics of a conditional expression in the following ways:

  • The test expression cannot contain an updating expression.
  • If any branch of the conditional expression contains an updating expression, the conditional expression is an updating expression. In this case, both of its branches must contain either:
    • An updating expression
    • An empty expression ()
    • A call to fn:error()

For example, if you are unsure whether an existing row needs to be updated with the new quantity, or if a new row needs to be created, you can use a simple conditional expression:

let $previousHolding := collection("holdings")/holdings[ 
 userid = "minollo" and stockticker = "PRGS"] 
return 
 if ($previousHolding) then 
 ddtek:sql-update($previousHolding, 
  "shares", $previousHolding/shares + 500) 
 else 
 ddtek:sql-insert("holdings", "userid", "Minollo", 
  "stockticker", "PRGS", "shares", 100)   

Comma Expressions

To support updates of relational databases, DataDirect XQuery extends the semantics of a comma expression in the following way:

If any operand of a comma expression is an updating expression, the comma expression is an updating expression. In this case, each of the operands must contain either:

  • An updating expression
  • An empty expression ()
  • A call to fn:error()

Parenthesized Expressions

To support updates of relational databases, DataDirect XQuery extends the semantics of a parenthesized expression in the following way: If any operand of a parenthesized expression is an updating expression, the parenthesized expression is an updating expression.

Parentheses can be used to enforce a particular evaluation order in expressions that contain multiple operators.

Snapshot Semantics

The concept of snapshot semantics is introduced with the new functionality of updating relational database tables through DataDirect XQuery. DataDirect XQuery evaluates all updating and non-updating expressions of an XQuery and creates a virtual "snapshot" of the queried XDM instances before any updates are applied to the underlying database table, which is referred to as snapshot semantics. Then, this snapshot is used to execute all non-updating expressions before any updating expressions are executed. For example, if you have an XQuery that defines a non-updating expression, an updating expression, and then another non-updating expression, you will not see the update of the data for the second non-updating expression because both of the non-updating expressions are executed before the updating expression is executed. Snapshot semantics is supported on a per query basis.