XQuery Updates implementation

Saxon 9.1 introduces support for XQuery Updates.

To run an updating query from the command line, use the option -update:on on the command line. From Java, compile the query in the normal way, and use the method XQueryExpression.runUpdate() to execute the query. At present it is not possible to run updates using the higher-level interfaces in XQJ or S9API, or using the .NET API.

To enable updating internally, an extension of the NodeInfo interface has been introduced, called MutableNodeInfo. Currently the only tree implementation that supports this interface is the linked tree (formerly called the standard tree). In principle updating should work with any tree model that supports this interface, though at present there are probably some dependencies on the specific implementation.

The linked tree has been improved so that it can now handle schema type annotations, and there have been improvements to the way in which line number information is maintained.

Saxon does not currently include any locking code to prevent concurrent threads attempting to update the same document. This is something that applications must organize for themselves.

At the Java API level, updated documents are not automatically written back to disk. Rather, the runUpdate() method returns a set containing the root nodes of documents that have been updated. This may include documents that were read using the doc() or collection() functions as well as documents supplied as the context node of the query or by binding external variables. It may also include documents (or elements) that were created by the query itself - but only if they have been updated after their initial construction. There is a helper method QueryResult.rewriteToDisk allowing such documents to be written back to disk if required, at the URI determined by their document-uri() property, but this must be explicitly invoked by the application. Clearly if the application does not have write access to the URI, this operation will fail.

Alternatively, updated documents may be written back to disk using the put() function. Note that because put() delivers no result, there is a danger that it will be "optimized out" of the query. Saxon implements put() using the runtime code for xsl:result-document, and the implementation currently imposes similar restrictions: in particular, it must not be called while evaluating a variable or function.

Applications should access the updated document via the root nodes returned by the runUpdate() function. Use of NodeInfo objects that were obtained before running the update is in general unsafe; while it will probably work in most cases, there are some cases (particularly with attributes) where the NodeInfo object returned to the application is a snapshot created on demand, and this snapshot will not be updated when the underlying tree is changed.

Updates are not currently atomic, as required by the specification. In particular, if the update fails revalidation against the schema, it is not rolled back.