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 ba...@apache.org on 2005/06/09 08:48:36 UTC

svn commit: r189721 [1/5] - in /incubator/derby/code/trunk: java/engine/org/apache/derby/catalog/types/ java/engine/org/apache/derby/iapi/ java/engine/org/apache/derby/iapi/reference/ java/engine/org/apache/derby/iapi/services/io/ java/engine/org/apache/derby/iapi/sql/compile/ java/engine/org/apache/derby/iapi/types/ java/engine/org/apache/derby/impl/jdbc/ java/engine/org/apache/derby/impl/sql/compile/ java/engine/org/apache/derby/loc/ java/testing/org/apache/derbyTesting/functionTests/master/ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/ tools/jar/

Author: bandaram
Date: Wed Jun  8 23:48:34 2005
New Revision: 189721

URL: http://svn.apache.org/viewcvs?rev=189721&view=rev
Log:
Submit initial XML support to Derby.

Submitted by Army Brown.(qozinx@sbcglobal.net)

Adding some "starter" XML functionality to Derby, which can then serve as the basis for future XML development.  Initial features include the following:

1 - A built-in XML datatype.
2 - An XMLPARSE() operator for creating XML values.
3 - An XMLSERIALIZE() operator for serializing XML values to strings (for data retrieval).
4 - An XMLEXISTSTS() operator for running simple existence queries against XML using XPath.

These features are implemented at the SQL level only (no JDBC support).  See the email here for a more detailed description:

http://thread.gmane.org/gmane.comp.apache.db.derby.devel/4468


Added:
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XML.java   (with props)
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XMLDataValue.java   (with props)
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLConstantNode.java   (with props)
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLTypeCompiler.java   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xmlBinding.out   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/xml_general.out   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/xmlBinding.out   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/xml_general.out   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlBinding.java   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlBinding_app.properties   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/deep40k.xml   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/dtdDoc.xml   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/dtdDoc_invalid.xml   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/personal.dtd   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/personal.xsd   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/wide40k.xml   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/xsdDoc.xml   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xmlTestFiles/xsdDoc_invalid.xml   (with props)
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/xml_general.sql   (with props)
Modified:
    incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypesImplInstanceGetter.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/build.xml
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/ClassName.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/SQLState.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/C_NodeTypes.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DTSClassInfo.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeUtilities.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactory.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactoryImpl.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/StringDataValue.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/build.xml
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/Util.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/C_NodeNames.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CharTypeCompiler.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DB2LengthOperatorNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ReadCursorNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TypeCompilerFactoryImpl.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
    incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
    incubator/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
    incubator/derby/code/trunk/tools/jar/DBMSnodes.properties

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java Wed Jun  8 23:48:34 2005
@@ -415,6 +415,17 @@
                 JDBCTypeId = Types.TIMESTAMP;
                 wrapperTypeFormatId = StoredFormatIds.TIMESTAMP_TYPE_ID;
                 break;
+
+          case StoredFormatIds.XML_TYPE_ID_IMPL:
+                SQLTypeName = TypeId.XML_NAME;
+                // RESOLVE: There isn't a JDBC type for XML, so we
+                // just use our internal type.  Is it okay to do this,
+                // or should "JDBCTypeId" be renamed since it no longer
+                // just holds JDBC types?
+                JDBCTypeId = StoredFormatIds.XML_TYPE_ID;
+                wrapperTypeFormatId = StoredFormatIds.XML_TYPE_ID;
+                break;
+
           default:
                 if (SanityManager.DEBUG)
                 {

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypesImplInstanceGetter.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypesImplInstanceGetter.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypesImplInstanceGetter.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypesImplInstanceGetter.java Wed Jun  8 23:48:34 2005
@@ -51,6 +51,7 @@
                   case StoredFormatIds.BLOB_TYPE_ID_IMPL:
                   case StoredFormatIds.CLOB_TYPE_ID_IMPL:
                   case StoredFormatIds.NCLOB_TYPE_ID_IMPL:
+                  case StoredFormatIds.XML_TYPE_ID_IMPL:
                           return new BaseTypeIdImpl(fmtId);
                   case StoredFormatIds.DECIMAL_TYPE_ID_IMPL:
                           return new DecimalTypeIdImpl();

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/build.xml
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/build.xml?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/build.xml (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/build.xml Wed Jun  8 23:48:34 2005
@@ -44,8 +44,8 @@
       <include name="${derby.dir}/iapi/error/**"/>
     </javac>
     <ant dir="${derby.engine.dir}/iapi/util"/>
-    <ant dir="${derby.engine.dir}/iapi/services" target="compile_iapi_services_jsr169" />
     <ant dir="${derby.engine.dir}/iapi/types" />
+    <ant dir="${derby.engine.dir}/iapi/services" target="compile_iapi_services_jsr169" />
     <ant dir="${derby.engine.dir}/iapi/store" target="compile_iapi_store_jsr169"/>
     <ant dir="${derby.engine.dir}/iapi/sql" target="compile_iapi_sql_jsr169" />
     <ant dir="${derby.engine.dir}/iapi/db"/>

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/ClassName.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/ClassName.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/ClassName.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/ClassName.java Wed Jun  8 23:48:34 2005
@@ -54,6 +54,7 @@
 	String RefDataValue = "org.apache.derby.iapi.types.RefDataValue";
 	String UserDataValue = "org.apache.derby.iapi.types.UserDataValue";
 	String ConcatableDataValue  = "org.apache.derby.iapi.types.ConcatableDataValue";
+	String XMLDataValue  = "org.apache.derby.iapi.types.XMLDataValue";
 
 	String FormatableBitSet = "org.apache.derby.iapi.services.io.FormatableBitSet";
 

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/SQLState.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/SQLState.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/SQLState.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/SQLState.java Wed Jun  8 23:48:34 2005
@@ -118,6 +118,7 @@
 
 	<LI>Language
 	  <UL>
+		<LI> 2200J-2200R for SQL/XML errors (based on SQL/XML[2003]) </LI>
 		<LI> 42800-? for compatible DB2 errors
 		<LI> 42X00-42Zxx for compilation errors </LI>
 		<LI> 43X00-43Yxx  for org.apache.derby.impl.sql.execute.rts
@@ -571,6 +572,7 @@
 	** to the appropriate group. Language errors are divided into 3 groups:
 	** A group for standard SQLExceptions.
 	**
+	** 2200J-00R - For SQL/XML errors (based on SQL/XML[2003]).
 	** 428?? - adding some DB2 compatible errors
 	** 42X00-42Zxx for compilation errors 
 	** 46000  for SQLJ errors (for now, leave this range empty)
@@ -671,6 +673,11 @@
 	String LANG_FK_VIOLATION                                           = "23503";
 	String LANG_CHECK_CONSTRAINT_VIOLATED                              = "23513";
 
+	// From SQL/XML[2003] spec; there are others, but
+	// these are the ones we actually use with our
+	// current XML support.
+	String LANG_NOT_AN_XML_DOCUMENT                                    = "2200L";
+
 	String LANG_INVALID_TRANSACTION_STATE                              = "25000";
 
 	String LANG_UNEXPECTED_USER_EXCEPTION                              = "38000";
@@ -1184,6 +1191,16 @@
 	String LANG_COLUMN_NAME_NOT_FOUND                                  = "X0X0F.S";
 
 	String LANG_INDEX_NOT_FOUND_DURING_EXECUTION                       = "X0X99.S";
+
+	// For Derby-specific XML errors (not defined by
+	// SQL/XML standard).
+	String LANG_ATTEMPT_TO_BIND_XML                                    = "X0X14.S";
+	String LANG_ATTEMPT_TO_SELECT_XML                                  = "X0X15.S";
+	String LANG_XML_KEYWORD_MISSING                                    = "X0X16.S";
+	String LANG_INVALID_XMLSERIALIZE_TYPE                              = "X0X17.S";
+	String LANG_UNSUPPORTED_XML_FEATURE                                = "X0X18.S";
+	String LANG_UNEXPECTED_XML_EXCEPTION                               = "X0XML.S";
+
 	// X0Y01 used to be DUPLICATE_KEY_CONSTRAINT
 	String LANG_DROP_VIEW_ON_NON_VIEW                                  = "X0Y16.S";
 	// String LANG_DROP_SYSTEM_TABLE_ATTEMPTED_DURING_EXECUTION           = "X0Y17.S";

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java Wed Jun  8 23:48:34 2005
@@ -511,11 +511,13 @@
         /* 449 */       "org.apache.derby.catalog.types.TypesImplInstanceGetter",
         /* 450 */       "org.apache.derby.iapi.types.DTSClassInfo", //InstanceGetter,
 
- 
         /* 451 */   "org.apache.derby.catalog.types.RoutineAliasInfo",
 		/* 452 */   null,
 		/* 453 */   "org.apache.derby.impl.store.raw.log.ChecksumOperation",
 		/* 454 */   "org.apache.derby.impl.store.raw.data.CompressSpacePageOperation",
-		/* 455 */   "org.apache.derby.catalog.types.SynonymAliasInfo"
+		/* 455 */   "org.apache.derby.catalog.types.SynonymAliasInfo",
+        /* 456 */   "org.apache.derby.iapi.types.DTSClassInfo", //InstanceGetter, XML_TYPE_ID
+        /* 457 */   "org.apache.derby.catalog.types.TypesImplInstanceGetter", // XML_TYPE_ID_IMPL
+        /* 458 */   "org.apache.derby.iapi.types.DTSClassInfo" //InstanceGetter, XML_ID
 };
 }

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java Wed Jun  8 23:48:34 2005
@@ -466,6 +466,12 @@
                 (MIN_ID_2 + 441);
 
         /**
+                Instance of TypeId for XML data types.
+         */
+        static public final int XML_TYPE_ID =
+                (MIN_ID_2 + 456);
+        
+        /**
             class org.apache.derby.iapi.types.JSQLType
          */
         static public final int JSQLTYPEIMPL_ID =
@@ -765,7 +771,7 @@
          */
         static public final int TIMESTAMP_TYPE_ID =
                 (MIN_ID_2 + 36);
-
+        
         /**
             class org.apache.derby.catalog.types.DecimalTypeIdImpl
          */
@@ -840,6 +846,12 @@
         static public final int NCLOB_TYPE_ID_IMPL =
                 (MIN_ID_2 + 449);
         
+        /**
+            class org.apache.derby.iapi.types.XML (implementation of
+            org.apache.derby.iapi.types.XMLDataValue).
+         */
+        static public final int XML_TYPE_ID_IMPL =
+                (MIN_ID_2 + 457);
 
         /******************************************************************
         **
@@ -1507,6 +1519,10 @@
         public static final int SQL_NCLOB_ID = 
                 (MIN_ID_2 + 450);
 
+        // Interface: org.apache.derby.iapi.types.XMLDataValue
+        public static final int XML_ID = 
+                (MIN_ID_2 + 458);
+
         /******************************************************************
         ** 
         ** Access ids.
@@ -1811,7 +1827,7 @@
          * Make sure this is updated when a new module is added
          */
         public static final int MAX_ID_2 =
-                (MIN_ID_2 + 455);
+                (MIN_ID_2 + 458);
 
         // DO NOT USE 4 BYTE IDS ANYMORE
         static public final int MAX_ID_4 =

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/C_NodeTypes.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/C_NodeTypes.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/C_NodeTypes.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/C_NodeTypes.java Wed Jun  8 23:48:34 2005
@@ -209,6 +209,12 @@
     // for SAVEPOINT sql
     static final int SAVEPOINT_NODE = 198;
 
+    // XML
+    static final int XML_CONSTANT_NODE = 199;
+    static final int XML_PARSE_OPERATOR_NODE = 200;
+    static final int XML_SERIALIZE_OPERATOR_NODE = 201;
+    static final int XML_EXISTS_OPERATOR_NODE = 202;
+
     /**
      * Extensions to this interface can use nodetypes > MAX_NODE_TYPE with out fear of collision
      * with C_NodeTypes

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DTSClassInfo.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DTSClassInfo.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DTSClassInfo.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DTSClassInfo.java Wed Jun  8 23:48:34 2005
@@ -57,6 +57,7 @@
                 case StoredFormatIds.SQL_BLOB_ID: return new SQLBlob();
                 case StoredFormatIds.SQL_CLOB_ID: return new SQLClob();
                 case StoredFormatIds.SQL_NCLOB_ID: return new SQLNClob();
+                case StoredFormatIds.XML_ID: return new XML();
 
                 /* Type ids */
                 case StoredFormatIds.BIT_TYPE_ID: 
@@ -84,6 +85,7 @@
                 case StoredFormatIds.BLOB_TYPE_ID:
                 case StoredFormatIds.CLOB_TYPE_ID:
                 case StoredFormatIds.NCLOB_TYPE_ID:
+                case StoredFormatIds.XML_TYPE_ID:
                         return new TypeId(fmtId);
                 default:
                         return null;

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeUtilities.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeUtilities.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeUtilities.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeUtilities.java Wed Jun  8 23:48:34 2005
@@ -23,6 +23,7 @@
 import org.apache.derby.iapi.error.StandardException;
 
 import org.apache.derby.iapi.reference.JDBC30Translation;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
 
 import java.sql.Types;
 import java.sql.ResultSetMetaData;
@@ -49,7 +50,8 @@
 		case Types.BINARY:     	// BINARY types return their # bytes...
 		case Types.VARBINARY:
 		case Types.LONGVARBINARY:
-			case Types.BLOB:
+		case Types.BLOB:
+		case StoredFormatIds.XML_TYPE_ID:
 				return dtd.getMaximumWidth();
 			case Types.SMALLINT:
 				return 5;
@@ -102,7 +104,8 @@
 		return (typeId == Types.CHAR ||
 		          typeId == Types.VARCHAR ||
 		          typeId == Types.CLOB ||
-		          typeId == Types.LONGVARCHAR);
+		          typeId == Types.LONGVARCHAR ||
+		          typeId == StoredFormatIds.XML_TYPE_ID);
 	}
 	/**
 		Is the data type nullable.

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactory.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactory.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactory.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactory.java Wed Jun  8 23:48:34 2005
@@ -453,6 +453,14 @@
         public DateTimeDataValue getTimestampValue( String timestampStr, boolean isJdbcEscape) throws StandardException;
 
         /**
+         * Get a null XML value. The second form re-uses the previous value,
+         * if non-null, as the data holder to return.
+         */
+        XMLDataValue getXMLDataValue();
+        XMLDataValue getXMLDataValue(XMLDataValue previous)
+			throws StandardException;
+
+        /**
          * Get a SQL int with a SQL null value. If the supplied value
          * is null then get a new value, otherwise set it to null and return 
          * that value.
@@ -655,4 +663,11 @@
          * that value.
          */
         DateTimeDataValue       getNullTimestamp(DateTimeDataValue dataValue);
+
+        /**
+         * Get an XML with a SQL null value. If the supplied value is
+         * null then get a new value, otherwise set it to null and return 
+         * that value.
+         */
+        XMLDataValue            getNullXML(XMLDataValue dataValue);
 }

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactoryImpl.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactoryImpl.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueFactoryImpl.java Wed Jun  8 23:48:34 2005
@@ -1027,6 +1027,57 @@
     } // end of getTimestampValue( String timestampStr)
 
 
+    /**
+     * getXMLDataValue:
+     * Get a SQL null value with XML type.
+     * @return An XMLDataValue instance corresponding to a
+     *  a NULL value.
+     */
+    public XMLDataValue getXMLDataValue()
+    {
+        return new XML();
+    }
+
+    /**
+     * getXMLDataValue:
+     * Get a null XML  value.  If a non-null XMLDataValue is
+     * received then re-use that instance, otherwise create
+	 * a new one.
+     * @param previous An XMLDataValue instance to re-use.
+     * @return An XMLDataValue instance corresponding to a
+     *  NULL value.  If an XMLDataValue was received, the
+     *  returned XMLDataValue is the same instance as the one
+     *  received, but the actual data has been set to a
+     *  SQL null value.
+     * @exception StandardException Thrown on error
+     */
+    public XMLDataValue getXMLDataValue(XMLDataValue previous)
+		throws StandardException
+    {
+		return getNullXML(previous);
+    }
+
+    /**
+     * getNullXML:
+     * Get an XML with a SQL null value. If the supplied value is
+     * null then get a new value, otherwise set it to null and return 
+     * that value.
+     * @param dataValue An XMLDataValue instance to re-use.
+     * @return An XMLDataValue instance corresponding to a
+     *  NULL value.  If an XMLDataValue was received, the
+     *  returned XMLDataValue is the same instance as the one
+     *  received, but the actual data has been set to null.
+     */
+    public XMLDataValue getNullXML(XMLDataValue dataValue)
+    {
+        if (dataValue == null)
+            return getXMLDataValue();
+        else {
+            dataValue.setToNull();
+            return dataValue;
+        }
+    }
+
         // RESOLVE: This is here to find the LocaleFinder (i.e. the Database)
         // on first access. This is necessary because the Monitor can't find
         // the Database at boot time, because the Database is not done booting.

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java Wed Jun  8 23:48:34 2005
@@ -2732,4 +2732,46 @@
 		this.intLength = intLength;
 		this.localeFinder = localeFinder;
 	}
+
+    /*
+     * Implementation of the XMLParse operator.
+     *
+     * NOTE: The XMLParse operator is implemented here (and
+     * defined on the StringDataValue interface) since it is
+     * called with a _String_ operand, not with an XML operand.
+     * That said, though, the bulk of the work is done by
+     * calling the "parseAndLoadXML" method that is defined on
+     * XMLDataValue.
+     * @param result The result of a previous call to this method,
+     *  null if not called yet.
+     * @return An XML value containing the result of XMLParse IF
+     *  the String data in this SQLChar constitutes valid XML.
+     *  Otherwise, an exception is thrown.
+     * @exception StandardException Thrown on error
+     */
+    public XMLDataValue XMLParse(XMLDataValue result, boolean preserveWS)
+        throws StandardException
+    {
+
+        if (result == null)
+        {
+            result = new XML();
+        }
+
+        if (this.isNull())
+        {
+            result.setToNull();
+            return result;
+        }
+
+        // First make sure that the string is valid, well-formed XML.
+        String str = getString();
+        result.parseAndLoadXML(str, preserveWS);
+
+        // If we get here, the character string is valid XML
+		// and was loaded, so we're done.
+        return result;
+
+    }
+
 }

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/StringDataValue.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/StringDataValue.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/StringDataValue.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/StringDataValue.java Wed Jun  8 23:48:34 2005
@@ -146,4 +146,24 @@
 	 * @exception StandardException		Thrown on error
 	 */
 	public char[] getCharArray() throws StandardException;
+
+    /*
+     * Get an XML value from a string.
+     *
+     * NOTE: The XMLParse operator is defined here since it
+     * is called with a _String_ operand, not with an XML
+     * operand.  That said, though, the bulk of the work is
+     * is done by a corresponding method that is defined
+     * on the XMLDataValue interface (implementations
+     * of this method should just call the XMLDataValue
+     * method, passing in the correct String data).
+     *
+     * @param result The result (reusable - allocate if null).
+     * @return An XML value corresponding to the string, if
+     *  the string is valid XML.
+     * @exception StandardException Thrown on error
+     */
+    public XMLDataValue XMLParse(XMLDataValue result, boolean preserveWS)
+        throws StandardException;
+
 }

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java Wed Jun  8 23:48:34 2005
@@ -114,6 +114,7 @@
         public static final int BLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long
         public static final int CLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long
         public static final int NCLOB_MAXWIDTH = Integer.MAX_VALUE; // to change long
+        public static final int XML_MAXWIDTH = Integer.MAX_VALUE;
 
         // Max width for datetime values is the length of the
         // string returned from a call to "toString()" on the
@@ -168,12 +169,17 @@
         public static final String      BLOB_NAME = "BLOB";
         public static final String      CLOB_NAME = "CLOB";
         public static final String      NCLOB_NAME = "NCLOB";
+
+        // Following use of "XML" is per SQL/XML (2003) spec,
+        // section "10.2 Type name determination".
+        public static final String      XML_NAME = "XML";
         
         /**
          * The following constants define the type precedence hierarchy.
          */
         public static final int USER_PRECEDENCE  = 1000;
 
+        public static final int XML_PRECEDENCE       = 180;
         public static final int BLOB_PRECEDENCE = 170;
         public static final int LONGVARBIT_PRECEDENCE = 160;
         public static final int VARBIT_PRECEDENCE        = 150;
@@ -239,6 +245,7 @@
         private static TypeId                   BLOB_ID;
         private static TypeId                   CLOB_ID;
         private static TypeId                   NCLOB_ID;
+        private static TypeId                   XML_ID;
 
         /**
          * Implementation of DECIMAL datatype for generating holders through getNull.
@@ -397,6 +404,15 @@
                           ret = CLOB_ID = new TypeId(StoredFormatIds.CLOB_TYPE_ID,
                                                      new BaseTypeIdImpl(StoredFormatIds.CLOB_TYPE_ID_IMPL));
                       break;
+
+                  // XML is not a JDBC type, so we have to check for our
+                  // internal XML type.
+                  case StoredFormatIds.XML_TYPE_ID:
+                      ret = XML_ID;
+                      if (ret == null)
+                          ret = XML_ID = new TypeId(StoredFormatIds.XML_TYPE_ID,
+                                                     new BaseTypeIdImpl(StoredFormatIds.XML_TYPE_ID_IMPL));
+                      break;
                 }
                 return ret;
         }
@@ -484,6 +500,10 @@
                 {
                         return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_CLOB);
                 }
+                else if (javaTypeName.equals("org.apache.derby.iapi.types.XML"))
+                {
+                        return getBuiltInTypeId(StoredFormatIds.XML_TYPE_ID);
+                }
                 else
                 {
                         /*
@@ -571,6 +591,9 @@
                 if (SQLTypeName.equals(TypeId.CLOB_NAME)) {
                         return getBuiltInTypeId(JDBC20Translation.SQL_TYPES_CLOB);
                 }
+                if (SQLTypeName.equals(TypeId.XML_NAME)) {
+                        return getBuiltInTypeId(StoredFormatIds.XML_TYPE_ID);
+                }
 
                 TypeId ret = null;
 
@@ -931,6 +954,12 @@
                               isLOBTypeId = true;
                               break;
 
+                      case StoredFormatIds.XML_TYPE_ID:
+                              typePrecedence = XML_PRECEDENCE;
+                              javaTypeName = "org.apache.derby.iapi.types.XML";
+                              maxMaxWidth = TypeId.XML_MAXWIDTH;
+                              break;
+
                 }
         }
         /**
@@ -1170,6 +1199,15 @@
                 }
         }
 
+        /** 
+         *Is this an XML doc?
+         * @return true if this is XML
+         */
+        public boolean isXMLTypeId()
+        {
+               return (formatId == StoredFormatIds.XML_TYPE_ID);
+        }
+
         /**
          * Tell whether this is a built-in type.
          * NOTE: There are 3 "classes" of types:
@@ -1206,6 +1244,7 @@
                         case StoredFormatIds.NCLOB_TYPE_ID:
                         case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
                         case StoredFormatIds.LONGVARCHAR_TYPE_ID:
+                        case StoredFormatIds.XML_TYPE_ID:
                                 return false;
 
                         case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
@@ -1568,6 +1607,9 @@
                         case StoredFormatIds.VARCHAR_TYPE_ID:
                                 return new SQLVarchar();
 
+                        case StoredFormatIds.XML_TYPE_ID:
+                                return new XML();
+
                         default:
                                 if (SanityManager.DEBUG)
                                 {
@@ -1628,6 +1670,8 @@
                         case StoredFormatIds.BLOB_TYPE_ID:
                         case StoredFormatIds.CLOB_TYPE_ID:
                         case StoredFormatIds.NCLOB_TYPE_ID:
+                        // RESOLVE: Should XML be here?  What's this value mean, anyway?
+                        case StoredFormatIds.XML_TYPE_ID:
                                 return 10240;
 
                         case StoredFormatIds.REF_TYPE_ID:
@@ -1772,6 +1816,12 @@
 // none of the LONG_VARCHAR types are true here...????
 //                        case StoredFormatIds.CLOB_TYPE_ID:
 //                        case StoredFormatIds.NCLOB_TYPE_ID:
+                        // RESOLVE: does "variableLength" here mean simply
+                        // that the length is variable, or that the user
+                        // can specify a length, such as "char(20)"?  The
+                        // answer to that determines where XML is supposed
+                        // to be...
+                        case StoredFormatIds.XML_TYPE_ID:
                                 return true;
 
                         default:

Added: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XML.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XML.java?rev=189721&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XML.java (added)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XML.java Wed Jun  8 23:48:34 2005
@@ -0,0 +1,861 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.types.XML
+
+   Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.types;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.services.cache.ClassSize;
+import org.apache.derby.iapi.services.io.ArrayInputStream;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
+import org.apache.derby.iapi.services.io.StreamStorable;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.iapi.types.StringDataValue;
+import org.apache.derby.iapi.types.BooleanDataValue;
+
+import org.apache.derby.iapi.reference.SQLState;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectInput;
+import java.io.StringReader;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.XMLReader;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.InputSource;
+
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerFactory;
+
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.TemplatesHandler;
+import javax.xml.transform.sax.TransformerHandler;
+
+// Note that even though the following has a Xalan
+// package name, it IS part of the JDK 1.4 API, and
+// thus we can compile it without having Xalan in
+// our classpath.
+import org.apache.xalan.processor.TransformerFactoryImpl;
+
+/**
+ * This type implements the XMLDataValue interface and thus is
+ * the type on which all XML related operations are executed.
+ *
+ * The first and simplest XML store implementation is a UTF-8
+ * based one--all XML data is stored on disk as a UTF-8 string,
+ * just like the other Derby string types.  In order to make
+ * it possible for smarter XML implementations to exist in
+ * the future, this class always writes an "XML implementation
+ * id" to disk before writing the rest of its data.  When
+ * reading the data, the impl id is read first and serves
+ * as an indicator of how the rest of the data should be
+ * read.
+ *
+ * So long as there's only one implementation (UTF-8)
+ * the impl id can be ignored; but when smarter implementations
+ * are written, the impl id will be the key to figuring out
+ * how an XML value should be read, written, and processed.
+ */
+public class XML
+    extends DataType implements XMLDataValue, StreamStorable
+{
+    // Id for this implementation.  Should be unique
+    // across all XML type implementations.
+    protected static final short UTF8_IMPL_ID = 0;
+
+    // Parser class to use for parsing XML.  We use the
+    // Xerces parser, so (for now) we require that Xerces
+    // be in the user's classpath.  Note that we load
+    // the Xerces class dynamically (using the class 
+    // name) so that Derby will build even if Xerces
+    // isn't in the build environment; i.e. Xerces is
+    // only required if XML is actually going to be used
+    // at runtime; it's not required for a successful
+    // build nor for non-XML database use.
+    protected static final String XML_PARSER_CLASS =
+        "org.apache.xerces.parsers.SAXParser";
+
+    // Guess at how much memory this type will take.
+    private static final int BASE_MEMORY_USAGE =
+        ClassSize.estimateBaseFromCatalog(XML.class);
+
+    // The actual XML data in this implementation is just a simple
+    // string, so this class really just wraps a SQLChar and
+    // defers most calls to the corresponding calls on that
+    // SQLChar.  Note that, even though a SQLChar is the
+    // underlying implementation, an XML value is nonetheless
+    // NOT considered comparable nor compatible with any of
+    // Derby string types.
+    private SQLChar xmlStringValue;
+
+    // An XML reader for reading and parsing SAX events.
+    protected XMLReader saxReader;
+
+    // XSLT objects used when performing an XSLT query, which
+    // is the query mechanism for this UTF8-based implementation.
+    private static final String XPATH_PLACEHOLDER = "XPATH_PLACEHOLDER";
+    private static final String QUERY_MATCH_STRING = "MATCH";
+    private static String xsltStylesheet;
+    private XMLReader xsltReader;
+    private TransformerFactoryImpl saxTFactory;
+
+    /**
+     * Default constructor.
+     */
+    public XML()
+    {
+        xmlStringValue = null;
+    }
+
+    /**
+     * Private constructor used for the getClone() method.
+     * Takes a SQLChar and clones it.
+     * @param val A SQLChar instance to clone and use for
+     *  this XML value.
+     */
+    private XML(SQLChar val)
+    {
+        xmlStringValue = (val == null ? null : (SQLChar)val.getClone());
+    }
+
+    /* ****
+     * DataValueDescriptor interface.
+     * */
+
+    /**
+     * @see DataValueDescriptor#getClone
+     */
+    public DataValueDescriptor getClone()
+    {
+        return new XML(xmlStringValue);
+    }
+
+    /**
+     * @see DataValueDescriptor#getNewNull
+     */
+    public DataValueDescriptor getNewNull()
+    {
+        return new XML();
+    }
+
+    /**
+     * @see DataValueDescriptor#getTypeName
+     */
+    public String getTypeName()
+    {
+        return TypeId.XML_NAME;
+    }
+
+    /**
+     * @see DataValueDescriptor#typePrecedence
+     */
+    public int typePrecedence()
+    {
+        return TypeId.XML_PRECEDENCE;
+    }
+
+    /**
+     * @see DataValueDescriptor#getString
+     */
+    public String getString() throws StandardException
+    {
+        return (xmlStringValue == null) ? null : xmlStringValue.getString();
+    }
+
+    /**
+     * @see DataValueDescriptor#getLength
+     */
+    public int    getLength() throws StandardException
+    {
+        return ((xmlStringValue == null) ? 0 : xmlStringValue.getLength());
+    }
+
+    /** 
+     * @see DataValueDescriptor#estimateMemoryUsage
+     */
+    public int estimateMemoryUsage()
+    {
+        int sz = BASE_MEMORY_USAGE;
+        if (xmlStringValue != null)
+            sz += xmlStringValue.estimateMemoryUsage();
+        return sz;
+    }
+
+    /**
+     * @see DataValueDescriptor#readExternalFromArray
+     */
+    public void readExternalFromArray(ArrayInputStream in)
+        throws IOException
+    {
+        if (xmlStringValue == null)
+            xmlStringValue = new SQLChar();
+
+        // Read the XML implementation id.  Right now there's
+        // only one implementation (UTF-8 based), so we don't
+        // use this value.  But if better implementations come
+        // up in the future, we'll have to use this impl id to
+        // figure out how to read the data.
+        in.readShort();
+
+        // Now just read the XML data as UTF-8.
+        xmlStringValue.readExternalFromArray(in);
+    }
+
+    /**
+     * @see DataValueDescriptor#setFrom
+     */
+    protected void setFrom(DataValueDescriptor theValue)
+        throws StandardException
+    {
+        if (xmlStringValue == null)
+            xmlStringValue = new SQLChar();
+        xmlStringValue.setValue(theValue.getString());
+    }
+
+    /** 
+     * @see DataValueDescriptor#setValueFromResultSet 
+     */
+    public final void setValueFromResultSet(
+        ResultSet resultSet, int colNumber, boolean isNullable)
+        throws SQLException
+    {
+        if (xmlStringValue == null)
+            xmlStringValue = new SQLChar();
+        xmlStringValue.setValue(resultSet.getString(colNumber));
+    }
+
+    /**
+     * Compare two XML DataValueDescriptors.  NOTE: This method
+     * should only be used by the database store for the purpose of
+     * index positioning--comparisons of XML type are not allowed
+     * from the language side of things.  That said, all store
+     * wants to do is order the NULLs, so we don't actually
+     * have to do a full comparison.  Just return an order
+     * value based on whether or not this XML value and the
+     * other XML value are null.  As mentioned in the "compare"
+     * method of DataValueDescriptor, nulls are considered
+     * equal to other nulls and less than all other values.
+     *
+     * An example of when this method might be used is if the
+     * user executed a query like:
+     *
+     * select i from x_table where x_col is not null
+     *
+     * @see DataValueDescriptor#compare
+     */
+    public int compare(DataValueDescriptor other)
+        throws StandardException
+    {
+        if (SanityManager.DEBUG) {
+            SanityManager.ASSERT(other instanceof XMLDataValue,
+                "Store should NOT have tried to compare an XML value " +
+                "with a non-XML value.");
+        }
+
+        if (isNull()) {
+            if (other.isNull())
+            // both null, so call them 'equal'.
+                return 0;
+            // This XML is 'less than' the other.
+            return -1;
+        }
+
+        if (other.isNull())
+        // This XML is 'greater than' the other.
+            return 1;
+
+        // Two non-null values: we shouldn't ever get here,
+        // since that would necessitate a comparsion of XML
+        // values, which isn't allowed.
+        if (SanityManager.DEBUG) {
+            SanityManager.THROWASSERT(
+                "Store tried to compare two non-null XML values, " +
+                "which isn't allowed.");
+        }
+        return 0;
+    }
+
+    /* ****
+     * Storable interface, implies Externalizable, TypedFormat
+     */
+
+    /**
+     * @see TypedFormat#getTypeFormatId
+     *
+     * From the engine's perspective, all XML implementations share
+     * the same format id.
+     */
+    public int getTypeFormatId() {
+        return StoredFormatIds.XML_ID;
+    }
+
+    /**
+     * @see Storable#isNull
+     */
+    public boolean isNull()
+    {
+        return ((xmlStringValue == null) || xmlStringValue.isNull());
+    }
+
+    /**
+     * @see Storable#restoreToNull
+     */
+    public void restoreToNull()
+    {
+        if (xmlStringValue != null)
+            xmlStringValue.restoreToNull();
+    }
+
+    /**
+     * Read an XML value from an input stream.
+     * @param in The stream from which we're reading.
+     */
+    public void readExternal(ObjectInput in) throws IOException
+    {
+        if (xmlStringValue == null)
+            xmlStringValue = new SQLChar();
+
+        // Read the XML implementation id.  Right now there's
+        // only one implementation (UTF-8 based), so we don't
+        // use this value.  But if better implementations come
+        // up in the future, we'll have to use this impl id to
+        // figure out how to read the data.
+        in.readShort();
+
+        // Now just read the XML data as UTF-8.
+        xmlStringValue.readExternal(in);
+    }
+
+    /**
+     * Write an XML value. 
+     * @param out The stream to which we're writing.
+     */
+    public void writeExternal(ObjectOutput out) throws IOException
+    {
+        // never called when value is null
+        if (SanityManager.DEBUG)
+            SanityManager.ASSERT(!isNull());
+
+        // Write out the XML store impl id.
+        out.writeShort(UTF8_IMPL_ID);
+
+        // Now write out the data.
+        xmlStringValue.writeExternal(out);
+    }
+
+    /* ****
+     * StreamStorable interface
+     * */
+
+    /**
+     * @see StreamStorable#returnStream
+     */
+    public InputStream returnStream()
+    {
+        return
+            (xmlStringValue == null) ? null : xmlStringValue.returnStream();
+    }
+
+    /**
+     * @see StreamStorable#setStream
+     */
+    public void setStream(InputStream newStream)
+    {
+        if (xmlStringValue == null)
+            xmlStringValue = new SQLChar();
+
+        // The stream that we receive is for an XML data value,
+        // which means it has an XML implementation id stored
+        // at the front (we put it there when we wrote it out).
+        // If we leave that there we'll get a failure when
+        // our underlying SQLChar tries to read from the
+        // stream, because the extra impl id will throw
+        // off the UTF format.  So we need to read in (and
+        // ignore) the impl id before using the stream.
+        try {
+            // 2 bytes equal a short, which is what an impl id is.
+            newStream.read();
+            newStream.read();
+        } catch (Exception e) {
+            if (SanityManager.DEBUG)
+                SanityManager.THROWASSERT("Failed to read impl id" +
+                    "bytes in setStream.");
+        }
+
+        // Now go ahead and use the stream.
+        xmlStringValue.setStream(newStream);
+    }
+
+    /**
+     * @see StreamStorable#loadStream
+     */
+    public void loadStream() throws StandardException
+    {
+        getString();
+    }
+
+    /* ****
+     * XMLDataValue interface.
+     * */
+
+    /**
+     * Method to parse an XML string and, if it's valid,
+     * store the _parsed_ version for subsequent use.
+     * @param text The string value to check.
+     * @param preserveWS Whether or not to preserve
+     *  ignorable whitespace.
+     * @return  If 'text' constitutes a valid XML document,
+     *  it has been stored in this XML value and nothing
+     *  is returned; otherwise, an exception is thrown.
+     * @exception StandardException Thrown on parse error.
+     */
+    public void parseAndLoadXML(String text, boolean preserveWS)
+        throws StandardException
+    {
+        try {
+
+            if (preserveWS) {
+            // We're just going to use the text exactly as it
+            // is, so we just need to see if it parses. 
+                loadSAXReader();
+                saxReader.parse(
+                    new InputSource(new StringReader(text)));
+            }
+            else {
+            // We don't support this yet, so we shouldn't
+            // get here.
+                if (SanityManager.DEBUG)
+                    SanityManager.THROWASSERT("Tried to STRIP whitespace " +
+                        "but we shouldn't have made it this far");
+            }
+
+        } catch (Exception xe) {
+        // The text isn't a valid XML document.  Throw a StandardException
+        // with the parse exception nested in it.
+            throw StandardException.newException(
+                SQLState.LANG_NOT_AN_XML_DOCUMENT, xe);
+        }
+
+        // If we get here, the text is valid XML so go ahead
+        // and load/store it.
+        if (xmlStringValue == null)
+            xmlStringValue = new SQLChar();
+        xmlStringValue.setValue(text);
+        return;
+    }
+
+    /**
+     * The SQL/XML XMLSerialize operator.
+     * Converts this XML value into a string with a user-specified
+     * type, and returns that string via the received StringDataValue
+     * (if the received StringDataValue is non-null; else a new
+     * StringDataValue is returned).
+     * @param result The result of a previous call to this method,
+     *    null if not called yet.
+     * @param targetType The string type to which we want to serialize.
+     * @param targetWidth The width of the target type.
+     * @return A serialized (to string) version of this XML object,
+     *  in the form of a StringDataValue object.
+     * @exception StandardException    Thrown on error
+     */
+    public StringDataValue XMLSerialize(StringDataValue result,
+        int targetType, int targetWidth) throws StandardException
+    {
+        if (result == null) {
+            switch (targetType)
+            {
+                case Types.CHAR:        result = new SQLChar(); break;
+                case Types.VARCHAR:     result = new SQLVarchar(); break;
+                case Types.LONGVARCHAR: result = new SQLLongvarchar(); break;
+                case Types.CLOB:        result = new SQLClob(); break;
+                default:
+                // Shouldn't ever get here, as this check was performed
+                // at bind time.
+
+                    if (SanityManager.DEBUG) {
+                        SanityManager.THROWASSERT(
+                            "Should NOT have made it to XMLSerialize " +
+                            "with a non-string target type.");
+                    }
+                    return null;
+            }
+        }
+
+        // Else we're reusing a StringDataValue.  We only reuse
+        // the result if we're executing the _same_ XMLSERIALIZE
+        // call on multiple rows.  That means that all rows
+        // must have the same result type (targetType) and thus
+        // we know that the StringDataValue already has the
+        // correct type.  So we're set.
+
+        if (this.isNull()) {
+        // Attempts to serialize a null XML value lead to a null
+        // result (SQL/XML[2003] section 10.13).
+            result.setToNull();
+            return result;
+        }
+
+        // Get the XML value as a string.  For this UTF-8 impl,
+        // we already have it as a string, so just use that.
+        result.setValue(xmlStringValue.getString());
+
+        // Seems wrong to trunc an XML document, as it then becomes non-
+        // well-formed and thus useless.  So we throw an error (that's
+        // what the "true" in the next line says).
+        result.setWidth(targetWidth, 0, true);
+        return result;
+    }
+
+    /**
+     * The SQL/XML XMLExists operator.
+     * Takes an XML query expression (as a string) and an XML
+     * value and checks if at least one node in the XML
+     * value matches the query expression.  NOTE: For now,
+     * the query expression must be XPath only (XQuery not
+     * supported).
+     * @param xExpr The query expression, as a string.
+     * @param xml The XML value being queried.
+     * @return True if the received query expression matches at
+     *  least one node in the received XML value; unknown if
+     *  either the query expression or the xml value is null;
+     *  false otherwise.
+     * @exception StandardException Thrown on error
+     */
+    public BooleanDataValue XMLExists(StringDataValue xExpr,
+        XMLDataValue xml) throws StandardException
+    {
+        if ((xExpr == null) || xExpr.isNull())
+        // If the query is null, we assume unknown.
+            return SQLBoolean.unknownTruthValue();
+
+        if ((xml == null) || xml.isNull())
+        // Then per SQL/XML spec 8.4, we return UNKNOWN.
+            return SQLBoolean.unknownTruthValue();
+
+        return new SQLBoolean(xml.exists(xExpr.getString()));
+    }
+
+    /**
+     * Helper method for XMLExists.
+     * See if the received XPath expression returns at least
+     * one node when evaluated against _this_ XML value.
+     * @param xExpr The XPath expression.
+     * @return True if at least one node in this XML value
+     *  matches the received xExpr; false otherwise.
+     */
+    public boolean exists(String xExpr) throws StandardException
+    {
+        // NOTE: At some point we'll probably need to implement some
+        // some kind of query cache so that we don't have to recompile
+        // the same query over and over for every single XML row
+        // in a table.  That's what we do right now...
+
+        try {
+
+            xExpr = replaceDoubleQuotes(xExpr);
+            loadXSLTObjects();
+
+            // Take our simple stylesheet and plug in the query.
+            int pos = xsltStylesheet.indexOf(XPATH_PLACEHOLDER);
+            StringBuffer stylesheet = new StringBuffer(xsltStylesheet);
+            stylesheet.replace(pos, pos + XPATH_PLACEHOLDER.length(), xExpr);
+
+            // Create a Templates ContentHandler to handle parsing of the 
+            // stylesheet.
+            TemplatesHandler templatesHandler = 
+                saxTFactory.newTemplatesHandler();
+            xsltReader.setContentHandler(templatesHandler);
+    
+            // Now parse the generic stylesheet we created.
+            xsltReader.parse(
+                new InputSource(new StringReader(stylesheet.toString())));
+
+            // Get the Templates object (generated during the parsing of
+            // the stylesheet) from the TemplatesHandler.
+            Templates compiledQuery = templatesHandler.getTemplates();
+
+            // Create a Transformer ContentHandler to handle parsing of 
+            // the XML Source.  
+            TransformerHandler transformerHandler 
+                = saxTFactory.newTransformerHandler(compiledQuery);
+
+            // Reset the XMLReader's ContentHandler to the TransformerHandler.
+            xsltReader.setContentHandler(transformerHandler);
+
+            // Create an ExistsHandler.  When the XSLT transformation
+            // occurs, a period (".") will be thrown to this handler
+            // (via a SAX 'characters' event) for every matching
+            // node that XSLT finds.  This is how we know if a
+            // match was found.
+            ExistsHandler eH = new ExistsHandler();
+            transformerHandler.setResult(new SAXResult(eH));
+
+            // This call to "parse" is what does the query, because we
+            // passed in an XSLT handler with the compiled query above.
+            try {
+                xsltReader.parse(
+                    new InputSource(new StringReader(getString())));
+            } catch (Throwable th) {
+                if (th.getMessage().indexOf(
+                    "SAXException: " + QUERY_MATCH_STRING) == -1)
+                { // then this isn't the exception that means we have
+                  // a match; so re-throw it.
+                    throw new Exception(th.getMessage());
+                }
+            }
+
+            // Did we have any matches?
+            return eH.exists();
+
+        } catch (Exception xe) {
+        // We don't expect to get here.  Turn it into a
+        // StandardException, then throw it.
+            throw StandardException.newException(
+                SQLState.LANG_UNEXPECTED_XML_EXCEPTION, xe);
+        }
+    }
+
+    /* ****
+     * Helper classes and methods.
+     * */
+
+    /**
+     * Load an XMLReader for SAX events that can be used
+     * for parsing XML data.
+     *
+     * This method is currently only used for XMLPARSE, and
+     * the SQL/XML[2003] spec says that XMLPARSE should NOT
+     * perform validation -- Seciont 6.11:
+     *
+     *    "Perform a non-validating parse of a character string to
+     *    produce an XML value."
+     *
+     * Thus, we make sure to disable validation on the XMLReader
+     * loaded here.  At some point in the future we will probably
+     * want to add support for the XMLVALIDATE function--but until
+     * then, user is unable to validate the XML values s/he inserts.
+     *
+     * Note that, even with validation turned off, XMLPARSE
+     * _will_ still check the well-formedness of the values,
+     * and it _will_ still process DTDs to get default values,
+     * etc--but that's it; no validation errors will be thrown.
+     *
+     * For future reference: the features needed to perform
+     * validation (with Xerces) are:
+     *
+     * http://apache.org/xml/features/validation/schema
+     * http://apache.org/xml/features/validation/dynamic
+     */
+    protected void loadSAXReader() throws Exception
+    {
+        if (saxReader != null)
+        // already loaded.
+            return;
+
+        // Get an instance of an XMLReader.
+        saxReader = XMLReaderFactory.createXMLReader(XML_PARSER_CLASS);
+
+        // Turn off validation, since it's not allowed by
+        // SQL/XML[2003] spec.
+        saxReader.setFeature(
+            "http://xml.org/sax/features/validation", false);
+
+        // Make the parser namespace aware.
+        saxReader.setFeature(
+            "http://xml.org/sax/features/namespaces", true);
+
+        // We have to set the error handler in order to properly
+        // receive the parse errors.
+        saxReader.setErrorHandler(new XMLErrorHandler());
+    }
+
+    /**
+     * Prepare for an XSLT query by loading the objects
+     * required for such a query.  We should only have
+     * to do this once per XML object.
+     */
+    private void loadXSLTObjects() throws SAXException
+    {
+        if (xsltReader != null)
+        // we already loaded everything.
+            return;
+
+        // Instantiate a TransformerFactory.
+        TransformerFactory tFactory = TransformerFactory.newInstance();
+
+        // Cast the TransformerFactory to SAXTransformerFactory.
+        saxTFactory = (TransformerFactoryImpl)tFactory;
+
+        // Get an XML reader.
+        xsltReader = XMLReaderFactory.createXMLReader(XML_PARSER_CLASS);
+
+        // Make the parser namespace aware.  Note that because we
+        // only support a small subset of SQL/XML, and because we
+        // only allow XPath (as opposed to XQuery) expressions,
+        // there is no way for a user to specify namespace
+        // bindings as part of the XMLEXISTS operator.  This means
+        // that in order to query for a node name, the user must
+        // use the XPath functions "name()" and "local-name()"
+        // in conjunction with XPath 1.0 'namespace' axis.  For
+        // example:
+        //
+        // To see if any elements exist that have a specific name
+        // with ANY namespace:
+        //     //child::*[local-name()="someName"]
+        //
+        // To see if any elements exist that have a specific name
+        // with NO namespace:
+        //     //child::*[name()="someName"]
+        //
+        // To see if any elements exist that have a specific name
+        // in a specific namespace:
+        //     //child::*[local-name()=''someName'' and
+        //        namespace::*[string()=''http://www.some.namespace'']]
+        //
+        xsltReader.setFeature(
+            "http://xml.org/sax/features/namespaces", true);
+
+        // Create a very simple XSLT stylesheet.  This stylesheet
+        // will execute the XPath expression and, for every match,
+        // write a period (".") to the ExistsHandler (see the exists()
+        // method above).  Then, in order to see if at least one
+        // node matches, we just check to see if the ExistsHandler
+        // caught at least one 'characters' event.  If it did, then
+        // we know we had a match.
+        if (xsltStylesheet == null) {
+            StringBuffer sb = new StringBuffer();
+            sb.append("<xsl:stylesheet version=\"1.0\"\n");
+            sb.append("xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n");
+            sb.append(" <xsl:template match=\"/\">\n"); // Search whole doc...
+            sb.append("  <xsl:for-each select=\"");     // For every match...
+            sb.append(XPATH_PLACEHOLDER);               // using XPath expr...
+            sb.append("\">.</xsl:for-each>\n");         // Write a "."
+            sb.append(" </xsl:template>\n");
+            sb.append("</xsl:stylesheet>\n");
+            xsltStylesheet = sb.toString();
+        }
+    }
+
+    /**
+     * Takes a string (which is an XPath query specified by
+     * the user) and replaces any double quotes with single
+     * quotes.  We have to do this because a double quote
+     * in the XSLT stylesheet (which is where the user's
+     * query ends up) will be parsed as a query terminator
+     * thus will cause XSLT execution errors.
+     * @param queryText Text in which we want to replace double
+     *  quotes.
+     * @return queryText with all double quotes replaced by
+     *  single quotes.
+     */
+    private String replaceDoubleQuotes(String queryText)
+    {
+        int pos = queryText.indexOf("\"");
+        if (pos == -1)
+        // nothing to do.
+            return queryText;
+
+        StringBuffer sBuf = new StringBuffer(queryText);
+        while (pos >= 0) {
+            sBuf.replace(pos, pos+1, "'");
+            pos = queryText.indexOf("\"", pos+1);
+        }
+        return sBuf.toString();
+    }
+
+    /*
+     ** The XMLErrorHandler class is just a generic implementation
+     ** of the ErrorHandler interface.  It allows us to catch
+     ** and process XML parsing errors in a graceful manner.
+     */
+    private class XMLErrorHandler implements ErrorHandler
+    {
+        public void error (SAXParseException exception)
+            throws SAXException
+        {
+            throw new SAXException (exception);
+        }
+
+        public void fatalError (SAXParseException exception)
+            throws SAXException
+        {
+            throw new SAXException (exception);
+        }
+
+        public void warning (SAXParseException exception)
+            throws SAXException
+        {
+            throw new SAXException (exception);
+        }
+    }
+
+    /*
+     ** The ExistsHandler is what we pass to the XSLT processor
+     ** when we query.  The generic xsltStylesheet that we defined
+     ** above will throw a 'characters' event for every matching
+     ** node that is found by the XSLT transformation.  This
+     ** handler is the one that catches the event, and thus
+     ** it tells us whether or not we had a match.
+     */
+    private class ExistsHandler extends DefaultHandler
+    {
+        // Did we catch at least one 'characters' event?
+        private boolean atLeastOneMatch;
+
+        public ExistsHandler() {
+            atLeastOneMatch = false;
+        }
+
+        /*
+         * Catch a SAX 'characters' event, which tells us that
+         * we had at least one matching node.
+         */
+        public void characters(char[] ch, int start, int length)
+            throws SAXException
+        {
+            // If we get here, we had at least one matching node.
+            // Since that's all we need to know, we don't have
+            // to continue querying--we can stop the XSLT
+            // transformation now by throwing a SAX exception.
+            atLeastOneMatch = true;
+            throw new SAXException(QUERY_MATCH_STRING);
+        }
+
+        /*
+         * Tell whether or not this handler caught a match.
+         */
+        public boolean exists()
+        {
+            return atLeastOneMatch;
+        }
+    }
+}

Propchange: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XML.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XMLDataValue.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XMLDataValue.java?rev=189721&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XMLDataValue.java (added)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XMLDataValue.java Wed Jun  8 23:48:34 2005
@@ -0,0 +1,106 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.types.XMLDataValue
+
+   Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.types;
+
+import org.apache.derby.iapi.error.StandardException;
+
+public interface XMLDataValue extends DataValueDescriptor
+{
+    /*
+     ** NOTE: Officially speaking, the XMLParse operator
+     ** is not defined here; it is instead defined on the
+     ** StringDataValue interface (and implemented in
+     ** SQLChar.java) since it is called with a _String_
+     ** operand, not with an XML operand.  That said,
+     ** though, the implemention in SQLChar.java
+     ** really just calls the "parseAndLoadXML" method that's
+     ** defined on this interface, so it's this interface
+     ** that really does the work.
+     **
+     ** XMLSerialize and XMLExists, on the other hand,
+     ** are called with XML operands, and thus they
+     ** can just be defined in this interface.
+     */
+
+    /**
+     * Parse the received string value as XML.  If the
+     * parse succeeds, store the string value as the
+     * contents of this XML value.
+     *
+     * @param text The string value to check.
+     * @param preserveWS Whether or not to preserve
+     *  ignorable whitespace.
+     * @return  If 'text' constitutes a valid XML document,
+     *  it has been stored in this XML value and nothing
+     *  is returned; otherwise, an exception is thrown.
+     * @exception StandardException Thrown on parse error.
+     */
+    public void parseAndLoadXML(String xmlText, boolean preserveWS)
+        throws StandardException;
+
+    /**
+     * The SQL/XML XMLSerialize operator.
+     * Converts this XML value into a string with a user-specified
+     * type, and returns that string via the received StringDataValue.
+     * (if the received StringDataValue is non-null and of the
+     * correct type; else, a new StringDataValue is returned).
+     *
+     * @param result The result of a previous call to this method,
+     *  null if not called yet.
+     * @param targetType The string type to which we want to serialize.
+     * @param targetWidth The width of the target type.
+     * @return A serialized (to string) version of this XML object,
+     *  in the form of a StringDataValue object.
+     * @exception StandardException Thrown on error
+     */
+    public StringDataValue XMLSerialize(StringDataValue result,
+        int targetType, int targetWidth) throws StandardException;
+
+    /**
+     * The SQL/XML XMLExists operator.
+     * Takes an XML query expression (as a string) and an XML
+     * value and checks if at least one node in the XML
+     * value matches the query expression.  NOTE: For now,
+     * the query expression must be XPath only (XQuery not
+     * supported).
+     *
+     * @param xExpr The query expression, as a string.
+     * @param xml The XML value being queried.
+     * @return True if the received query expression matches at
+     *  least one node in the received XML value; unknown if
+     *  either the query expression or the xml value is null;
+     *  false otherwise.
+     * @exception StandardException Thrown on error
+     */
+    public BooleanDataValue XMLExists(StringDataValue xExpr,
+        XMLDataValue xml) throws StandardException;
+
+    /**
+     * Helper method for XMLExists.
+     * See if the received XPath expression returns at least
+     * one node when evaluated against _this_ XML value.
+     *
+     * @param xExpr The XPath expression.
+     * @return True if at least one node in this XML value
+     *  matches the received xExpr; false otherwise.
+     */
+    public boolean exists(String xExpr) throws StandardException;
+}

Propchange: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/XMLDataValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/build.xml
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/build.xml?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/build.xml (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/types/build.xml Wed Jun  8 23:48:34 2005
@@ -19,6 +19,24 @@
 <!-- Targets -->
 
   <target name="compile_types">
+    <!-- We only compile XML against JDK 1.4 because it relies on    -->
+    <!-- several XML classes that are part of 1.4 but aren't in 1.3  -->
+    <javac
+      bootclasspath="${empty}"
+      nowarn="on"
+      debug="${debug}"
+      depend="${depend}"
+      deprecation="${deprecation}"
+      optimize="${optimize}"
+      proceed="${proceed}"
+      verbose="${verbose}"
+      srcdir="${derby.engine.src.dir}"
+      destdir="${out.dir}">
+      <classpath>
+        <pathelement path="${java14compile.classpath}"/>
+      </classpath>
+      <include name="${derby.dir}/iapi/types/XML.java"/>
+    </javac>
     <javac
       bootclasspath="${empty}"
       nowarn="on"
@@ -36,6 +54,7 @@
       <include name="${derby.dir}/iapi/types/*.java"/>
       <exclude name="${derby.dir}/iapi/types/SQLDecimal.java"/>
       <exclude name="${derby.dir}/iapi/types/J2SEDataValueFactory.java"/>
+      <exclude name="${derby.dir}/iapi/types/XML.java"/>
     </javac>
     <javac
       bootclasspath="${empty}"
@@ -53,6 +72,7 @@
       </classpath>
       <include name="${derby.dir}/iapi/types/SQLDecimal.java"/>
       <include name="${derby.dir}/iapi/types/J2SEDataValueFactory.java"/>
+      <exclude name="${derby.dir}/iapi/types/XML.java"/>
     </javac>
   </target>
 

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/Util.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/Util.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/Util.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/Util.java Wed Jun  8 23:48:34 2005
@@ -24,6 +24,7 @@
 import org.apache.derby.iapi.services.i18n.MessageService;
 
 import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
 import org.apache.derby.iapi.types.TypeId;
 
 import org.apache.derby.iapi.error.ExceptionSeverity;
@@ -274,6 +275,7 @@
 
 			case Types.OTHER		:  return "OTHER";
 			case Types.JAVA_OBJECT	:  return "Types.JAVA_OBJECT";
+			case StoredFormatIds.XML_TYPE_ID :  return TypeId.XML_NAME;
 			default : return String.valueOf(jdbcType);
 		}
 	}

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryOperatorNode.java Wed Jun  8 23:48:34 2005
@@ -33,6 +33,7 @@
 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
 import org.apache.derby.iapi.types.StringDataValue;
 import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
 
 import org.apache.derby.iapi.store.access.Qualifier;
 
@@ -42,6 +43,7 @@
 import org.apache.derby.iapi.util.JBitSet;
 import org.apache.derby.iapi.services.classfile.VMOpcode;
 
+import java.sql.Types;
 import java.util.Vector;
 
 /**
@@ -82,6 +84,37 @@
 
 	String		leftInterfaceType;
 	String		rightInterfaceType;
+	String		resultInterfaceType;
+	int			operatorType;
+
+	// At the time of adding XML support, it was decided that
+	// we should avoid creating new OperatorNodes where possible.
+	// So for the XML-related binary operators we just add the
+	// necessary code to _this_ class, similar to what is done in
+	// TernarnyOperatorNode. Subsequent binary operators (whether
+	// XML-related or not) should follow this example when
+	// possible.
+
+	public final static int XMLEXISTS_OP = 0;
+
+	// NOTE: in the following 4 arrays, order
+	// IS important.
+
+	static final String[] BinaryOperators = {
+		"xmlexists",
+	};
+
+	static final String[] BinaryMethodNames = {
+		"XMLExists",
+	};
+
+	static final String[] BinaryResultTypes = {
+		ClassName.BooleanDataValue		// XMLExists
+	};
+
+	static final String[][] BinaryArgTypes = {
+		{ClassName.StringDataValue, ClassName.XMLDataValue}		// XMLExists
+	};
 
 	/**
 	 * Initializer for a BinaryOperatorNode
@@ -109,6 +142,7 @@
 		this.methodName = (String) methodName;
 		this.leftInterfaceType = (String) leftInterfaceType;
 		this.rightInterfaceType = (String) rightInterfaceType;
+		this.operatorType = -1;
 	}
 
 	public void init(
@@ -121,6 +155,30 @@
 		this.rightOperand = (ValueNode) rightOperand;
 		this.leftInterfaceType = (String) leftInterfaceType;
 		this.rightInterfaceType = (String) rightInterfaceType;
+		this.operatorType = -1;
+	}
+
+	/**
+	 * Initializer for a BinaryOperatorNode
+	 *
+	 * @param leftOperand	The left operand of the node
+	 * @param rightOperand	The right operand of the node
+	 * @param opType  An Integer holding the operatorType
+	 *  for this operator.
+	 */
+	public void init(
+			Object leftOperand,
+			Object rightOperand,
+			Object opType)
+	{
+		this.leftOperand = (ValueNode)leftOperand;
+		this.rightOperand = (ValueNode)rightOperand;
+		this.operatorType = ((Integer)opType).intValue();
+		this.operator = BinaryOperators[this.operatorType];
+		this.methodName = BinaryMethodNames[this.operatorType];
+		this.leftInterfaceType = BinaryArgTypes[this.operatorType][0];
+		this.rightInterfaceType = BinaryArgTypes[this.operatorType][1];
+		this.resultInterfaceType = BinaryResultTypes[this.operatorType];
 	}
 
 	/**
@@ -154,6 +212,7 @@
 	void setOperator(String operator)
 	{
 		this.operator = operator;
+		this.operatorType = -1;
 	}
 
 	/**
@@ -166,6 +225,7 @@
 	void setMethodName(String methodName)
 	{
 		this.methodName = methodName;
+		this.operatorType = -1;
 	}
 
 	/**
@@ -179,6 +239,7 @@
 	{
 		leftInterfaceType = iType;
 		rightInterfaceType = iType;
+		this.operatorType = -1;
 	}
 
 	/**
@@ -248,6 +309,8 @@
 		rightOperand = rightOperand.bindExpression(fromList, subqueryList, 
 			aggregateVector);
 
+		if (operatorType == XMLEXISTS_OP)
+			return bindXMLExists();
 
 		/* Is there a ? parameter on the left? */
 		if (leftOperand.isParameterNode())
@@ -275,6 +338,75 @@
 		return genSQLJavaSQLTree();
 	}
 
+    /**
+     * Bind an XMLEXISTS operator.  Makes sure the operand type
+     * and target type are both correct, and sets the result type.
+     *
+     * @exception StandardException Thrown on error
+     */
+    public ValueNode bindXMLExists() throws StandardException
+    {
+        // Check operand types.
+        TypeId leftOperandType = leftOperand.getTypeId();
+        TypeId rightOperandType = rightOperand.getTypeId();
+
+        // Left operand is query expression, and must be a string.
+        if (leftOperandType != null) {
+            switch (leftOperandType.getJDBCTypeId())
+            {
+                case Types.CHAR:
+                case Types.VARCHAR:
+                case Types.LONGVARCHAR:
+                case Types.CLOB:
+                    break;
+                default:
+                {
+                    throw StandardException.newException(
+                        SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, 
+                        methodName,
+                        leftOperandType.getSQLTypeName(),
+                        rightOperandType.getSQLTypeName());
+                }
+            }
+        }
+
+        // Right operand is an XML data value.
+        if ((rightOperandType != null) &&
+            !rightOperandType.isXMLTypeId())
+        {
+            throw StandardException.newException(
+                SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, 
+                    methodName,
+                    leftOperandType.getSQLTypeName(),
+                    rightOperandType.getSQLTypeName());
+        }
+
+        // Is there a ? parameter on the left?
+        if (leftOperand.isParameterNode())
+        {
+            // Set the left operand to be a VARCHAR, which should be
+            // long enough to hold the XPath expression.
+            ((ParameterNode) leftOperand).setDescriptor(
+                DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR));
+        }
+
+        // Is there a ? parameter on the right?
+        if (rightOperand.isParameterNode())
+        {
+            // For now, since JDBC has no type defined for XML, we
+            // don't allow binding to an XML parameter.
+            throw StandardException.newException(
+                SQLState.LANG_ATTEMPT_TO_BIND_XML);
+        }
+
+        // Set the result type of this XMLExists operator--it's always
+        // SQLBoolean.  The "true" in the next line says that the result
+        // can be nullable--which it can be if evaluation of the expression
+        // returns a null (this is per SQL/XML spec section 8.4).
+        setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, true));
+        return genSQLJavaSQLTree();
+    }
+
 	/** generate a SQL->Java->SQL conversion tree above the left and right
 	 * operand of this Binary Operator Node if needed. Subclasses can override
 	 * the default behavior.
@@ -364,7 +496,9 @@
 			** a class, they can note that in the implementation
 			** of the node that uses the method.
 			*/
-		    receiverType = getReceiverInterfaceName();
+		    receiverType = (operatorType == -1)
+				? getReceiverInterfaceName()
+				: leftInterfaceType;
 
 			/*
 			** Generate (with <left expression> only being evaluated once)
@@ -394,7 +528,9 @@
 			** a class, they can note that in the implementation
 			** of the node that uses the method.
 			*/
-		    receiverType = getReceiverInterfaceName();
+		    receiverType = (operatorType == -1)
+				? getReceiverInterfaceName()
+				: rightInterfaceType;
 
 			/*
 			** Generate (with <right expression> only being evaluated once)
@@ -419,7 +555,9 @@
 		}
 
 		/* Figure out the result type name */
-		resultTypeName = getTypeCompiler().interfaceName();
+		resultTypeName = (operatorType == -1)
+			? getTypeCompiler().interfaceName()
+			: resultInterfaceType;
 
 		// Boolean return types don't need a result field
 		boolean needField = !getTypeId().isBooleanTypeId();

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/C_NodeNames.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/C_NodeNames.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/C_NodeNames.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/C_NodeNames.java Wed Jun  8 23:48:34 2005
@@ -56,6 +56,8 @@
 
 	static final String BINARY_ARITHMETIC_OPERATOR_NODE_NAME = "org.apache.derby.impl.sql.compile.BinaryArithmeticOperatorNode";
 
+	static final String BINARY_OPERATOR_NODE_NAME = "org.apache.derby.impl.sql.compile.BinaryOperatorNode";
+
 	static final String BINARY_RELATIONAL_OPERATOR_NODE_NAME = "org.apache.derby.impl.sql.compile.BinaryRelationalOperatorNode";
 
 	static final String BIT_CONSTANT_NODE_NAME = "org.apache.derby.impl.sql.compile.BitConstantNode";
@@ -253,6 +255,8 @@
 	static final String UNARY_DATE_TIMESTAMP_OPERATOR_NODE_NAME
     = "org.apache.derby.impl.sql.compile.UnaryDateTimestampOperatorNode";
 
+	static final String UNARY_OPERATOR_NODE_NAME = "org.apache.derby.impl.sql.compile.UnaryOperatorNode";
+
 	static final String UNION_NODE_NAME = "org.apache.derby.impl.sql.compile.UnionNode";
 
 	static final String INTERSECT_OR_EXCEPT_NODE_NAME = "org.apache.derby.impl.sql.compile.IntersectOrExceptNode";
@@ -271,9 +275,11 @@
 
 	static final String SAVEPOINT_NODE_NAME = "org.apache.derby.impl.sql.compile.SavepointNode";
 
+	static final String XML_CONSTANT_NODE_NAME = "org.apache.derby.impl.sql.compile.XMLConstantNode";
+
 	// The names are in alphabetic order.
 	//
     // WARNING: WHEN ADDING NODE TYPES HERE, YOU MUST ALSO ADD
-    // THEM TO $WS/tools/release/config/dbms/cloudscapenodes.properties
+    // THEM TO tools/jar/DBMSnodes.properties
 
 }

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CharTypeCompiler.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CharTypeCompiler.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CharTypeCompiler.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CharTypeCompiler.java Wed Jun  8 23:48:34 2005
@@ -102,10 +102,10 @@
 				return (getTypeId().isStringTypeId());
 
 			// can't CAST to CHAR and VARCHAR from REAL or DOUBLE
-			// or binary types
+			// or binary types or XML
 			// all other types are ok.
 			if (otherType.isFloatingPointTypeId() || otherType.isBitTypeId() ||
-				otherType.isBlobTypeId())
+				otherType.isBlobTypeId() || otherType.isXMLTypeId())
 				return false;
 						
 			return true;

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DB2LengthOperatorNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DB2LengthOperatorNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DB2LengthOperatorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/DB2LengthOperatorNode.java Wed Jun  8 23:48:34 2005
@@ -82,6 +82,15 @@
 			throws StandardException
 	{
         ValueNode boundExpression = super.bindExpression( fromList, subqueryList, aggregateVector);
+
+        // This operator is not allowed on XML types.
+        TypeId operandType = operand.getTypeId();
+        if (operandType.isXMLTypeId()) {
+            throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
+                                    getOperatorString(),
+                                    operandType.getSQLTypeName());
+        }
+
         setType( new DataTypeDescriptor( TypeId.getBuiltInTypeId( Types.INTEGER),
                                          operand.getTypeServices().isNullable()));
         return boundExpression;

Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NodeFactoryImpl.java Wed Jun  8 23:48:34 2005
@@ -69,7 +69,7 @@
 	/* Do join order optimization by default */
 	private Boolean joinOrderOptimization = Boolean.TRUE;
 
-	private final ClassInfo[]	nodeCi = new ClassInfo[200];
+	private final ClassInfo[]	nodeCi = new ClassInfo[205];
 
 	//////////////////////////////////////////////////////////////////////
 	//
@@ -188,7 +188,7 @@
 		switch (nodeType)
 		{
 		  // WARNING: WHEN ADDING NODE TYPES HERE, YOU MUST ALSO ADD
-		  // THEM TO $WS/tools/release/config/dbms/cloudscapenodes.properties
+		  // THEM TO tools/jar/DBMSnode.properties
 			// xxxRESOLVE: why not make this a giant array and simply index into
 			// it? manish Thu Feb 22 14:49:41 PST 2001  
 		  case C_NodeTypes.CURRENT_ROW_LOCATION_NODE:
@@ -318,6 +318,9 @@
           case C_NodeTypes.CLOB_CONSTANT_NODE:
 			return C_NodeNames.CHAR_CONSTANT_NODE_NAME;
 
+          case C_NodeTypes.XML_CONSTANT_NODE:
+			return C_NodeNames.XML_CONSTANT_NODE_NAME;
+
 		  case C_NodeTypes.COLUMN_REFERENCE:
 		  	return C_NodeNames.COLUMN_REFERENCE_NAME;
 
@@ -564,6 +567,13 @@
 
 		  case C_NodeTypes.DB2_LENGTH_OPERATOR_NODE:
             return C_NodeNames.DB2_LENGTH_OPERATOR_NODE_NAME;
+
+          case C_NodeTypes.XML_PARSE_OPERATOR_NODE:
+          case C_NodeTypes.XML_SERIALIZE_OPERATOR_NODE:
+            return C_NodeNames.UNARY_OPERATOR_NODE_NAME;
+
+          case C_NodeTypes.XML_EXISTS_OPERATOR_NODE:
+            return C_NodeNames.BINARY_OPERATOR_NODE_NAME;
 
 		  // WARNING: WHEN ADDING NODE TYPES HERE, YOU MUST ALSO ADD
 		  // THEM TO tools/jar/DBMSnodes.properties