You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by bp...@apache.org on 2006/08/25 02:53:16 UTC

svn commit: r434583 - in /db/derby/code/branches/10.2/java: engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/master/ testing/org/apache/derbyTesting/functionTests/master/DerbyNe...

Author: bpendleton
Date: Thu Aug 24 17:53:15 2006
New Revision: 434583

URL: http://svn.apache.org/viewvc?rev=434583&view=rev
Log:
DERBY-688: Enhancements to XML functionality toward XPath/XQuery support

Merged from the trunk by svn merge -r 434555:434556 ../trunk

Originally submitted by Army Brown (qozinx@gmail.com)

Modified:
    db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java
    db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/XML.java
    db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
    db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
    db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out
    db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/xml_general.out
    db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/xml_general.out
    db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xml_general.sql

Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/SqlXmlUtil.java Thu Aug 24 17:53:15 2006
@@ -56,6 +56,8 @@
 import org.apache.xpath.objects.XObject;
 import org.apache.xpath.objects.XNodeSet;
 
+import org.apache.xml.utils.PrefixResolverDefault;
+
 import org.apache.xalan.serialize.DOMSerializer;
 import org.apache.xalan.serialize.Serializer;
 import org.apache.xalan.serialize.SerializerFactory;
@@ -203,12 +205,23 @@
             // Just rethrow it.
             throw se;
 
-        } catch (Exception e) {
+        } catch (Throwable t) {
 
-            // Must be something caused by JAXP or Xalan; wrap it in a
-            // StandardException and rethrow it.
+            /* Must be something caused by JAXP or Xalan; wrap it in a
+             * StandardException and rethrow it. Note: we catch "Throwable"
+             * here to catch as many external errors as possible in order
+             * to minimize the chance of an uncaught JAXP/Xalan error (such
+             * as a NullPointerException) causing Derby to fail in a more
+             * serious way.  In particular, an uncaught Java exception
+             * like NPE can result in Derby throwing "ERROR 40XT0: An
+             * internal error was identified by RawStore module" for all
+             * statements on the connection after the failure--which we
+             * clearly don't want.  If we catch the error and wrap it,
+             * though, the statement will fail but Derby will continue to
+             * run as normal.
+             */ 
             throw StandardException.newException(
-                SQLState.LANG_UNEXPECTED_XML_EXCEPTION, e);
+                SQLState.LANG_UNEXPECTED_XML_EXCEPTION, t);
 
         }
 
@@ -225,21 +238,43 @@
      *
      * @param queryExpr The XPath expression to compile
      */
-    public void compileXQExpr(String queryExpr)
+    public void compileXQExpr(String queryExpr, String opName)
         throws StandardException
     {
         try {
 
-            // The following XPath constructor compiles the expression
-            // as part of the construction process.
-            query = new XPath(queryExpr, null, null, XPath.SELECT);
-
-        } catch (TransformerException te) {
-
-            // Something went wrong during compilation of the
-            // expression; wrap the error and re-throw it.
+            /* The following XPath constructor compiles the expression
+             * as part of the construction process.  We have to pass
+             * in a PrefixResolver object in order to avoid NPEs when
+             * invalid/unknown functions are used, so we just create
+             * a dummy one, which means prefixes will not be resolved
+             * in the query (Xalan will just throw an error if a prefix
+             * is used).  In the future we may want to revisit this
+             * to make it easier for users to query based on namespaces.
+             */
+            query = new XPath(queryExpr, null,
+                new PrefixResolverDefault(dBuilder.newDocument()),
+                XPath.SELECT);
+
+        } catch (Throwable te) {
+
+            /* Something went wrong during compilation of the
+             * expression; wrap the error and re-throw it.
+             * Note: we catch "Throwable" here to catch as many
+             * Xalan-produced errors as possible in order to
+             * minimize the chance of an uncaught Xalan error
+             * (such as a NullPointerException) causing Derby
+             * to fail in a more serious way.  In particular, an
+             * uncaught Java exception like NPE can result in
+             * Derby throwing "ERROR 40XT0: An internal error was
+             * identified by RawStore module" for all statements on
+             * the connection after the failure--which we clearly
+             * don't want.  If we catch the error and wrap it,
+             * though, the statement will fail but Derby will
+             * continue to run as normal. 
+             */
             throw StandardException.newException(
-                SQLState.LANG_XML_QUERY_ERROR, te);
+                SQLState.LANG_XML_QUERY_ERROR, te, opName);
 
         }
     }
@@ -344,7 +379,7 @@
      *  results of the query
      * @param resultXType The qualified XML type of the result
      *  of evaluating the expression, if returnResults is true.
-     *  If the result is a sequence of one Document or Element node
+     *  If the result is a sequence of exactly one Document node
      *  then this will be XML(DOCUMENT(ANY)); else it will be
      *  XML(SEQUENCE).  If returnResults is false, this value
      *  is ignored.
@@ -438,16 +473,14 @@
 
         nodeList = null;
 
-        // Indicate what kind of XML result value we have.  If
-        // we have a sequence of exactly one Element or Document
-        // then it is XMLPARSE-able and so we consider it to be
-        // of type XML_DOC_ANY (which means we can store it in
-        // a Derby XML column).
-        if ((numItems == 1) && ((itemRefs.get(0) instanceof Document)
-            || (itemRefs.get(0) instanceof Element)))
-        {
+        /* Indicate what kind of XML result value we have.  If
+         * we have a sequence of exactly one Document then it
+         * is XMLPARSE-able and so we consider it to be of type
+         * XML_DOC_ANY (which means we can store it in a Derby
+         * XML column).
+         */
+        if ((numItems == 1) && (itemRefs.get(0) instanceof Document))
             resultXType[0] = XML.XML_DOC_ANY;
-        }
         else
             resultXType[0] = XML.XML_SEQUENCE;
 

Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/XML.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/XML.java?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/XML.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/iapi/types/XML.java Thu Aug 24 17:53:15 2006
@@ -555,11 +555,23 @@
                         "but we shouldn't have made it this far");
             }
 
-        } catch (Exception xe) {
-        // Couldn't parse the XML document.  Throw a StandardException
-        // with the parse exception nested in it.
+        } catch (Throwable t) {
+        /* Couldn't parse the XML document.  Throw a StandardException
+         * with the parse exception (or other error) nested in it.
+         * Note: we catch "Throwable" here to catch as many external
+         * errors as possible in order to minimize the chance of an
+         * uncaught JAXP/Xalan error (such as a NullPointerException)
+         * causing Derby to fail in a more serious way.  In particular,
+         * an uncaught Java exception like NPE can result in Derby
+         * throwing "ERROR 40XT0: An internal error was identified by
+         * RawStore module" for all statements on the connection after
+         * the failure--which we clearly don't want.  If we catch the
+         * error and wrap it, though, the statement will fail but Derby
+         * will continue to run as normal.
+         */ 
             throw StandardException.newException(
-                SQLState.LANG_INVALID_XML_DOCUMENT, xe);
+                SQLState.LANG_INVALID_XML_DOCUMENT, t);
+
         }
 
         // If we get here, the text is valid XML so go ahead
@@ -676,15 +688,26 @@
             return new SQLBoolean(null !=
                 sqlxUtil.evalXQExpression(this, false, new int[1]));
 
-        } catch (Exception xe) {
-        // Failed somewhere during evaluation of the XML query expression;
-        // turn error into a StandardException and throw it.
-            if (xe instanceof StandardException)
-                throw (StandardException)xe;
-            else {
-                throw StandardException.newException(
-                    SQLState.LANG_XML_QUERY_ERROR, xe, "XMLEXISTS");
-            }
+        } catch (StandardException se) {
+
+            // Just re-throw it.
+            throw se;
+
+        } catch (Throwable xe) {
+        /* Failed somewhere during evaluation of the XML query expression;
+         * turn error into a StandardException and throw it.  Note: we
+         * catch "Throwable" here to catch as many Xalan-produced errors
+         * as possible in order to minimize the chance of an uncaught Xalan
+         * error (such as a NullPointerException) causing Derby to fail in
+         * a more serious way.  In particular, an uncaught Java exception
+         * like NPE can result in Derby throwing "ERROR 40XT0: An internal
+         * error was identified by RawStore module" for all statements on
+         * the connection after the failure--which we clearly don't want.  
+         * If we catch the error and wrap it, though, the statement will
+         * fail but Derby will continue to run as normal. 
+         */
+            throw StandardException.newException(
+                SQLState.LANG_XML_QUERY_ERROR, xe, "XMLEXISTS");
         }
     }
 
@@ -744,9 +767,19 @@
             // Just re-throw it.
             throw se;
 
-        } catch (Exception xe) {
-        // Failed somewhere during evaluation of the XML query expression;
-        // turn error into a StandardException and throw it.
+        } catch (Throwable xe) {
+        /* Failed somewhere during evaluation of the XML query expression;
+         * turn error into a StandardException and throw it.  Note: we
+         * catch "Throwable" here to catch as many Xalan-produced errors
+         * as possible in order to minimize the chance of an uncaught Xalan
+         * error (such as a NullPointerException) causing Derby to fail in
+         * a more serious way.  In particular, an uncaught Java exception
+         * like NPE can result in Derby throwing "ERROR 40XT0: An internal
+         * error was identified by RawStore module" for all statements on
+         * the connection after the failure--which we clearly don't want.  
+         * If we catch the error and wrap it, though, the statement will
+         * fail but Derby will continue to run as normal. 
+         */
             throw StandardException.newException(
                 SQLState.LANG_XML_QUERY_ERROR, xe, "XMLQUERY");
         }

Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java Thu Aug 24 17:53:15 2006
@@ -367,7 +367,8 @@
         // compile the query expression.
             sqlxUtil = new SqlXmlUtil();
             sqlxUtil.compileXQExpr(
-                ((CharConstantNode)leftOperand).getString());
+                ((CharConstantNode)leftOperand).getString(),
+                (operatorType == XMLEXISTS_OP ? "XMLEXISTS" : "XMLQUERY"));
         }
 
         // Right operand must be an XML data value.  NOTE: This

Modified: db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ db/derby/code/branches/10.2/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Thu Aug 24 17:53:15 2006
@@ -7098,9 +7098,9 @@
  * operator uses and the result is always a Document node).
  * Internally this means that we can only store a sequence if it
  * contains exactly one org.w3c.dom.Node that is an instance of
- * either org.w3c.dom.Document or org.w3c.dom.Element.  If the
- * result of an XMLQUERY operation does not fit this criteria then
- * it will *not* be storable into Derby XML columns.
+ * org.w3c.dom.Document.  If the result of an XMLQUERY operation
+ * does not fit this criteria then it will *not* be storable into
+ * Derby XML columns.
  */
 short
 	xqReturningClause() throws StandardException :

Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out Thu Aug 24 17:53:15 2006
@@ -632,6 +632,16 @@
 ERROR 42Z77: Context item must have type 'XML'; 'CHAR' is not allowed.
 ij> select i, xmlquery('//*' passing by ref cast ('hello' as clob) empty on empty) from t1;
 ERROR 42Z77: Context item must have type 'XML'; 'CLOB' is not allowed.
+ij> -- This should fail because the function is not recognized by Xalan.
+----- The failure should be an error from Xalan saying what the problem
+----- is; it should *NOT* be a NPE, which is what we were seeing before
+----- DERBY-688 was completed.
+select i,
+  xmlserialize(
+    xmlquery('data(//@*)' passing by ref x returning sequence empty on empty)
+  as char(70))
+from t1;
+ERROR 10000: Encountered error while evaluating XML query expression for XMLQUERY operator; see next exception for details. SQLSTATE: XJ001: Java exception: 'Could not find function: data: javax.xml.transform.TransformerException'.
 ij> -- These should all succeed.  Since it's Xalan that's actually doing
 ----- the query evaluation we don't need to test very many queries; we
 ----- just want to make sure we get the correct results when there is
@@ -790,8 +800,7 @@
 -----
 <lets> try this </lets>       
 ij> -- Check insertion of XMLQUERY result into a table.  Should only allow
------ results that constitute a valid DOCUMENT node (i.e. that can be parsed
------ by the XMLPARSE operator).
+----- results that are a sequence of exactly one Document node.
 insert into t1 values (
   9,
   xmlparse(document '<here><is><my height="4.4">attribute</my></is></here>' preserve whitespace)
@@ -813,9 +822,9 @@
 0 |<ay>caramba</ay>                                                           
 0 |<there><goes><my weight="180">attribute</my></goes></there>                
 ij> -- These should all fail because the result of the XMLQUERY op is
------ not a valid document (it's either an empty sequence, an attribute,
------ some undefined value, or a sequence with more than one item in
------ it.
+----- not a valid document (it's either an empty sequence, a node that is
+----- not a Document node, some undefined value, or a sequence with more
+----- than one item in it).
 insert into t2 (i, x) values (
   20, 
   (select
@@ -856,27 +865,27 @@
   )
 );
 ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
-ij> -- These should succeed.
-insert into t2 (i, x) values (
+ij> insert into t2 (i, x) values (
   25,
   (select
-    xmlquery('.' passing by ref x returning sequence empty on empty)
+    xmlquery('//is' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
-1 row inserted/updated/deleted
+ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
 ij> insert into t2 (i, x) values (
   26,
   (select
-    xmlquery('//is' passing by ref x returning sequence empty on empty)
+    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
-1 row inserted/updated/deleted
-ij> insert into t2 (i, x) values (
+ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
+ij> -- These should succeed.
+insert into t2 (i, x) values (
   27,
   (select
-    xmlquery('/here' passing by ref x returning sequence empty on empty)
+    xmlquery('.' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -884,7 +893,7 @@
 ij> insert into t2 (i, x) values (
   28,
   (select
-    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
+    xmlquery('/here/..' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -894,10 +903,8 @@
 I |2                                                                          
 -----
 1 |<should> work as planned </should>                                         
-25 |<here><is><my height="4.4">attribute</my></is></here>                      
-26 |<is><my height="4.4">attribute</my></is>                                   
 27 |<here><is><my height="4.4">attribute</my></is></here>                      
-28 |<my height="4.4">attribute</my>                                            
+28 |<here><is><my height="4.4">attribute</my></is></here>                      
 ij> -- Next two should _both_ succeed because there's no row with i = 100
 ----- in t1, thus the SELECT will return null and XMLQuery operator should
 ----- never get executed.  x will be NULL in these cases.
@@ -938,7 +945,7 @@
 1 row inserted/updated/deleted
 ij> update t3
   set x = 
-    xmlquery('//*[@height]' passing by ref
+    xmlquery('self::node()[//@height]' passing by ref
       (select
         xmlquery('.' passing by ref x empty on empty)
         from t1
@@ -995,7 +1002,7 @@
 0 |<ay>caramba</ay>                                                           
 0 |<there><goes><my weight="180">attribute</my></goes></there>                
 29 |<none><here/></none>                                                       
-30 |<my height="4.4">attribute</my>                                            
+30 |<here><is><my height="4.4">attribute</my></is></here>                      
 ij> -- Pass results of an XMLQUERY op into another XMLQUERY op.
 ----- Should work so long as results of the first op constitute
 ----- a valid document.
@@ -1013,7 +1020,7 @@
 ij> select i,
   xmlserialize(
     xmlquery('.' passing by ref
-      xmlquery('//lets/@*' passing by ref
+      xmlquery('//lets' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1022,7 +1029,7 @@
 ERROR 2200V: Invalid context item for XMLQUERY operator; context items must be well-formed DOCUMENT nodes.
 ij> select i,
   xmlexists('.' passing by ref
-    xmlquery('//lets/@*' passing by ref
+    xmlquery('/okay' passing by ref
       xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
     empty on empty)
   )
@@ -1032,7 +1039,7 @@
 select i,
   xmlserialize(
     xmlquery('/not' passing by ref
-      xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1047,8 +1054,8 @@
 ij> -- Should succeed with various results.
 select i,
   xmlserialize(
-    xmlquery('.' passing by ref
-      xmlquery('//lets' passing by ref
+    xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1062,8 +1069,8 @@
 9 |<lets boki="inigo"/>                                                                                
 ij> select i,
   xmlserialize(
-    xmlquery('//@boki' passing by ref
-      xmlquery('/okay' passing by ref
+    xmlquery('string(//@boki)' passing by ref
+      xmlquery('/okay/..' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1077,8 +1084,8 @@
 9 |inigo                                                                                               
 ij> select i,
   xmlserialize(
-    xmlquery('/masted/text()' passing by ref
-      xmlquery('//masted' passing by ref x empty on empty)
+    xmlquery('/half/masted/text()' passing by ref
+      xmlquery('.' passing by ref x empty on empty)
     empty on empty)
   as char(100))
 from t1 where i = 6;
@@ -1086,8 +1093,8 @@
 -----
 6 | bass                                                                                               
 ij> select i,
-  xmlexists('/masted/text()' passing by ref
-    xmlquery('//masted' passing by ref x empty on empty)
+  xmlexists('/half/masted/text()' passing by ref
+    xmlquery('.' passing by ref x empty on empty)
   )
 from t1 where i = 6;
 I |2     

Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/xml_general.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/xml_general.out?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/xml_general.out (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/xml_general.out Thu Aug 24 17:53:15 2006
@@ -633,6 +633,16 @@
 ERROR 42Z77: Context item must have type 'XML'; 'CHAR' is not allowed.
 ij> select i, xmlquery('//*' passing by ref cast ('hello' as clob) empty on empty) from t1;
 ERROR 42Z77: Context item must have type 'XML'; 'CLOB' is not allowed.
+ij> -- This should fail because the function is not recognized by Xalan.
+----- The failure should be an error from Xalan saying what the problem
+----- is; it should *NOT* be a NPE, which is what we were seeing before
+----- DERBY-688 was completed.
+select i,
+  xmlserialize(
+    xmlquery('data(//@*)' passing by ref x returning sequence empty on empty)
+  as char(70))
+from t1;
+ERROR 10000: Encountered error while evaluating XML query expression for XMLQUERY operator; see next exception for details. SQLSTATE: XJ001: Java exception: 'Could not find function: data: javax.xml.transform.TransformerException'.
 ij> -- These should all succeed.  Since it's Xalan that's actually doing
 ----- the query evaluation we don't need to test very many queries; we
 ----- just want to make sure we get the correct results when there is
@@ -791,8 +801,7 @@
 -----
 <lets> try this </lets>       
 ij> -- Check insertion of XMLQUERY result into a table.  Should only allow
------ results that constitute a valid DOCUMENT node (i.e. that can be parsed
------ by the XMLPARSE operator).
+----- results that are a sequence of exactly one Document node.
 insert into t1 values (
   9,
   xmlparse(document '<here><is><my height="4.4">attribute</my></is></here>' preserve whitespace)
@@ -814,9 +823,9 @@
 0 |<ay>caramba</ay>                                                           
 0 |<there><goes><my weight="180">attribute</my></goes></there>                
 ij> -- These should all fail because the result of the XMLQUERY op is
------ not a valid document (it's either an empty sequence, an attribute,
------ some undefined value, or a sequence with more than one item in
------ it.
+----- not a valid document (it's either an empty sequence, a node that is
+----- not a Document node, some undefined value, or a sequence with more
+----- than one item in it).
 insert into t2 (i, x) values (
   20, 
   (select
@@ -857,27 +866,27 @@
   )
 );
 ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
-ij> -- These should succeed.
-insert into t2 (i, x) values (
+ij> insert into t2 (i, x) values (
   25,
   (select
-    xmlquery('.' passing by ref x returning sequence empty on empty)
+    xmlquery('//is' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
-1 row inserted/updated/deleted
+ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
 ij> insert into t2 (i, x) values (
   26,
   (select
-    xmlquery('//is' passing by ref x returning sequence empty on empty)
+    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
-1 row inserted/updated/deleted
-ij> insert into t2 (i, x) values (
+ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
+ij> -- These should succeed.
+insert into t2 (i, x) values (
   27,
   (select
-    xmlquery('/here' passing by ref x returning sequence empty on empty)
+    xmlquery('.' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -885,7 +894,7 @@
 ij> insert into t2 (i, x) values (
   28,
   (select
-    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
+    xmlquery('/here/..' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -895,10 +904,8 @@
 I |2                                                                          
 -----
 1 |<should> work as planned </should>                                         
-25 |<here><is><my height="4.4">attribute</my></is></here>                      
-26 |<is><my height="4.4">attribute</my></is>                                   
 27 |<here><is><my height="4.4">attribute</my></is></here>                      
-28 |<my height="4.4">attribute</my>                                            
+28 |<here><is><my height="4.4">attribute</my></is></here>                      
 ij> -- Next two should _both_ succeed because there's no row with i = 100
 ----- in t1, thus the SELECT will return null and XMLQuery operator should
 ----- never get executed.  x will be NULL in these cases.
@@ -939,7 +946,7 @@
 1 row inserted/updated/deleted
 ij> update t3
   set x = 
-    xmlquery('//*[@height]' passing by ref
+    xmlquery('self::node()[//@height]' passing by ref
       (select
         xmlquery('.' passing by ref x empty on empty)
         from t1
@@ -996,7 +1003,7 @@
 0 |<ay>caramba</ay>                                                           
 0 |<there><goes><my weight="180">attribute</my></goes></there>                
 29 |<none><here/></none>                                                       
-30 |<my height="4.4">attribute</my>                                            
+30 |<here><is><my height="4.4">attribute</my></is></here>                      
 ij> -- Pass results of an XMLQUERY op into another XMLQUERY op.
 ----- Should work so long as results of the first op constitute
 ----- a valid document.
@@ -1014,7 +1021,7 @@
 ij> select i,
   xmlserialize(
     xmlquery('.' passing by ref
-      xmlquery('//lets/@*' passing by ref
+      xmlquery('//lets' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1023,7 +1030,7 @@
 ERROR 2200V: Invalid context item for XMLQUERY operator; context items must be well-formed DOCUMENT nodes.
 ij> select i,
   xmlexists('.' passing by ref
-    xmlquery('//lets/@*' passing by ref
+    xmlquery('/okay' passing by ref
       xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
     empty on empty)
   )
@@ -1033,7 +1040,7 @@
 select i,
   xmlserialize(
     xmlquery('/not' passing by ref
-      xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1048,8 +1055,8 @@
 ij> -- Should succeed with various results.
 select i,
   xmlserialize(
-    xmlquery('.' passing by ref
-      xmlquery('//lets' passing by ref
+    xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1063,8 +1070,8 @@
 9 |<lets boki="inigo"/>                                                                                
 ij> select i,
   xmlserialize(
-    xmlquery('//@boki' passing by ref
-      xmlquery('/okay' passing by ref
+    xmlquery('string(//@boki)' passing by ref
+      xmlquery('/okay/..' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1078,8 +1085,8 @@
 9 |inigo                                                                                               
 ij> select i,
   xmlserialize(
-    xmlquery('/masted/text()' passing by ref
-      xmlquery('//masted' passing by ref x empty on empty)
+    xmlquery('/half/masted/text()' passing by ref
+      xmlquery('.' passing by ref x empty on empty)
     empty on empty)
   as char(100))
 from t1 where i = 6;
@@ -1087,8 +1094,8 @@
 -----
 6 | bass                                                                                               
 ij> select i,
-  xmlexists('/masted/text()' passing by ref
-    xmlquery('//masted' passing by ref x empty on empty)
+  xmlexists('/half/masted/text()' passing by ref
+    xmlquery('.' passing by ref x empty on empty)
   )
 from t1 where i = 6;
 I |2     

Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/xml_general.out
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/xml_general.out?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/xml_general.out (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/master/xml_general.out Thu Aug 24 17:53:15 2006
@@ -651,6 +651,17 @@
 ERROR 42Z77: Context item must have type 'XML'; 'CHAR' is not allowed.
 ij> select i, xmlquery('//*' passing by ref cast ('hello' as clob) empty on empty) from t1;
 ERROR 42Z77: Context item must have type 'XML'; 'CLOB' is not allowed.
+ij> -- This should fail because the function is not recognized by Xalan.
+-- The failure should be an error from Xalan saying what the problem
+-- is; it should *NOT* be a NPE, which is what we were seeing before
+-- DERBY-688 was completed.
+select i,
+  xmlserialize(
+    xmlquery('data(//@*)' passing by ref x returning sequence empty on empty)
+  as char(70))
+from t1;
+ERROR 10000: Encountered error while evaluating XML query expression for XMLQUERY operator; see next exception for details.
+ERROR XJ001: Java exception: 'Could not find function: data: javax.xml.transform.TransformerException'.
 ij> -- These should all succeed.  Since it's Xalan that's actually doing
 -- the query evaluation we don't need to test very many queries; we
 -- just want to make sure we get the correct results when there is
@@ -809,8 +820,7 @@
 ------------------------------
 <lets> try this </lets>       
 ij> -- Check insertion of XMLQUERY result into a table.  Should only allow
--- results that constitute a valid DOCUMENT node (i.e. that can be parsed
--- by the XMLPARSE operator).
+-- results that are a sequence of exactly one Document node.
 insert into t1 values (
   9,
   xmlparse(document '<here><is><my height="4.4">attribute</my></is></here>' preserve whitespace)
@@ -832,9 +842,9 @@
 0          |<ay>caramba</ay>                                                           
 0          |<there><goes><my weight="180">attribute</my></goes></there>                
 ij> -- These should all fail because the result of the XMLQUERY op is
--- not a valid document (it's either an empty sequence, an attribute,
--- some undefined value, or a sequence with more than one item in
--- it.
+-- not a valid document (it's either an empty sequence, a node that is
+-- not a Document node, some undefined value, or a sequence with more
+-- than one item in it).
 insert into t2 (i, x) values (
   20, 
   (select
@@ -875,27 +885,27 @@
   )
 );
 ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
-ij> -- These should succeed.
-insert into t2 (i, x) values (
+ij> insert into t2 (i, x) values (
   25,
   (select
-    xmlquery('.' passing by ref x returning sequence empty on empty)
+    xmlquery('//is' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
-1 row inserted/updated/deleted
+ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
 ij> insert into t2 (i, x) values (
   26,
   (select
-    xmlquery('//is' passing by ref x returning sequence empty on empty)
+    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
-1 row inserted/updated/deleted
-ij> insert into t2 (i, x) values (
+ERROR 2200L: Values assigned to XML columns must be well-formed DOCUMENT nodes.
+ij> -- These should succeed.
+insert into t2 (i, x) values (
   27,
   (select
-    xmlquery('/here' passing by ref x returning sequence empty on empty)
+    xmlquery('.' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -903,7 +913,7 @@
 ij> insert into t2 (i, x) values (
   28,
   (select
-    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
+    xmlquery('/here/..' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -913,10 +923,8 @@
 I          |2                                                                          
 ---------------------------------------------------------------------------------------
 1          |<should> work as planned </should>                                         
-25         |<here><is><my height="4.4">attribute</my></is></here>                      
-26         |<is><my height="4.4">attribute</my></is>                                   
 27         |<here><is><my height="4.4">attribute</my></is></here>                      
-28         |<my height="4.4">attribute</my>                                            
+28         |<here><is><my height="4.4">attribute</my></is></here>                      
 ij> -- Next two should _both_ succeed because there's no row with i = 100
 -- in t1, thus the SELECT will return null and XMLQuery operator should
 -- never get executed.  x will be NULL in these cases.
@@ -957,7 +965,7 @@
 1 row inserted/updated/deleted
 ij> update t3
   set x = 
-    xmlquery('//*[@height]' passing by ref
+    xmlquery('self::node()[//@height]' passing by ref
       (select
         xmlquery('.' passing by ref x empty on empty)
         from t1
@@ -1014,7 +1022,7 @@
 0          |<ay>caramba</ay>                                                           
 0          |<there><goes><my weight="180">attribute</my></goes></there>                
 29         |<none><here/></none>                                                       
-30         |<my height="4.4">attribute</my>                                            
+30         |<here><is><my height="4.4">attribute</my></is></here>                      
 ij> -- Pass results of an XMLQUERY op into another XMLQUERY op.
 -- Should work so long as results of the first op constitute
 -- a valid document.
@@ -1034,7 +1042,7 @@
 ij> select i,
   xmlserialize(
     xmlquery('.' passing by ref
-      xmlquery('//lets/@*' passing by ref
+      xmlquery('//lets' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1045,7 +1053,7 @@
 ERROR 2200V: Invalid context item for XMLQUERY operator; context items must be well-formed DOCUMENT nodes.
 ij> select i,
   xmlexists('.' passing by ref
-    xmlquery('//lets/@*' passing by ref
+    xmlquery('/okay' passing by ref
       xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
     empty on empty)
   )
@@ -1057,7 +1065,7 @@
 select i,
   xmlserialize(
     xmlquery('/not' passing by ref
-      xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1072,8 +1080,8 @@
 ij> -- Should succeed with various results.
 select i,
   xmlserialize(
-    xmlquery('.' passing by ref
-      xmlquery('//lets' passing by ref
+    xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1087,8 +1095,8 @@
 9          |<lets boki="inigo"/>                                                                                
 ij> select i,
   xmlserialize(
-    xmlquery('//@boki' passing by ref
-      xmlquery('/okay' passing by ref
+    xmlquery('string(//@boki)' passing by ref
+      xmlquery('/okay/..' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -1102,8 +1110,8 @@
 9          |inigo                                                                                               
 ij> select i,
   xmlserialize(
-    xmlquery('/masted/text()' passing by ref
-      xmlquery('//masted' passing by ref x empty on empty)
+    xmlquery('/half/masted/text()' passing by ref
+      xmlquery('.' passing by ref x empty on empty)
     empty on empty)
   as char(100))
 from t1 where i = 6;
@@ -1111,8 +1119,8 @@
 ----------------------------------------------------------------------------------------------------------------
 6          | bass                                                                                               
 ij> select i,
-  xmlexists('/masted/text()' passing by ref
-    xmlquery('//masted' passing by ref x empty on empty)
+  xmlexists('/half/masted/text()' passing by ref
+    xmlquery('.' passing by ref x empty on empty)
   )
 from t1 where i = 6;
 I          |2    

Modified: db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xml_general.sql
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xml_general.sql?rev=434583&r1=434582&r2=434583&view=diff
==============================================================================
--- db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xml_general.sql (original)
+++ db/derby/code/branches/10.2/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xml_general.sql Thu Aug 24 17:53:15 2006
@@ -265,6 +265,16 @@
 select i, xmlquery('//*' passing by ref 'hello' empty on empty) from t1;
 select i, xmlquery('//*' passing by ref cast ('hello' as clob) empty on empty) from t1;
 
+-- This should fail because the function is not recognized by Xalan.
+-- The failure should be an error from Xalan saying what the problem
+-- is; it should *NOT* be a NPE, which is what we were seeing before
+-- DERBY-688 was completed.
+select i,
+  xmlserialize(
+    xmlquery('data(//@*)' passing by ref x returning sequence empty on empty)
+  as char(70))
+from t1;
+
 -- These should all succeed.  Since it's Xalan that's actually doing
 -- the query evaluation we don't need to test very many queries; we
 -- just want to make sure we get the correct results when there is
@@ -340,8 +350,7 @@
 as char(30));
 
 -- Check insertion of XMLQUERY result into a table.  Should only allow
--- results that constitute a valid DOCUMENT node (i.e. that can be parsed
--- by the XMLPARSE operator).
+-- results that are a sequence of exactly one Document node.
 
 insert into t1 values (
   9,
@@ -359,9 +368,9 @@
 select i, xmlserialize(x as char(75)) from t3;
 
 -- These should all fail because the result of the XMLQUERY op is
--- not a valid document (it's either an empty sequence, an attribute,
--- some undefined value, or a sequence with more than one item in
--- it.
+-- not a valid document (it's either an empty sequence, a node that is
+-- not a Document node, some undefined value, or a sequence with more
+-- than one item in it).
 
 insert into t2 (i, x) values (
   20, 
@@ -403,12 +412,10 @@
   )
 );
 
--- These should succeed.
-
 insert into t2 (i, x) values (
   25,
   (select
-    xmlquery('.' passing by ref x returning sequence empty on empty)
+    xmlquery('//is' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -416,15 +423,17 @@
 insert into t2 (i, x) values (
   26,
   (select
-    xmlquery('//is' passing by ref x returning sequence empty on empty)
+    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
 
+-- These should succeed.
+
 insert into t2 (i, x) values (
   27,
   (select
-    xmlquery('/here' passing by ref x returning sequence empty on empty)
+    xmlquery('.' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -432,7 +441,7 @@
 insert into t2 (i, x) values (
   28,
   (select
-    xmlquery('//*[@*]' passing by ref x returning sequence empty on empty)
+    xmlquery('/here/..' passing by ref x returning sequence empty on empty)
     from t1 where i = 9
   )
 );
@@ -478,7 +487,7 @@
 
 update t3
   set x = 
-    xmlquery('//*[@height]' passing by ref
+    xmlquery('self::node()[//@height]' passing by ref
       (select
         xmlquery('.' passing by ref x empty on empty)
         from t1
@@ -551,7 +560,7 @@
 select i,
   xmlserialize(
     xmlquery('.' passing by ref
-      xmlquery('//lets/@*' passing by ref
+      xmlquery('//lets' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -560,7 +569,7 @@
 
 select i,
   xmlexists('.' passing by ref
-    xmlquery('//lets/@*' passing by ref
+    xmlquery('/okay' passing by ref
       xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
     empty on empty)
   )
@@ -571,7 +580,7 @@
 select i,
   xmlserialize(
     xmlquery('/not' passing by ref
-      xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -582,8 +591,8 @@
 
 select i,
   xmlserialize(
-    xmlquery('.' passing by ref
-      xmlquery('//lets' passing by ref
+    xmlquery('//lets' passing by ref
+      xmlquery('.' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -592,8 +601,8 @@
 
 select i,
   xmlserialize(
-    xmlquery('//@boki' passing by ref
-      xmlquery('/okay' passing by ref
+    xmlquery('string(//@boki)' passing by ref
+      xmlquery('/okay/..' passing by ref
         xmlparse(document '<okay><lets boki="inigo"/></okay>' preserve whitespace)
       empty on empty)
     empty on empty)
@@ -602,15 +611,15 @@
 
 select i,
   xmlserialize(
-    xmlquery('/masted/text()' passing by ref
-      xmlquery('//masted' passing by ref x empty on empty)
+    xmlquery('/half/masted/text()' passing by ref
+      xmlquery('.' passing by ref x empty on empty)
     empty on empty)
   as char(100))
 from t1 where i = 6;
 
 select i,
-  xmlexists('/masted/text()' passing by ref
-    xmlquery('//masted' passing by ref x empty on empty)
+  xmlexists('/half/masted/text()' passing by ref
+    xmlquery('.' passing by ref x empty on empty)
   )
 from t1 where i = 6;