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 29951 - [FO31] fn-transform "saved"
Summary: [FO31] fn-transform "saved"
Status: RESOLVED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: Functions and Operators 3.1 (show other bugs)
Version: Candidate Recommendation
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: 2016-10-20 13:27 UTC by Tim Mills
Modified: 2017-03-21 11:20 UTC (History)
5 users (show)

See Also:


Attachments

Description Tim Mills 2016-10-20 13:27:53 UTC
I'm a bit concerned by the fn:transform "saved" delivery-format.

I forget the details now, but fn:put never made it into XQ31.  Instead it was left in XQ Update.  fn:transform with the "saved" option using a transform olong the lines of:

<xsl:param name="href" />

<xsl:template match="/">
  <xsl:result-document href="$href">
    <xsl:copy-of select="."/>
  </xsl:result-document>
</xsl:template>

would appear to give fn:put facilities and has all the baggage of a function with side effects.  

If I'm not mistaken, is this wise?
Comment 1 Michael Kay 2016-10-26 09:48:03 UTC
I think the best answer to this might be to put suitable caveats in the spec:

* implementations should not be required to support the "saved" option.

* if they do support it, they may impose restrictions such as not allowing two result documents to be written to the same destination, or not allowing a destination to be read and written within the same query, etc.

* users should be aware that side-effects cannot be relied upon, for example if the actual result of the fn:transform call is not used, or is only partially used, then the side-effects of the call may not happen.
Comment 2 Tim Mills 2016-10-27 07:03:14 UTC
In the case of an implementation NOT supporting 'saved', which error code should be raised?  Arguments could be made for pretty much any of the four existing FOXT codes.
Comment 3 Michael Kay 2016-10-31 17:56:54 UTC
Suggested resolution is to add:

The delivery format "saved" indicates that the transformation should modify the state of the external environment. This has two noteworthy consequences:

(a) it create a potential security risk.

(b) the fn:transform function ceases to be a pure function, because it has side-effects.

Implementations may mitigate these problems in a number of ways, including the following:

(i) use of the "saved" option may be disallowed, either completely or at user option

(ii) the environment that the "saved" option is allowed to modify may be sand-boxed in some way. For example: resources that are created using this option may be accessible only via some special interface; the resource may become available only on completion of the execution scope in which the fn:transform function is evaluated; or the implementation may prevent access to such resources using functions such as fn:doc and fn:collection.

(iii) creating multiple resources with the same URI may be disallowed.

(iv) the implementation may define circumstances in which the side-effect of creating external resources does not happen as a consequence of query optimization (for example, any situation in which a query calls fn:transform but has no functional dependency on the result of the call.) 

(v) there may be restrictions on the URIs that can be used to identify saved resources. 

Add error code FOXT0007: The transformation uses delivery-format="saved" in a way that violates implementation-defined constraints on the use of this option.
Comment 4 Michael Kay 2016-11-01 17:05:32 UTC
The changes were accepted and have been applied.
Comment 5 Tim Mills 2016-11-01 19:32:01 UTC
Thanks.
Comment 6 Josh Spiegel 2016-11-08 15:17:10 UTC
In light of bug 29959 and bug 29990, I would like the working group to take a second look at this.
Comment 7 Josh Spiegel 2016-11-08 16:07:21 UTC
Some examples for discussion:

(e1, e2, e3) [2]

Which expressions get evaluated?

  e1, e2?
  All three?
  Just e2?

------------------------------------------
Equivalent?

for $x in f()
let $y := e1
where $x > 3
return
  ...

vs 

for $x in f()
where $x > 3
let $y := e1
return
  ...
------------------------------------------

let $x := e1
return
  if (c) then
    "hello world"
  else 
    $x

Can I inline the let?  

------------------------------------------

for $o in orders(),
    $c in customers()
let $x := f($c)
where $o/cid eq $c/cid
return 
   ...

Rewrite using a hash-join?

------------------------------------------

(e1, e2)

If e2 raises a type error does e1 get evaluated?  What if the type error is detected statically?  If it is detected during dynamic evaluation, do side effects produced by e1 still persist?

------------------------------------------

let $dummy := e1
return 123

Does e1 get evaluated?
Comment 8 Michael Kay 2016-11-08 16:16:51 UTC
The answer to all the examples in comment 7 is that we decided to leave it implementation-dependent. If you want to be sure that a call on fn:transform() will be evaluated, then make sure that the result of your query depends on its return value.

The rationale was that the feature is still useful even if it isn't 100% interoperable.
Comment 9 Liam R E Quin 2016-11-08 17:48:58 UTC
See also bug 29959
Comment 10 Jonathan Robie 2016-11-09 13:32:12 UTC
I agree with Tim. I would prefer to use fn:put() with fn:transform() instead of having "saved".  The same difficulties we had with fn:put() also apply to fn:transform() with "saved".
Comment 11 Michael Kay 2016-11-15 18:17:49 UTC
After discussion on today's telcon, I propose the following resolution:

(a) drop the option delivery-format=saved.

(b) add a new option post-process. The value is a function of type

function(xs:anyURI, item()*) as item()*

with the default value

function($a, $b) { $b }

which is invoked to post-process each result of the transformation (both the principal result and secondary results), in whatever form it would otherwise be delivered (document, serialized, or raw). The first argument of the function is the URI of the result, the second argument is the actual value. The value that is returned in the result of the fn:transform function is the result of applying this post-processing.

<note>
<p>If the implementation provides a way of writing or invoking functions with side-effects, this post-processing function might be used to save a copy of the result document to persistent storage. For example, if the implementation provides access to the EXPath File library [non-normative reference], then a serialized document might be written to filestore by calling the file:write-binary function. Similar mechanisms might be used to issue an HTTP POST request that posts the result to an HTTP server, or to send the document to an email recipient. The semantics of calling functions with side-effects are entirely implementation-defined.</p>

<p>If the primary purpose of the post-processing function is achieved by means of such side-effects, and if the actual results are not needed by the caller of the fn:transform() function, then it does not matter what the post-processing function actually returns (it could be an empty sequence, for example).</p>

<p>Calls to fn:transform can potentially have side-effects even in the absence of the post-processing option, because the XSLT specification allows a stylesheet to invoke extension functions that have side-effects. The semantics in this case are implementation-defined.</p>

<p>Unless implementations provide mechanisms such as pragmas or function annotations to allow functions with side-effects to be specially recognized, it is advisable that calls to fn:transform should appear in a context where the result of the function is actually used, otherwise there is a risk that an optimizer might decide to eliminate the function call.</p>

</note>
Comment 12 Abel Braaksma 2016-12-01 10:52:13 UTC
> because the XSLT specification allows a stylesheet to invoke extension 
> functions that have side-effects
This suggests that only extension functions have side effects, while in effect there's more (in addition to xsl:result-document and the principal output document):

- XSLT uses XPath, which defines fn:trace, fn:transform etc which may have side effects
- XSLT defines xsl:message, xsl:assert which may cause side effects
- XSLT can have extension functions, attributes and instructions that may cause side effects

I'd propose to either enumerate all of them or to make the statement more generic.
Comment 13 Andrew Coleman 2016-12-02 10:07:22 UTC
At the meeting on 2016-11-29, the WG decided to adopt the resolution proposed in comment 11.  Action A-662-02 has been raised to track this.
Comment 14 Michael Kay 2016-12-05 16:04:37 UTC
The changes have been applied.
Comment 15 Michael Kay 2017-03-17 23:02:58 UTC
I have discovered that the changes were incompletely applied.

Although the "saved" option has been dropped, there are still quite a few references to it.

Fixing this requires deletion of the following sections of text:

(a) 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).

(b) The delivery format saved indicates that the transformation should modify the state of the external environment. This has two noteworthy consequences:
	• It creates a potential security risk.
	• The fn:transform function ceases to be a pure function, because it has side-effects.
Implementations may mitigate these problems in a number of ways, including the following:

	• Use of the delivery-format=saved option may be disallowed, either completely or at user option.
	• The environment that the delivery-format=saved option is allowed to modify may be sand-boxed in some way. For example: resources that are created using this option may be accessible only via some special interface; the resource may become available only on completion of the execution scope in which the fn:transform function is evaluated; or the implementation may prevent the use functions such as fn:doc and fn:collection to access such resources.
	• Creating multiple resources with the same URI may be disallowed.
	• The implementation may define circumstances in which the side-effect of creating external resources is thwarted as a consequence of query optimization (for example, any situation in which a query calls fn:transform but has no functional dependency on the result of the call). 
	• There may be restrictions on the URIs that can be used to identify saved resources

(c) Errors FOXT0005 and FOXT0007.

(d) There is also no change log entry for 29951
Comment 16 Andrew Coleman 2017-03-21 11:20:59 UTC
The fix in comment #15 was applied editorially to the document before publication as Rec.