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