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 24510 - Absence of bind-group and bind-grouping-key need not be free-ranging
Summary: Absence of bind-group and bind-grouping-key need not be free-ranging
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:
: 24455 24556 (view as bug list)
Depends on:
Blocks: 24556
  Show dependency treegraph
 
Reported: 2014-02-05 04:13 UTC by Abel Braaksma
Modified: 2014-05-15 14:00 UTC (History)
3 users (show)

See Also:


Attachments
Proposed textual changes (51.33 KB, application/pdf)
2014-03-07 11:30 UTC, Michael Kay
Details
Revised proposal (52.56 KB, application/pdf)
2014-03-14 10:35 UTC, Michael Kay
Details

Description Abel Braaksma 2014-02-05 04:13:58 UTC
Rules #5 and #6 under 19.8.4.18 Streamability of xsl:for-each-group (http://www.w3.org/TR/xslt-30/#streamability-xsl-for-each-group) seem to be too strict. 

When the user does not bind the group or the grouping key, he probably doesn't intent to use them. I mean, if without streaming there would be no call to current-group() or current-grouping-key(), then there is no need to force use of bind-group and bind-grouping-key in such scenarios.

Since a reference to either of these functions is already disallowed, I think we can remove rule #5 and #6.
Comment 1 Innovimax 2014-02-05 08:18:53 UTC
Well you should also add the reference to the context (., current(), etc.)
Comment 2 Michael Kay 2014-02-05 11:07:03 UTC
The problem arises because in the absence of bind-group and bind-grouping-key, the functions current-group() and current-grouping-key() are permitted. We ban their use within the body of the xsl:for-each-group itself, but not in a called template. For example:

<xsl:for-each-group select="emps" group-adjacent="@dept">
  <xsl:apply-templates select="doc('abc.xml')/lookup" mode="non-streaming"/>
</xsl:for-each-group>

<xsl:template match="lookup" mode="non-streaming">
  <xsl:for-each select="current-group()"/>
</xsl:template>

It's possible that there is a better solution to the problem. For example, we could say that if an xsl:for-each-group instruction appears within a streamable template or within xsl:stream, then any calls to xsl:apply-templates etc appearing within the xsl:for-each-group clear the values of current-group and current-grouping-key; thus in a streaming context, the scope of current-group() and current-grouping-key() becomes static, and the need for bind-group and binding-grouping-key disappears, which would be a significant simplification.
Comment 3 Abel Braaksma 2014-02-05 16:05:50 UTC
That sounds like a viable way forward. We already have situations where allowed appearances of current-group can only be determined dynamically and I believe we already have defined errors for such cases, we could extend that to streamability. 

But that leaves the binding to merge-source and merge-key. Should we do the same there? In which case the complex binding rules in the streamability analysis can completely disappear.
Comment 4 C. M. Sperberg-McQueen 2014-02-11 15:50:07 UTC
We discussed this in Prague and found that the WG was in favor of exploring the proposal in comment 2.

This would be the first feature that is legal both with streamable=yes and otherwise and which behaves differently in the two cases.  Perhaps it would be less odd, semantically, if attempts to invoke the functions returned a dynamic error, rather than just ().
Comment 5 Michael Kay 2014-02-18 20:25:31 UTC
This is a proposal to drop the bind-XX variables introduced for grouping and merging in XSLT 3.0, and revert to the use of current-XX() functions.

The reason the bind-XX variables were introduced was because variables are statically scoped while the current-XX() functions were dynamically scoped, which means they cannot be analyzed for streamability across template rule boundaries. However, the problem they introduce is that they break the usual rule that variable references cannot be bound to streamed nodes. In addition, having two ways of doing things complicates the specification and implementations unnecessarily, as this bug report indicates.

This proposal suggests that we revert to use of the functions, and make them statically scoped in the streaming case. In particular, any use of xsl:apply-templates, xsl:call-template, xsl:apply-imports, xsl:next-match, or [xsl:]use-attribute-sets appearing as a descendant of xsl:stream, xsl:template in a streamable mode, or xsl:merge, clears the values of current group and current grouping key.

To handle the bind-source attribute of xsl:merge-source, we re-introduce the name attribute of xsl:merge-source, and a new function current-source-group(name) that returns the same result as the existing bind-source variable. The name attribute is optional; if no name is supplied, current-source-group() is not available.

I suggest we drop the overloading of current-group() to handle both grouping and merging. For the merging case, use a new function current-merge-group().

The streamability rules for current-group() and current-source-group() are taken from the current rules for the corresponding variable references.
Comment 6 Michael Kay 2014-03-06 17:50:59 UTC
Editor actioned to produce a detailed textual proposal along the lines of comment 5.
Comment 7 Michael Kay 2014-03-07 11:30:57 UTC
Created attachment 1450 [details]
Proposed textual changes

Proposed textual changes are attached as PDF.
Comment 8 Michael Kay 2014-03-14 10:20:21 UTC
We looked at the proposal on 2014-03-13 and found some inconsistencies in the handling of current merge group.

I've taken the opportunity to look again at this area and the revised proposal does some refactoring of the way that current-merge-group() works. Although the current merge group is still defined as a map, the function no longer returns this map directly, but instead has two forms:

- the arity-1 function returns a selected entry from the map, that is, all the merge inputs from one named merge source

- the arity-0 function returns the inputs from all merge sources, that is all the values in the map regardless of their key.
Comment 9 Michael Kay 2014-03-14 10:35:16 UTC
Created attachment 1452 [details]
Revised proposal
Comment 10 Michael Kay 2014-04-16 08:31:39 UTC
*** Bug 24455 has been marked as a duplicate of this bug. ***
Comment 11 Michael Kay 2014-04-16 08:35:49 UTC
The proposal was accepted, with editorial guidance, on 3 April 2014 and has now been implemented.
Comment 12 Michael Kay 2014-04-24 14:42:52 UTC
*** Bug 24556 has been marked as a duplicate of this bug. ***