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 29959 - [xq31] fn:put()
Summary: [xq31] fn:put()
Status: RESOLVED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3.1 (show other bugs)
Version: Candidate Recommendation
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Jonathan Robie
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-10-25 15:44 UTC by Michael Kay
Modified: 2016-11-25 14:02 UTC (History)
3 users (show)

See Also:


Attachments

Description Michael Kay 2016-10-25 15:44:12 UTC
XQuery 3.1 defines an optional feature, the fn:put feature, which provides the fn:put function. But the semantics of this function are totally dependent on the XQ Update 3.0 specification, which is at WD status and likely to remain so.
Comment 1 Josh Spiegel 2016-11-04 15:24:40 UTC
Is it safe to optimistically remove this feature pending working group approval?  It seems we have no other option?
Comment 2 Liam R E Quin 2016-11-05 02:03:51 UTC
Removing the feature altogether would be a substantive change too. On the other hand we have the functionality for at least some use cases via fn:transform, indirectly and possibly much less efficiently.

An alternative might be to provide a suggested implementation using fn:transform, or a note that it could be so implemented, and mention non-normatively that the XQuery 3.1 Update draft has a definition for fn:put that could also be used.

This definition of fn:put() is actually broken in that it can be optimized away, so it should also be marked impure - we used to have a pragma for that I think? Or it should return a list of URIs.

So I'm OK with removing it if there can be a note about using fn:transform instead, but would be happier if it remained with the option of making it a wrapper.
Comment 3 Josh Spiegel 2016-11-07 14:43:06 UTC

> This definition of fn:put() is actually broken in that it can be 
> optimized away, so it should also be marked impure - we used to 
> have a pragma for that I think? Or it should return a list of URIs.

I don't think it is broken.  fn:put() is an updating function and any expression that calls it becomes an updating expression. 
https://www.w3.org/XML/Group/qtspecs/specifications/xquery-update-30/html/#id-updating-functions

I think the only problem is that we are normatively defining a feature in XQ based on a Last Call Working Draft of XQUF.  

I don't know what you mean about using fn:transform (I am not very familiar with XSLT).  Could you give an example?
Comment 4 Liam R E Quin 2016-11-07 17:57:12 UTC
Broken in the sense that pure XQuery 3.1 doesn't have updating functions, pending update lists, etc., and without that machinery it's just a function with no useful return.

In XSLT 2 and later you can use xslt:result-document to generate output to a URI (actually you can have multiple xslt:result-document elements and hence multiple outputs in multiple serialization formats). XSLT 1 engines pretty much all support one (or more) of several extensions to do more or less the same thing.
Comment 5 Josh Spiegel 2016-11-07 18:14:55 UTC
It currently says this:  "An implementation that provides the fn:put() feature MUST implement the function as defined in [XQuery Update Facility 3.0]."

Which I take to mean that it does include that machinery.  This at least was the intent of the working group, as I recall.
Comment 6 Liam R E Quin 2016-11-07 19:37:55 UTC
I see - I hadn't understood the implication of the conformance statement. Are there tests for it? But our wording is still fuzzy: e.g. since we don't have updating functions, is it actually meaningful?

Since people are implementing fn:transform() I'm leaning towards removing fn:put altogether although having an fn:put optionally defined in terms of fn:transform is still more appealing to me, as it makes it more likely to be available.
Comment 7 Josh Spiegel 2016-11-07 19:57:24 UTC
If you are saying that fn:transform can have side-effects then that sounds like a problem to me.  Like you were saying before, they can be optimized away...

    let $dummy := fn:transform(...)
    return
      123
Comment 8 Josh Spiegel 2016-11-07 20:54:33 UTC
I see what you are referring to now:

fn:transform
"If the delivery format is saved, the value is the absolute URI of the location where the serialized result has been saved. The saved document will not be accessible at this location within the current ·execution scope· (this is to prevent any dependency on order of execution)."

I wasn't aware of this until now and I am surprised to see this in the specification.  Even if side effects aren't visible within an execution scope, this still doesn't work.  In many cases, there is no guarantee as to how many times a function call will be evaluated. So, the behavior of this feature is not well-defined or interoperable.  For example, processors may do lazy evaluation, rewrite multiple for clauses using a hash-join, detect errors at different points, lift let clauses outside of for clauses, and so on.
Comment 9 Michael Kay 2016-11-08 11:47:46 UTC
The problem of fn:transform having side-effects (with the "saved" option) was discussed and resolved in the closure of bug #29951.

Having opened the door to side-effects just a tiny bit with fn:transform(), I personally don't think it would be wise to now exploit that as a way of making fn:put possible. (Perhaps, though, it should serve as a warning that our users may attempt to do so.)
Comment 10 Liam R E Quin 2016-11-08 17:48:49 UTC
See also bug 29951
Comment 11 Jonathan Robie 2016-11-14 23:15:31 UTC
I think we need to do *something*.  fn:put() was available with XQuery Update 1.0, and we don't have XQuery Update 3.1 yet.  And the ability to create multiple files as the result of a query is a rather fundamental one.  We shouldn't tell people they have to use XSLT if they want to do that.

Here are the possible choices that I see:

1. Eliminate fn:put() from XQuery 3.1.  As I indicate above, I don't think this is acceptable.

2. Add fn:put() to F&O 3.1, indicating that implementations SHOULD treat it as though it contributes to the result of the query even though it does not return a value.  This kind of special casing is not usually a great idea, but it may be the simplest way to provide the desired functionality.  This probably corresponds to what implementers will do if we do nothing.

3. Modify the signature of fn:put() so that it actually does return a value that changes the query result in addition to the side effect.  This is undesirable because (a) it differs from the definition of fn:put() in XQuery Update 1.0, and (b) it requires the ability to return a value and a pending update from the same function, something we will probably have in XQuery Update 3.1, but which never made it into the XQuery 1.0 specification.

None of these are great options, but I think special casing the function as in #2 makes the most sense, and corresponds to the semantics we would want in the XQuery Update 3.1 specification when it is finished.
Comment 12 Michael Kay 2016-11-15 00:24:46 UTC
If we're going to retain fn:put(), I think it should return something, so that clean semantics at least become possible. I don't think many XQUpdate 1.0 applications are going to run without change so compatibility isn't too much of a concern; but perhaps we should rename the function just in case (e.g. fn:new-doc()).

I suggest that the function should return the URI supplied as the argument. It then becomes available in use cases like

function f:chap($chap as element(chapter)) as element() {
  <a href="{new-doc($chap, $chap/shortName)}">{$chap/title}</a>
}

Because the result here is used to create a node of a document which itself forms an output of the query, it's not too difficult to manage the side-effect problem. As with xsl:result-document, we should be explicit that the URI must not be the same as the URI of any "available document" in the dynamic context (so you can't write and read a document in the same execution scope) and make the effect of writing the same URI twice implementation-defined (in XSLT it's a dynamic error).

Having said all that, I'm not comfortable with adding this. The semantics are difficult and it's going to take us weeks of discussion to iron out the glitches. As a WG, we're not good at sweeping our rubbish under the carpet, and unless we're prepared to compromise our usual high standards this is not going to be done quickly.

An alternative would simply to be to recommend that implementors should implement file:write() from the EXPath File module.
Comment 13 Andrew Coleman 2016-11-25 14:02:42 UTC
At the meeting on 2016-11-15, the WG agreed to resolve this with the following actions:

ACTION A-661-09 JR: Amend XQ 3.1 requirements (changing the status of this requirement). (And while there under 2.4.4 collations, there is a misreference to fn:put()).

ACTION A-661-10 JR: In the XQuery 3.1 spec, get rid of the optional fn:put() feature

ACTION A-661-11 MK: Add reference to fn:put(), EXPath etc in a non-normative appendix.