This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 26752 - [XSLT30] Streamability of QuantifiedExpr is incomplete and fails
Summary: [XSLT30] Streamability of QuantifiedExpr is incomplete and fails
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Last Call drafts
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-08 01:38 UTC by Abel Braaksma
Modified: 2014-09-12 10:57 UTC (History)
0 users

See Also:


Attachments

Description Abel Braaksma 2014-09-08 01:38:43 UTC
This applies to the rules in 19.8.7.2 (Sept 5, 2014, internal WD)

In a QuantifiedExpr you assign a variable to items in a list and subsequently you can use this variable in an expression:

some $itm in //para satisfies starts-with($itm/../chapter, 'hello')

The current rules are for "some|every $v in S satisfies C":

The posture and sweep are determined by the first of the following that applies:

  1. If C is not motionless, then roaming and free-ranging.
  2. Otherwise, the posture and sweep of S.


Since a variable reference is always motionless, the above validates as streamable, with a posture and sweep of S, which is crawling and consuming. But it is not streamable.

There are a few things wrong in this picture:
1) the result of some..satisfies is true or false, always grounded
2) the variable takes a reference to a node, this is not allowed
3) if we do allow that, similar rules as we researched with functions should apply, i.e. the variable reference takes the posture of the expression S and in the case of crawling, expression in C must be motionless. In case of striding, it can be consuming.

If a variable reference were to be allowed, the expression can be consuming with respect to the variable reference, but must be motionless and grounded with respect to anything else (i.e., it cannot reference and consume another node at the same time.). But this can easily be enforced by doing something like this:

1. Determine the posture of the expression of S, this is the posture that a reference to $v returns when C is evaluated. If S is roaming, then roaming and free-ranging. 
2. Otherwise, apply the GSR with the operand roles as follows: S with usage absorption and C with usage inspection.

The probable thing to do here is the same as we did with ForExpr: disallow the use of variables binding to streamed nodes (see the operand roles of 19.8.7.1). Easiest in rules, but not very flexible with streaming.
Comment 1 Abel Braaksma 2014-09-08 01:44:30 UTC
If we apply those rules, the following becomes streamable:

some $itm in //br satisfies $itm/@dir[. = 'LTR']
every $s in (.., ../..) satisfies $s[@xml:lang = 'en-US']
some $a in /body/p/a satisfies $a eq 'test link'

While the last one is technically streamable, it wouldn't work (because there two consuming expressions) with the proposed rules. Perhaps using the rules of "higher order operands" would work? Or we just leave it and people should just stick to motionless expressions in C.
Comment 2 Michael Kay 2014-09-10 10:44:27 UTC
Agreed, this needs fixing.

I don't think we can contemplate allowing streamed nodes to be bound to variables for this case; it's too difficult to predict all the consequences. We simply don't have the language or conceptual machinery to talk about an expression being (eg.) consuming "with respect to" a variable.

Although the rules end up being restrictive, a workaround using predicates is often possible.

Suggested rewrite:

Writing the expression as some|every $v in S satisfies C, the two operand roles are S and C.

The general streamability rules apply. The operand roles are:
* The in expression (S). This has usage navigation.
* The satisfies expression (R). This is a higher-order operand with usage inspection.

Note:

Expressions of the form some $i in 1 to 3 satisfies $i lt 2, where there is no reference to a streamed node, are clearly streamable.

The in expression can also be consuming, so long as it is grounded: for example some $e in copy-of(emp) satisifies $e/salary gt 10000.

The rule that S has usage navigation prevents the variable being bound to a node in a streamed document. This disallows expressions of the form some $x in child::section satisfies has-children($x), because this requires data flow analysis (tracing from the binding of a variable to its usages), rather than purely syntactic analysis. Some implementations may be able to stream such constructs.

The fact that the return clause is a higher-order operand prevents it from being a consuming expression, for example some $i in 1 to 3 satisifes grade = $i. Use of a motionless expression that accesses streamed nodes is however allowed, for example some $i in 1 to 3 satisfies @grade = $i.

Quantified expressions that fail the streamability rules can often be rewritten as filter expresions. For example, the expression some $x in child::section satisfies has-children($x) can be rewritten as exists(child::section[has-children(.)]), which is grounded and consuming.

ASIDE: in this rewrite there is no equivalent to rule 1 of "for" expressions ("If R is not grounded, then roaming and free-ranging"). I don't believe the rule is needed for "for" expressions either.
Comment 3 Michael Kay 2014-09-12 08:26:33 UTC
The changes were accepted by the WG and have been applied to the spec.
Comment 4 Michael Kay 2014-09-12 10:57:32 UTC
The changes have been applied to the spec.