XQDynamicContext
provides access to the dynamic context as defined in
2.1.2
Dynamic Context, XQuery 1.0: An XML Query Language.
The following components can be accessed:
- The context item can be set
- The variable values can be bound
- The implicit time zone can be retrieved or specified
Where the prolog of the expression specifies the static type of external
variables, this interface allows the dynamic type and value of the
variable to be specified.
Note that in case of an
XQPreparedExpression
, values may only be bound
to those variables that are defined in the prolog of the expression.
Example -
XQConnection conn = XQDataSource.getConnection();
// create an XQPreparedExpression with external variable
XQPreparedExpression e1 = conn.prepareExpression("declare variable $i as xs:int external;
$i + 10");
// bind an int to the external variable
e1.bindInt(new QName("i"), 200, null);
// this will fail as the expression has no external variable $foo
e1.bindInt(new QName("foo"), 200, null);
// this will fail as xs:double is not compatible with an external
variable declared as xs:int
e1.bindDouble(new QName("i"), 2e2, null);
// create an XQExpression with external variable
XQExpression e2 = conn.createExpression();
// bind a value to $i and $foo
e2.bindInt(new QName("i"), 200, null);
e2.bindInt(new QName("foo"), 200, null);
// the value bound to $foo is ignored as the expression doesn't
// declare $foo as external variable
e2.executeQuery("declare variable $i as xs:int external; $i + 10");
Binding a value to the context item is achieved in the same way as binding a
value to an external variable. However, instead of specifying the variable's
name as first argument of the
bindXXX()
method, use
XQConstants#CONTEXT_ITEM as the first
argument.
Binding mode
The default binding mode is immediate. In other words, the external
variable value specified by the application is consumed during the
bindXXX()
method.
An application has the ability to set the binding mode to deferred. In deferred
mode an application cannot assume that the bound value will be
consumed during the invocation of the bindXXX
method. In
such scenario the order in which the bindings are evaluated is
implementation-dependent, and an implementation doesn't necessarily need
to consume a binding if it can evaluate the query without requiring the
external variable. The XQJ implementation is also free to read the bound
value either at bind time or during the subsequent evaluation and
processing of the query results.
Also note that in deferred binding mode, bindings are only active for a
single execution cycle. The application is required to explicitly
re-bind values to every external variable before each execution. Failing
to do so will result in an XQException
, as the
implementation will assume during the next execution that none of the
external variables are bound.
Finally, note that in deferred binding mode, any error condition
specified to throw an exception during the bindXXX()
methods,
may as well be thrown later during the query's evaluation.
Example - in case of an immediate binding mode, bindings stay active
over executions
// BINDING_MODE_IMMEDIATE is the default, no need to change it
QName v = new QName(v);
XQPreparedExpression e = c.prepareExpression("declare variable $v
external; $v");
e.bindInt(v, 1)
// successful execution
e.executeQuery();
// successful execution
e.executeQuery();
Example - in case of a deferred binding mode, bindings are only valid
for a single execution
// BINDING_MODE_IMMEDIATE is the default, change it to
// BINDING_MODE_DEFERRED
XQStaticContext cntxt = c.getStaticContext();
cntxt.setBindingMode(XQConstants.BINDING_MODE_DEFERRED);
c.setStaticContext(cntxt);
QName v = new QName(v);
XQPreparedExpression e = c.prepareExpression("declare variable $v
external; $v");
e.bindInt(v, 1)
// successful execution
XQSequence s = e.executeQuery();
while (s.next())
System.out.println(s.getInt());
// an error is reported during the next query
// evaluation as not all external variables are bound
s = e.executeQuery();
while (s.next())
System.out.println(s.getInt());