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 [2/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/
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java Wed Jun 8 23:48:34 2005
@@ -41,6 +41,7 @@
import org.apache.derby.iapi.sql.ParameterValueSet;
import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.reference.ClassName;
+import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
@@ -379,6 +380,18 @@
MethodBuilder mb)
throws StandardException
{
+ DataTypeDescriptor dtd = getTypeServices();
+ if ((dtd != null) && dtd.getTypeId().isXMLTypeId()) {
+ // We're a parameter that corresponds to an XML column/target,
+ // which we don't allow. We throw the error here instead of
+ // in "bindExpression" because at the time of bindExpression,
+ // we don't know yet what the type is going to be (only when
+ // the node that points to this parameter calls
+ // "setDescriptor" do we figure out the type).
+ throw StandardException.newException(
+ SQLState.LANG_ATTEMPT_TO_BIND_XML);
+ }
+
// PUSHCOMPILE
/* Reuse code if possible */
//if (genRetval != null)
@@ -402,7 +415,6 @@
// For some types perform host variable checking
// to match DB2/JCC where if a host variable is too
// big it is not accepted, regardless of any trailing padding.
- DataTypeDescriptor dtd = getTypeServices();
switch (dtd.getJDBCTypeId()) {
case Types.BINARY:
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java Wed Jun 8 23:48:34 2005
@@ -33,6 +33,7 @@
import org.apache.derby.iapi.services.compiler.MethodBuilder;
import org.apache.derby.iapi.services.monitor.Monitor;
import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.sql.compile.CompilerContext;
import org.apache.derby.iapi.sql.compile.NodeFactory;
@@ -976,6 +977,13 @@
case Types.BLOB:
constantNode = nf.getNode(
C_NodeTypes.BLOB_CONSTANT_NODE,
+ typeId,
+ cm);
+ break;
+
+ case StoredFormatIds.XML_TYPE_ID:
+ constantNode = nf.getNode(
+ C_NodeTypes.XML_CONSTANT_NODE,
typeId,
cm);
break;
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ReadCursorNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ReadCursorNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ReadCursorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ReadCursorNode.java Wed Jun 8 23:48:34 2005
@@ -81,6 +81,10 @@
// types for this node
resultSet.bindUntypedNullsToResultColumns(null);
+ // Reject any XML values in the select list; JDBC doesn't
+ // define how we bind these out, so we don't allow it.
+ resultSet.rejectXMLValues();
+
/* Verify that all underlying ResultSets reclaimed their FromList */
if (SanityManager.DEBUG)
{
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java Wed Jun 8 23:48:34 2005
@@ -120,6 +120,10 @@
// Is a count mismatch allowed - see set/get methods for details.
private boolean countMismatchAllowed;
+ // Number of RCs in this RCL at "init" time, before additional
+ // ones were added internally.
+ private int initialListSize = 0;
+
public ResultColumnList()
{
}
@@ -1472,6 +1476,11 @@
{
insertElementAt(allExpansion.elementAt(inner), index + inner);
}
+
+ // If the rc was a "*", we need to set the initial list size
+ // to the number of columns that are actually returned to
+ // the user.
+ markInitialSize();
}
else
{
@@ -1953,6 +1962,71 @@
}
/**
+ * Check for (and reject) XML values directly under the ResultColumns.
+ * This is done for SELECT/VALUES statements. We reject values
+ * in this case because JDBC does not define an XML type/binding
+ * and thus there's no standard way to pass such a type back
+ * to a JDBC application.
+ *
+ * Note that we DO allow an XML column in a top-level RCL
+ * IF that column was added to the RCL by _us_ instead of
+ * by the user. For example, if we have a table:
+ *
+ * create table t1 (i int, x xml)
+ *
+ * and the user query is:
+ *
+ * select i from t1 order by x
+ *
+ * the "x" column will be added (internally) to the RCL
+ * as part of ORDER BY processing--and so we need to
+ * allow that XML column to be bound without throwing
+ * an error. If, as in this case, the XML column reference
+ * is invalid (we can't use ORDER BY on an XML column because
+ * XML values aren't ordered), a more appropriate error
+ * message should be returned to the user in later processing.
+ * If we didn't allow for this, the user would get an
+ * error saying that XML columns are not valid as part
+ * of the result set--but as far as s/he knows, there
+ * isn't such a column: only "i" is supposed to be returned
+ * (the RC for "x" was added to the RCL by _us_ as part of
+ * ORDER BY processing).
+ *
+ * ASSUMPTION: Any RCs that are generated internally and
+ * added to this RCL (before this RCL is bound) are added
+ * at the _end_ of the list. If that's true, then any
+ * RC with an index greater than the size of the initial
+ * (user-specified) list must have been added internally
+ * and will not be returned to the user.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown if an XML value found
+ * directly under a ResultColumn
+ */
+ void rejectXMLValues() throws StandardException
+ {
+ int sz = size();
+ ResultColumn rc = null;
+ for (int i = 1; i <= sz; i++) {
+
+ if (i > initialListSize)
+ // this RC was generated internally and will not
+ // be returned to the user, so don't throw error.
+ continue;
+
+ rc = getResultColumn(i);
+ if ((rc != null) && (rc.getType() != null) &&
+ rc.getType().getTypeId().isXMLTypeId())
+ { // Disallow it.
+ throw StandardException.newException(
+ SQLState.LANG_ATTEMPT_TO_SELECT_XML);
+ }
+
+ }
+ }
+
+ /**
* Set the resultSetNumber in all of the ResultColumns.
*
* @param resultSetNumber The resultSetNumber
@@ -3947,4 +4021,15 @@
{
orderBySelect = src.orderBySelect;
}
+
+ /* ****
+ * Take note of the size of this RCL _before_ we start
+ * processing/binding it. This is so that, at bind time,
+ * we can tell if any columns in the RCL were added
+ * internally by us (i.e. they were not specified by the
+ * user and thus will not be returned to the user).
+ */
+ protected void markInitialSize() {
+ initialListSize = size();
+ }
}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java Wed Jun 8 23:48:34 2005
@@ -991,6 +991,26 @@
}
/**
+ * Check for (and reject) XML values directly under the ResultColumns.
+ * This is done for SELECT/VALUES statements. We reject values
+ * in this case because JDBC does not define an XML type/binding
+ * and thus there's no standard way to pass such a type back
+ * to a JDBC application.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown if an XML value found
+ * directly under a ResultColumn
+ */
+ public void rejectXMLValues() throws StandardException
+ {
+ if (resultColumns != null)
+ {
+ resultColumns.rejectXMLValues();
+ }
+ }
+
+ /**
* Rename generated result column names as '1', '2' etc... These will be the result
* column names seen by JDBC clients.
*/
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java Wed Jun 8 23:48:34 2005
@@ -80,6 +80,8 @@
{
super.init(null, tableProperties);
resultColumns = (ResultColumnList) valuesClause;
+ if (resultColumns != null)
+ resultColumns.markInitialSize();
}
/**
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java Wed Jun 8 23:48:34 2005
@@ -132,6 +132,8 @@
* Consider adding selectAggregates and whereAggregates
*/
resultColumns = (ResultColumnList) selectList;
+ if (resultColumns != null)
+ resultColumns.markInitialSize();
this.fromList = (FromList) fromList;
this.whereClause = (ValueNode) whereClause;
this.originalWhereClause = (ValueNode) whereClause;
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TypeCompilerFactoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TypeCompilerFactoryImpl.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TypeCompilerFactoryImpl.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TypeCompilerFactoryImpl.java Wed Jun 8 23:48:34 2005
@@ -29,6 +29,7 @@
import org.apache.derby.iapi.reference.JDBC20Translation;
import org.apache.derby.iapi.reference.JDBC30Translation;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
import java.util.Properties;
import java.sql.Types;
@@ -65,6 +66,7 @@
static TypeCompiler blobTypeCompiler ;
static TypeCompiler clobTypeCompiler ;
static TypeCompiler nclobTypeCompiler ;
+ static TypeCompiler xmlTypeCompiler ;
/**
* Get a TypeCompiler corresponding to the given TypeId
@@ -256,6 +258,13 @@
btc.setTypeId(typeId);
return btc;
}
+
+ case StoredFormatIds.XML_TYPE_ID:
+ return xmlTypeCompiler =
+ getAnInstance(PACKAGE_NAME + "XMLTypeCompiler",
+ xmlTypeCompiler,
+ typeId);
+
}
if (SanityManager.DEBUG)
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnaryOperatorNode.java Wed Jun 8 23:48:34 2005
@@ -28,10 +28,15 @@
import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.reference.ClassName;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.services.sanity.SanityManager;
import org.apache.derby.iapi.services.compiler.MethodBuilder;
import org.apache.derby.iapi.services.compiler.LocalField;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
+
+import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
import java.lang.reflect.Modifier;
import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
@@ -39,6 +44,7 @@
import org.apache.derby.iapi.util.JBitSet;
import org.apache.derby.iapi.services.classfile.VMOpcode;
+import java.sql.Types;
import java.util.Vector;
/**
@@ -50,10 +56,14 @@
* @author Jeff Lichtman
*/
-public abstract class UnaryOperatorNode extends ValueNode
+public class UnaryOperatorNode extends ValueNode
{
String operator;
String methodName;
+ int operatorType;
+
+ String resultInterfaceType;
+ String receiverInterfaceType;
/**
* WARNING: operand may be NULL for COUNT(*).
@@ -65,22 +75,87 @@
public final static int NOT = 3;
public final static int IS_NULL = 4;
+ // At the time of adding XML support, it was decided that
+ // we should avoid creating new OperatorNodes where possible.
+ // So for the XML-related unary operators we just add the
+ // necessary code to _this_ class, similar to what is done in
+ // TernarnyOperatorNode. Subsequent unary operators (whether
+ // XML-related or not) should follow this example when
+ // possible.
+
+ public final static int XMLPARSE_OP = 0;
+ public final static int XMLSERIALIZE_OP = 1;
+
+ // NOTE: in the following 4 arrays, order
+ // IS important.
+
+ static final String[] UnaryOperators = {
+ "xmlparse",
+ "xmlserialize"
+ };
+
+ static final String[] UnaryMethodNames = {
+ "XMLParse",
+ "XMLSerialize"
+ };
+
+ static final String[] UnaryResultTypes = {
+ ClassName.XMLDataValue, // XMLParse
+ ClassName.StringDataValue // XMLSerialize
+ };
+
+ static final String[] UnaryArgTypes = {
+ ClassName.StringDataValue, // XMLParse
+ ClassName.XMLDataValue // XMLSerialize
+ };
+
+ // Array to hold Objects that contain primitive
+ // args required by the operator method call.
+ private Object [] additionalArgs;
+
/**
* Initializer for a UnaryOperatorNode
*
* @param operand The operand of the node
- * @param operator The name of the operator
- * @param methodName The name of the method to call for this operator
+ * @param operatorOrOpType Either 1) the name of the operator,
+ * OR 2) an Integer holding the operatorType for this operator.
+ * @param methodNameOrParams Either 1) name of the method
+ * to call for this operator, or 2) an array of Objects
+ * from which primitive method parameters can be
+ * retrieved.
*/
public void init(
Object operand,
- Object operator,
- Object methodName)
+ Object operatorOrOpType,
+ Object methodNameOrAddedArgs)
{
this.operand = (ValueNode) operand;
- this.operator = (String) operator;
- this.methodName = (String) methodName;
+ if (operatorOrOpType instanceof String) {
+ // then 2nd and 3rd params are operator and methodName,
+ // respectively.
+ this.operator = (String) operatorOrOpType;
+ this.methodName = (String) methodNameOrAddedArgs;
+ this.operatorType = -1;
+ }
+ else {
+ // 2nd and 3rd params are operatorType and additional args,
+ // respectively.
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(
+ ((operatorOrOpType instanceof Integer) &&
+ ((methodNameOrAddedArgs == null) ||
+ (methodNameOrAddedArgs instanceof Object[]))),
+ "Init params in UnaryOperator node have the " +
+ "wrong type.");
+ }
+ this.operatorType = ((Integer) operatorOrOpType).intValue();
+ this.operator = UnaryOperators[this.operatorType];
+ this.methodName = UnaryMethodNames[this.operatorType];
+ this.resultInterfaceType = UnaryResultTypes[this.operatorType];
+ this.receiverInterfaceType = UnaryArgTypes[this.operatorType];
+ this.additionalArgs = (Object[])methodNameOrAddedArgs;
+ }
}
/**
@@ -91,6 +166,7 @@
public void init(Object operand)
{
this.operand = (ValueNode) operand;
+ this.operatorType = -1;
}
/**
@@ -103,6 +179,7 @@
void setOperator(String operator)
{
this.operator = operator;
+ this.operatorType = -1;
}
/**
@@ -125,6 +202,7 @@
void setMethodName(String methodName)
{
this.methodName = methodName;
+ this.operatorType = -1;
}
/**
@@ -257,9 +335,103 @@
operand = operand.genSQLJavaSQLTree();
}
+ if (operatorType == XMLPARSE_OP)
+ bindXMLParse();
+ else if (operatorType == XMLSERIALIZE_OP)
+ bindXMLSerialize();
+
return this;
}
+ /**
+ * Bind an XMLPARSE operator. Makes sure the operand type
+ * is correct, and sets the result type.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void bindXMLParse() throws StandardException
+ {
+ // Check the type of the operand - this function is allowed only on
+ // string value (char) types.
+ TypeId operandType = operand.getTypeId();
+ if (operandType != null) {
+ switch (operandType.getJDBCTypeId())
+ {
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.CLOB:
+ break;
+ default:
+ {
+ throw StandardException.newException(
+ SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
+ methodName,
+ operandType.getSQLTypeName());
+ }
+ }
+ }
+
+ // The result type of XMLParse() is always an XML type.
+ setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor(
+ StoredFormatIds.XML_TYPE_ID));
+ }
+
+ /**
+ * Bind an XMLSERIALIZE operator. Makes sure the operand type
+ * and target type are both correct, and sets the result type.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void bindXMLSerialize() throws StandardException
+ {
+ TypeId operandType;
+
+ // Check the type of the operand - this function is allowed only on
+ // the XML type.
+ operandType = operand.getTypeId();
+ if ((operandType != null) && !operandType.isXMLTypeId())
+ {
+ throw StandardException.newException(
+ SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
+ methodName,
+ operandType.getSQLTypeName());
+ }
+
+ // Check the target type. We only allow string types to be used as
+ // the target type. The targetType is stored as the first Object
+ // in our list of additional parameters, so we have to retrieve
+ // it from there.
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(
+ ((additionalArgs != null) && (additionalArgs.length > 0)),
+ "Failed to locate target type for XMLSERIALIZE operator");
+ }
+
+ DataTypeDescriptor targetType =
+ (DataTypeDescriptor)additionalArgs[0];
+
+ TypeId targetTypeId = targetType.getTypeId();
+ switch (targetTypeId.getJDBCTypeId())
+ {
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.CLOB:
+ break;
+ default:
+ {
+ throw StandardException.newException(
+ SQLState.LANG_INVALID_XMLSERIALIZE_TYPE,
+ targetTypeId.getSQLTypeName());
+ }
+ }
+
+ // The result type of XMLSerialize() is always a string; which
+ // kind of string is determined by the targetType field.
+ setType(targetType);
+ }
+
/**
* Preprocess an expression tree. We do a number of transformations
* here (including subqueries, IN lists, LIKE and BETWEEN) plus
@@ -376,7 +548,22 @@
void bindParameter() throws StandardException
{
- if (operand.getTypeServices() == null)
+ if (operatorType == XMLPARSE_OP) {
+ // According to the SQL/XML standard, the XMLParse parameter
+ // takes a string operand. RESOLVE: We use CLOB here because
+ // an XML string can be arbitrarily long...is this okay?
+ // The SQL/XML spec doesn't state what the type of the param
+ // should be; only that it "shall be a character type".
+ ((ParameterNode) operand).setDescriptor(
+ DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.CLOB));
+ }
+ else if (operatorType == XMLSERIALIZE_OP) {
+ // 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);
+ }
+ else if (operand.getTypeServices() == null)
{
throw StandardException.newException(SQLState.LANG_UNARY_OPERAND_PARM, operator);
}
@@ -399,7 +586,11 @@
if (operand == null)
return;
- String resultTypeName = getTypeCompiler().interfaceName();
+ String resultTypeName =
+ (operatorType == -1)
+ ? getTypeCompiler().interfaceName()
+ : resultInterfaceType;
+
// System.out.println("resultTypeName " + resultTypeName + " method " + methodName);
// System.out.println("isBooleanTypeId() " + getTypeId().isBooleanTypeId());
@@ -414,7 +605,8 @@
/* Allocate an object for re-use to hold the result of the operator */
LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
mb.getField(field);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, 1);
+ int numParams = 1 + addMethodParams(mb);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, numParams);
/*
** Store the result of the method call in the field, so we can re-use
@@ -422,7 +614,8 @@
*/
mb.putField(field);
} else {
- mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, 0);
+ int numParams = addMethodParams(mb);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, numParams);
}
}
@@ -442,6 +635,9 @@
"cannot get interface without operand");
}
+ if (operatorType != -1)
+ return receiverInterfaceType;
+
return operand.getTypeCompiler().interfaceName();
}
@@ -495,4 +691,35 @@
return returnNode;
}
+
+ /**
+ * This method allows different operators to add
+ * primitive arguments to the generated method call,
+ * if needed.
+ * @param mb The MethodBuilder that will make the call.
+ * @return Number of parameters added.
+ */
+ protected int addMethodParams(MethodBuilder mb)
+ {
+ if (operatorType == XMLPARSE_OP) {
+ // We push whether or not we want to preserve whitespace.
+ mb.push(((Boolean)additionalArgs[0]).booleanValue());
+ return 1;
+ }
+
+ if (operatorType == XMLSERIALIZE_OP) {
+ // We push the target type's JDBC type id as well as
+ // the maximum width, since both are required when
+ // we actually perform the operation, and both are
+ // primitive types.
+ DataTypeDescriptor targetType =
+ (DataTypeDescriptor)additionalArgs[0];
+ mb.push(targetType.getJDBCTypeId());
+ mb.push(targetType.getMaximumWidth());
+ return 2;
+ }
+
+ // Default is to add zero params.
+ return 0;
+ }
}
Added: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLConstantNode.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLConstantNode.java?rev=189721&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLConstantNode.java (added)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLConstantNode.java Wed Jun 8 23:48:34 2005
@@ -0,0 +1,99 @@
+/*
+
+ Derby - Class org.apache.derby.impl.sql.compile.XMLConstantNode
+
+ 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.impl.sql.compile;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.types.TypeId;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+
+import org.apache.derby.iapi.util.ReuseFactory;
+
+public final class XMLConstantNode extends ConstantNode
+{
+ /**
+ * Initializer for an XMLConstantNode.
+ *
+ * @param arg1 The TypeId for the type of the node
+ *
+ * @exception StandardException
+ */
+ public void init(
+ Object arg1)
+ throws StandardException
+ {
+ super.init(
+ arg1,
+ Boolean.TRUE,
+ ReuseFactory.getInteger(0));
+ }
+
+ /**
+ * Return the value from this XMLConstantNode as a string.
+ *
+ * @return The value of this XMLConstantNode as a string.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public String getString() throws StandardException
+ {
+ return value.getString();
+ }
+
+ /**
+ * Return an Object representing the bind time value of this
+ * expression tree. If the expression tree does not evaluate to
+ * a constant at bind time then we return null.
+ *
+ * @return An Object representing the bind time value of this
+ * expression tree (null if not a bind time constant).
+ *
+ * @exception StandardException Thrown on error
+ */
+ Object getConstantValueAsObject() throws StandardException
+ {
+ return value.getObject();
+ }
+
+ /**
+ * This generates the proper constant. For an XML value,
+ * this constant value is simply the XML string (which is
+ * just null because null values are the only types of
+ * XML constants we can have).
+ *
+ * @param acb The ExpressionClassBuilder for the class being built
+ * @param mb The method the code to place the code
+ *
+ * @return The compiled Expression,
+ *
+ * @exception StandardException Thrown on error
+ */
+ void generateConstant(ExpressionClassBuilder acb, MethodBuilder mb)
+ throws StandardException
+ {
+ // The generated java is the expression:
+ // "#getString()"
+ mb.push(getString());
+ }
+}
Propchange: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLConstantNode.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLTypeCompiler.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLTypeCompiler.java?rev=189721&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLTypeCompiler.java (added)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLTypeCompiler.java Wed Jun 8 23:48:34 2005
@@ -0,0 +1,179 @@
+/*
+
+ Derby - Class org.apache.derby.impl.sql.compile.XMLTypeCompiler
+
+ 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.impl.sql.compile;
+
+import org.apache.derby.iapi.services.loader.ClassFactory;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import org.apache.derby.iapi.reference.ClassName;
+
+/**
+ * This class implements TypeCompiler for the XML type.
+ */
+
+public class XMLTypeCompiler extends BaseTypeCompiler
+{
+ /**
+ * Tell whether this type (XML) can be compared to the given type.
+ * Says SQL/XML[2003] spec:
+ *
+ * 4.2.2 XML comparison and assignment
+ * "XML values are not comparable."
+ *
+ * @param otherType The TypeId of the other type.
+ */
+ public boolean comparable(TypeId otherType,
+ boolean forEquals,
+ ClassFactory cs)
+ {
+ // An XML value cannot be compared to any type--
+ // not even to other XML values.
+ return false;
+ }
+
+ /**
+ * Tell whether this type (XML) can be converted to the given type.
+ *
+ * An XML value can't be converted to any other type, per
+ * SQL/XML[2003] 6.3 <cast specification>
+ *
+ * @see TypeCompiler#convertible
+ */
+ public boolean convertible(TypeId otherType,
+ boolean forDataTypeFunction)
+ {
+ // An XML value cannot be converted to any non-XML type. If
+ // user wants to convert an XML value to a string, then
+ // s/he must use the provided SQL/XML serialization operator
+ // (namely, XMLSERIALIZE).
+ return otherType.isXMLTypeId();
+ }
+
+ /**
+ * Tell whether this type (XML) is compatible with the given type.
+ *
+ * @param otherType The TypeId of the other type.
+ */
+ public boolean compatible(TypeId otherType)
+ {
+ // An XML value is not compatible (i.e. cannot be "coalesced")
+ // into any non-XML type.
+ return otherType.isXMLTypeId();
+ }
+
+ /**
+ * Tell whether this type (XML) can be stored into from the given type.
+ * Only XML values can be stored into an XML type, per SQL/XML spec:
+ *
+ * 4.2.2 XML comparison and assignment
+ * Values of XML type are assignable to sites of XML type.
+ *
+ * @param otherType The TypeId of the other type.
+ * @param cf A ClassFactory
+ */
+ public boolean storable(TypeId otherType, ClassFactory cf)
+ {
+ // The only type of value that can be stored as XML
+ // is an XML value. Strings are not allowed. If
+ // the user wants to store a string value as XML,
+ // s/he must use the provided XML parse operator
+ // (namely, XMLPARSE) to parse the string into
+ // XML.
+ return otherType.isXMLTypeId();
+ }
+
+ /**
+ * @see TypeCompiler#interfaceName
+ */
+ public String interfaceName() {
+ return ClassName.XMLDataValue;
+ }
+
+ /**
+ * @see TypeCompiler#getCorrespondingPrimitiveTypeName
+ */
+ public String getCorrespondingPrimitiveTypeName()
+ {
+ int formatId = getStoredFormatIdFromTypeId();
+ if (formatId == StoredFormatIds.XML_TYPE_ID)
+ return "org.apache.derby.iapi.types.XML";
+
+ if (SanityManager.DEBUG) {
+ SanityManager.THROWASSERT(
+ "unexpected formatId in getCorrespondingPrimitiveTypeName(): "
+ + formatId);
+ }
+
+ return null;
+ }
+
+ /**
+ * @see TypeCompiler#getCastToCharWidth
+ *
+ * While it is true XML values can't be cast to char, this method
+ * can get called before we finish type checking--so we return a dummy
+ * value here and let the type check throw the appropriate error.
+ */
+ public int getCastToCharWidth(DataTypeDescriptor dts)
+ {
+ return -1;
+ }
+
+ /**
+ * @see TypeCompiler#nullMethodName
+ */
+ protected String nullMethodName()
+ {
+ int formatId = getStoredFormatIdFromTypeId();
+ if (formatId == StoredFormatIds.XML_TYPE_ID)
+ return "getNullXML";
+
+ if (SanityManager.DEBUG) {
+ SanityManager.THROWASSERT(
+ "unexpected formatId in nullMethodName(): " + formatId);
+ }
+
+ return null;
+ }
+
+ /**
+ * @see TypeCompiler#dataValueMethodName
+ */
+ protected String dataValueMethodName()
+ {
+ int formatId = getStoredFormatIdFromTypeId();
+ if (formatId == StoredFormatIds.XML_TYPE_ID)
+ return "getXMLDataValue";
+
+ if (SanityManager.DEBUG) {
+ SanityManager.THROWASSERT(
+ "unexpected formatId in dataValueMethodName() - " + formatId);
+ }
+
+ return null;
+ }
+}
Propchange: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/XMLTypeCompiler.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Wed Jun 8 23:48:34 2005
@@ -86,6 +86,7 @@
import org.apache.derby.impl.sql.compile.TriggerReferencingStruct;
import org.apache.derby.impl.sql.compile.UnionNode;
import org.apache.derby.impl.sql.compile.IntersectOrExceptNode;
+import org.apache.derby.impl.sql.compile.UnaryOperatorNode;
import org.apache.derby.impl.sql.compile.UntypedNullConstantNode;
import org.apache.derby.impl.sql.compile.UpdateNode;
import org.apache.derby.impl.sql.compile.UserTypeConstantNode;
@@ -141,6 +142,7 @@
import org.apache.derby.catalog.types.RoutineAliasInfo;
import org.apache.derby.iapi.services.io.FormatableProperties;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
import org.apache.derby.iapi.util.ReuseFactory;
import org.apache.derby.iapi.services.io.FormatableBitSet;
import org.apache.derby.iapi.util.StringUtil;
@@ -683,6 +685,7 @@
case CLOB:
case NCLOB:
case BINARY: // LARGE OBJECT
+ case XML:
retval = true;
break;
@@ -1885,6 +1888,9 @@
The next lists should contain non-SQL92 keywords, and should
specify whether their keywords are reserved or non-reserved.
If they are non-reserved, they need to be added to the identifier() rule.
+
+ NOTE: XML, XMLPARSE, XMLSERIALIZE, and XMLEXISTS are considered reserved
+ words to comply with the SQL/XML (2003) standard, section 5.1.
*/
/* NOTE - If you add a keyword, then you must add it to reservedKeyword()
@@ -1904,10 +1910,19 @@
| <LTRIM: "ltrim">
| <RTRIM: "rtrim">
| <SUBSTR: "substr">
+| <XML: "xml">
+| <XMLPARSE: "xmlparse">
+| <XMLSERIALIZE: "xmlserialize">
+| <XMLEXISTS: "xmlexists">
}
/* NOTE - If you add a keyword, then you must add it to reservedKeyword()
* or nonReservedKeyword() as well!
+ *
+ * NOTE: CONTENT, DOCUMENT, STRIP, WHITESPACE and PASSING are considered NON-
+ * reserved words to comply with the SQL/XML (2003) standard, section 5.1.
+ * PRESERVE is also listed as non-reserved in the SQL/XML spec, but
+ * since that word is already reserved, we leave it alone.
*/
TOKEN [IGNORE_CASE] :
{ /* Additional JSQL keywords -- non-SQL92 non-reserved Keywords */
@@ -1915,10 +1930,12 @@
| <BEFORE: "before">
| <CLASS: "class">
| <COMPRESS: "compress">
+| <CONTENT: "content">
| <CS: "cs">
| <CURSORS: "cursors">
| <DB2SQL: "db2sql">
| <DIRTY: "dirty">
+| <DOCUMENT: "document">
| <EACH: "each">
| <EXCLUSIVE: "exclusive">
| <FN: "fn">
@@ -1939,8 +1956,10 @@
| <OLD_TABLE: "old_table">
| <OUT: "out">
| <PARAMETER: "parameter">
+| <PASSING: "passing">
| <PROPERTIES: "properties">
| <READS: "reads">
+| <REF: "ref">
| <REFERENCING: "referencing">
| <RENAME: "rename">
| <RESET: "reset">
@@ -1955,10 +1974,12 @@
| <SPECIFIC: "specific">
| <SQRT: "sqrt">
| <STABILITY: "stability">
+| <STRIP: "strip">
| <STYLE: "style">
| <TRIGGER: "trigger">
| <UCASE: "ucase">
| <UR: "ur">
+| <WHITESPACE: "whitespace">
}
TOKEN :
@@ -3377,6 +3398,8 @@
typeDescriptor = longType()
|
typeDescriptor = LOBType()
+|
+ typeDescriptor = XMLType()
)
{
return typeDescriptor;
@@ -3790,6 +3813,55 @@
}
/*
+ * <A NAME="XMLType">XMLType</A>
+ */
+DataTypeDescriptor
+XMLType() throws StandardException :
+{
+ DataTypeDescriptor value;
+}
+{
+ <XML>
+ {
+ checkVersion(DataDictionary.DD_VERSION_DERBY_10_1, "XML");
+ return DataTypeDescriptor.getBuiltInDataTypeDescriptor(
+ StoredFormatIds.XML_TYPE_ID);
+ }
+}
+
+/*
+ * <A NAME="xmlDocOrContent">xmlDocOrContent</A>
+ *
+ * Parse the XML keywords DOCUMENT and CONTENT. We don't
+ * support CONTENT yet, so we throw an appropriate error
+ * if we see it.
+ *
+ */
+void
+xmlDocOrContent() throws StandardException :
+{
+}
+{
+ LOOKAHEAD({ (getToken(1).kind != DOCUMENT) &&
+ (getToken(1).kind != CONTENT) })
+ {
+ throw StandardException.newException(
+ SQLState.LANG_XML_KEYWORD_MISSING, "DOCUMENT");
+ }
+|
+ LOOKAHEAD({ getToken(1).kind == CONTENT }) <CONTENT>
+ {
+ throw StandardException.newException(
+ SQLState.LANG_UNSUPPORTED_XML_FEATURE, "CONTENT");
+ }
+|
+ LOOKAHEAD({ getToken(1).kind == DOCUMENT }) <DOCUMENT>
+ {
+ return;
+ }
+}
+
+/*
* <A NAME="javaType">javaType</A>
*/
DataTypeDescriptor
@@ -5995,7 +6067,10 @@
getToken(1).kind == MINUTE ||
getToken(1).kind == SECOND ||
getToken(1).kind == LENGTH ||
- getToken(1).kind == LOCATE ) &&
+ getToken(1).kind == LOCATE ||
+ getToken(1).kind == XMLPARSE ||
+ getToken(1).kind == XMLSERIALIZE ||
+ getToken(1).kind == XMLEXISTS ) &&
getToken(2).kind == LEFT_PAREN
)
} )
@@ -6094,6 +6169,11 @@
value,
localCM);
}
+|
+ value = xmlFunction()
+ {
+ return value;
+ }
}
@@ -6144,6 +6224,237 @@
}
}
+/*
+ * <A NAME="xmlFunction">xmlFunction</A>
+ *
+ * This method parses the built-in functions used with
+ * the XML datatype.
+ *
+ */
+ValueNode
+ xmlFunction() throws StandardException :
+{
+ ValueNode value;
+ checkVersion(DataDictionary.DD_VERSION_DERBY_10_1, "XML");
+}
+{
+ <XMLPARSE> <LEFT_PAREN>
+ xmlDocOrContent() value = xmlParseValue() <RIGHT_PAREN>
+ {
+ return value;
+ }
+|
+ <XMLSERIALIZE> <LEFT_PAREN> value = xmlSerializeValue() <RIGHT_PAREN>
+ {
+ return value;
+ }
+|
+ <XMLEXISTS> <LEFT_PAREN> value = xmlExistsValue() <RIGHT_PAREN>
+ {
+ return value;
+ }
+}
+
+/*
+ * <A NAME="xmlParseValue">xmlParseValue</A>
+ *
+ * Syntax is as follows:
+ *
+ * XMLPARSE( DOCUMENT <string-value-expression> PRESERVE WHITESPACE )
+ *
+ * The result of this operation will be an XML value, which can either
+ * be used transiently or else can be stored persistently in a table that
+ * has an XML column. For example:
+ *
+ * ij> CREATE TABLE x_table (id INT, xdoc XML);
+ * 0 rows inserted/updated/deleted
+ * ij> INSERT INTO x_table VALUES (1, XMLPARSE(DOCUMENT '<simp> doc </simp>'
+ * PRESERVE WHITESPACE));
+ * 1 row inserted/updated/deleted
+ *
+ * We only allow XML documents (as opposed to XML content) to be
+ * parsed into XML values. Note that we require the "PRESERVE WHITESPACE"
+ * keyword to be explicit; this is because the SQL/XML (2003) spec says that
+ * if no whitespace option is given, the default is "STRIP WHITESPACE", which
+ * we don't support (yet).
+ *
+ * By the time we get to this method, the "DOCUMENT" keyword has already
+ * been parsed.
+ *
+ */
+ValueNode
+ xmlParseValue() throws StandardException :
+{
+ ValueNode value;
+ boolean wsOption;
+}
+{
+ value = additiveExpression(null,0,false) wsOption = xmlPreserveWhitespace() {
+ return (ValueNode) nodeFactory.getNode(
+ C_NodeTypes.XML_PARSE_OPERATOR_NODE,
+ value,
+ ReuseFactory.getInteger(UnaryOperatorNode.XMLPARSE_OP),
+ new Object[] {(wsOption ? Boolean.TRUE : Boolean.FALSE)},
+ getContextManager());
+ }
+}
+
+/*
+ * <A NAME="xmlPreserveWhitespace">xmlPreserveWhitespace</A>
+ *
+ * For now, we only support the PRESERVE WHITESPACE option.
+ *
+ */
+boolean
+ xmlPreserveWhitespace() throws StandardException :
+{
+}
+{
+ LOOKAHEAD({ (getToken(1).kind != STRIP) &&
+ (getToken(1).kind != PRESERVE) })
+ {
+ throw StandardException.newException(
+ SQLState.LANG_XML_KEYWORD_MISSING, "PRESERVE WHITESPACE");
+ }
+|
+ <STRIP> <WHITESPACE>
+ { // don't preserve whitespace.
+ throw StandardException.newException(
+ SQLState.LANG_UNSUPPORTED_XML_FEATURE, "STRIP WHITESPACE");
+ }
+|
+ <PRESERVE> <WHITESPACE>
+ { // must preserve whitespace.
+ return true;
+ }
+}
+
+/*
+ * <A NAME="xmlSerializeValue">xmlSerializeValue</A>
+ *
+ * Syntax is as follows:
+ *
+ * XMLSERIALIZE( <xml-value-expression> AS <string-data-type> )
+ *
+ * The result of this operation will be a string value with the type specified
+ * by the user. For example:
+ *
+ * ij> SELECT id, XMLSERIALIZE(xdoc AS varchar(30)) FROM x_table;
+ * ID |2
+ * ------------------------------------------
+ * 1 |<simp> doc </simp>
+ *
+ */
+ValueNode
+ xmlSerializeValue() throws StandardException :
+{
+ ValueNode value;
+ DataTypeDescriptor targetType;
+}
+{
+ value = additiveExpression(null,0,false)
+ targetType = xmlSerializeTargetType()
+ {
+ return (ValueNode) nodeFactory.getNode(
+ C_NodeTypes.XML_SERIALIZE_OPERATOR_NODE,
+ value,
+ ReuseFactory.getInteger(UnaryOperatorNode.XMLSERIALIZE_OP),
+ new Object[] {targetType},
+ getContextManager());
+ }
+}
+
+/*
+ * <A NAME="xmlSerializeTargetType">xmlSerializeTargetType</A>
+ *
+ * Parse the target type of an XMLSERIALIZE operation.
+ *
+ */
+DataTypeDescriptor xmlSerializeTargetType() throws StandardException :
+{
+ DataTypeDescriptor targetType;
+}
+{
+ LOOKAHEAD({ (getToken(1).kind != AS) || (getToken(2).kind == RIGHT_PAREN) })
+ {
+ throw StandardException.newException(
+ SQLState.LANG_XML_KEYWORD_MISSING, "AS <string-type>");
+ }
+|
+ <AS> targetType = dataTypeDDL()
+ {
+ return targetType;
+ }
+}
+
+/*
+ * <A NAME="xmlExistsValue">xmlExistsValue</A>
+ *
+ * Syntax is as follows:
+ *
+ * XMLEXISTS( <xpath-expression> PASSING BY VALUE <xml-value-expression> )
+ *
+ * The result of this operation will be a boolean true/false/unknown value:
+ * -- Unknown if either <xpath-expression> or <xml-value-expression> is null;
+ * -- True if at least one node in the given xml-value matches the given
+ * XPath expression;
+ * -- False otherwise.
+ *
+ * For example:
+ *
+ * ij> SELECT id FROM x_table WHERE XMLEXISTS('/simple' PASSING BY VALUE xdoc);
+ * ID
+ * -----------
+ * 1
+ *
+ */
+ValueNode
+ xmlExistsValue() throws StandardException :
+{
+ ValueNode xpathExpr;
+ ValueNode xmlValue;
+}
+{
+ xpathExpr = additiveExpression(null,0,false)
+ xmlPassingMechanism() xmlValue = additiveExpression(null, 0, false)
+ {
+ return (ValueNode) nodeFactory.getNode(
+ C_NodeTypes.XML_EXISTS_OPERATOR_NODE,
+ xpathExpr,
+ xmlValue,
+ ReuseFactory.getInteger(BinaryOperatorNode.XMLEXISTS_OP),
+ getContextManager());
+ }
+}
+
+/*
+ * <A NAME="xmlPassingMechanism">xmlPassingMechanism</A>
+ *
+ * For now, we only support the BY VALUE option because,
+ * at query time, we take the XML string value from disk and
+ * pass it into Xalan, which creates a "copy" of the XML
+ * value internally (as DOM/DTM) and then executes against
+ * that. Because Xalan creates this copy, this impl
+ * is BY VALUE.
+ *
+ */
+void
+ xmlPassingMechanism() throws StandardException :
+{
+}
+{
+ LOOKAHEAD( { getToken(3).kind == REF })
+ <PASSING> <BY> <REF>
+ { // pass the XML value by reference
+ throw StandardException.newException(
+ SQLState.LANG_UNSUPPORTED_XML_FEATURE, "BY REF");
+ }
+|
+ <PASSING> <BY> <VALUE>
+ { // pass a 'copy' of the XML value.
+ return;
+ }
+}
/*
* <A NAME="numericFunctionType">numericFunctionType</A>
@@ -11432,6 +11743,10 @@
| tok = <LTRIM>
| tok = <RTRIM>
| tok = <SUBSTR>
+| tok = <XML>
+| tok = <XMLPARSE>
+| tok = <XMLSERIALIZE>
+| tok = <XMLEXISTS>
)
{
// Remember whether last token was a delimited identifier
@@ -11476,6 +11791,7 @@
| tok = <COMPRESS>
| tok = <CONCAT>
| tok = <CONTAINS>
+ | tok = <CONTENT>
| tok = <CS>
| tok = <CURDATE>
| tok = <CURTIME>
@@ -11487,6 +11803,7 @@
| tok = <DYNAMIC>
| tok = <DATABASE>
| tok = <DB2SQL>
+ | tok = <DOCUMENT>
| tok = <EACH>
| tok = <EXCLUSIVE>
| tok = <FN>
@@ -11533,10 +11850,12 @@
| tok = <OLD_TABLE>
| tok = <OJ>
| tok = <PASCAL>
+ | tok = <PASSING>
| tok = <PLI>
| tok = <PRECISION>
| tok = <PROPERTIES>
| tok = <READS>
+ | tok = <REF>
// SQL92 says it is reserved, but we want it to be non-reserved.
| tok = <RELEASE>
| tok = <RENAME>
@@ -11571,6 +11890,7 @@
| tok = <STABILITY>
| tok = <START>
| tok = <STATEMENT>
+ | tok = <STRIP>
| tok = <SYNONYM>
| tok = <STYLE>
| tok = <T>
@@ -11592,6 +11912,7 @@
| tok = <VARBINARY>
| tok = <PARAMETER>
| tok = <WHEN>
+ | tok = <WHITESPACE>
)
{
// Remember whether last token was a delimited identifier
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties?rev=189721&r1=189720&r2=189721&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties Wed Jun 8 23:48:34 2005
@@ -373,6 +373,7 @@
22025=Escape character must be followed by escape character, '_', or '%'. It cannot be followed by any other character or be at the end of the pattern.
22027=The built-in TRIM() function only supports a single trim character. The LTRIM() and RTRIM() built-in functions support multiple trim characters.
22501=An ESCAPE clause of NULL returns undefined results and is not allowed.
+2200L=XMLPARSE operand is not an XML document; see next exception for details.
23502=Column ''{0}'' cannot accept a NULL value.
23505=The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by ''{0}'' defined on ''{1}''.
23503={2} on table ''{1}'' caused a violation of foreign key constraint ''{0}'' for key {3}. The statement has been rolled back.
@@ -927,6 +928,15 @@
X0X87.S=ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.
X0X95.S=Operation ''{0}'' cannot be performed on object ''{1}'' because there is an open ResultSet dependent on that object.
X0X99.S=Index ''{0}'' does not exist.
+
+# Derby-specific XML errors.
+X0X14.S=Binding directly to an XML value is not allowed; try using XMLPARSE.
+X0X15.S=XML values are not allowed in top-level result sets; try using XMLSERIALIZE.
+X0X16.S=XML syntax error; missing keyword(s): ''{0}''.
+X0X17.S=Invalid target type for XMLSERIALIZE: ''{0}''.
+X0X18.S=XML feature not supported: ''{0}''.
+X0XML.S=Encountered unexpected error while processing XML; see next exception for details.
+
X0Y16.S=''{0}'' is not a view. If it is a table, then use DROP TABLE instead.
X0Y23.S=Operation ''{0}'' cannot be performed on object ''{1}'' because VIEW ''{2}'' is dependent on that object.
X0Y24.S=Operation ''{0}'' cannot be performed on object ''{1}'' because STATEMENT ''{2}'' is dependent on that object.
Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xmlBinding.out
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xmlBinding.out?rev=189721&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xmlBinding.out (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xmlBinding.out Wed Jun 8 23:48:34 2005
@@ -0,0 +1,51 @@
+[ Beginning XML binding tests. ]
+XML column -- bind String to XML: PASS -- caught expected error X0X14.
+XML column -- bind Java null to XML: PASS -- caught expected error X0X14.
+XML column -- bind SQL NULL to XML: PASS -- caught expected error X0X14.
+XML column -- bind integer to XML: PASS -- caught expected error X0X14.
+Trying to bind to XML in XMLSERIALIZE: PASS -- caught expected error X0X14.
+Trying to bind to XML in XMLEXISTS: PASS -- caught expected error X0X14.
+XML value in result set: PASS -- caught expected error X0X15.
+[ End XML binding tests. ]
+[ Beginning XMLPARSE tests. ]
+Test insertions from file:
+Inserted roughly 40k of data.
+Inserted roughly 40k of data.
+Inserted roughly 1k of data.
+Inserted roughly 1k of data.
+Inserted roughly 1k of data.
+Inserted roughly 1k of data.
+-----> Insertions all PASS.
+Binding string in XMLPARSE: PASS -- Completed without exception, as expected.
+Binding Java null string in XMLPARSE: PASS -- Completed without exception, as expected.
+Binding SQL NULL string in XMLPARSE: PASS -- Completed without exception, as expected.
+[ End XMLPARSE tests. ]
+[ Beginning XMLSERIALIZE tests. ]
+1, [ roughly 40k ]
+2, [ roughly 40k ]
+3, [ roughly 1k ]
+4, [ roughly 1k ]
+5, [ roughly 1k ]
+6, [ roughly 1k ]
+7, [ roughly 0k ]
+8, NULL
+9, NULL
+[ End XMLSERIALIZE tests. ]
+[ Begin XMLEXISTS tests. ]
+Running XMLEXISTS with: //abb
+-----> Matching rows: 1
+Running XMLEXISTS with: //d50
+-----> Matching rows: 1
+Running XMLEXISTS with: //person/email
+-----> Matching rows: 4
+Running XMLEXISTS with: /personnel
+-----> Matching rows: 5
+Running XMLEXISTS with: //person/@id
+-----> Matching rows: 4
+Running XMLEXISTS with: //person/@noteTwo
+-----> Matching rows: 1
+Binding string in XMLEXISTS: PASS -- Completed without exception, as expected.
+Binding Java null string in XMLEXISTS: PASS -- Completed without exception, as expected.
+Binding SQL NULL string in XMLEXISTS: PASS -- Completed without exception, as expected.
+[ End XMLEXISTS tests. ]
+[ Done. ]
Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xmlBinding.out
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out?rev=189721&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out Wed Jun 8 23:48:34 2005
@@ -0,0 +1,582 @@
+ij> create table t0 (si smallint, i int, bi bigint, vcb varchar (32) for bit data, nu numeric(10,2), f float, d double, vc varchar(20), da date, ti time, ts timestamp, cl clob, bl blob);
+0 rows inserted/updated/deleted
+ij> -- XML column declarations should work like other built-in types.
+create table t1 (i int, x xml);
+0 rows inserted/updated/deleted
+ij> create table t2 (i int, x xml not null);
+0 rows inserted/updated/deleted
+ij> create table t3 (i int, x xml default null);
+0 rows inserted/updated/deleted
+ij> create table t4 (vc varchar(100));
+0 rows inserted/updated/deleted
+ij> create table t5 (x2 xml not null);
+0 rows inserted/updated/deleted
+ij> alter table t5 add column x1 xml;
+0 rows inserted/updated/deleted
+ij> -- Check insertion of null XML values.
+----- Next four should work.
+insert into t1 values (1, null);
+1 row inserted/updated/deleted
+ij> insert into t1 values (2, cast (null as xml));
+1 row inserted/updated/deleted
+ij> insert into t1 (i) values (4);
+1 row inserted/updated/deleted
+ij> insert into t1 values (3, default);
+1 row inserted/updated/deleted
+ij> -- Next two should fail.
+insert into t2 values (1, null);
+ERROR 23502: Column 'X' cannot accept a NULL value.
+ij> insert into t2 values (2, cast (null as xml));
+ERROR 23502: Column 'X' cannot accept a NULL value.
+ij> -- XML cols can't hold non-XML types.
+insert into t1 values (3, 'hmm');
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'CHAR'.
+ij> insert into t1 values (1, 2);
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'INTEGER'.
+ij> insert into t1 values (1, 123.456);
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'DECIMAL'.
+ij> insert into t1 values (1, x'01');
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'CHAR () FOR BIT DATA'.
+ij> insert into t1 values (1, x'ab');
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'CHAR () FOR BIT DATA'.
+ij> insert into t1 values (1, current date);
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'DATE'.
+ij> insert into t1 values (1, current time);
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'TIME'.
+ij> insert into t1 values (1, current timestamp);
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'TIMESTAMP'.
+ij> insert into t1 values (1, ('hmm' | | 'andstuff'));
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'CHAR'.
+ij> -- XML can't be stored in non-XML cols.
+insert into t0 (si) values (cast (null as xml));
+ERROR 42821: Columns of type 'SMALLINT' cannot hold values of type 'XML'.
+ij> insert into t0 (i) values (cast (null as xml));
+ERROR 42821: Columns of type 'INTEGER' cannot hold values of type 'XML'.
+ij> insert into t0 (bi) values (cast (null as xml));
+ERROR 42821: Columns of type 'BIGINT' cannot hold values of type 'XML'.
+ij> insert into t0 (vcb) values (cast (null as xml));
+ERROR 42821: Columns of type 'VARCHAR () FOR BIT DATA' cannot hold values of type 'XML'.
+ij> insert into t0 (nu) values (cast (null as xml));
+ERROR 42821: Columns of type 'NUMERIC' cannot hold values of type 'XML'.
+ij> insert into t0 (f) values (cast (null as xml));
+ERROR 42821: Columns of type 'DOUBLE' cannot hold values of type 'XML'.
+ij> insert into t0 (d) values (cast (null as xml));
+ERROR 42821: Columns of type 'DOUBLE' cannot hold values of type 'XML'.
+ij> insert into t0 (vc) values (cast (null as xml));
+ERROR 42821: Columns of type 'VARCHAR' cannot hold values of type 'XML'.
+ij> insert into t0 (da) values (cast (null as xml));
+ERROR 42821: Columns of type 'DATE' cannot hold values of type 'XML'.
+ij> insert into t0 (ti) values (cast (null as xml));
+ERROR 42821: Columns of type 'TIME' cannot hold values of type 'XML'.
+ij> insert into t0 (ts) values (cast (null as xml));
+ERROR 42821: Columns of type 'TIMESTAMP' cannot hold values of type 'XML'.
+ij> insert into t0 (cl) values (cast (null as xml));
+ERROR 42821: Columns of type 'CLOB' cannot hold values of type 'XML'.
+ij> insert into t0 (bl) values (cast (null as xml));
+ERROR 42821: Columns of type 'BLOB' cannot hold values of type 'XML'.
+ij> -- No casting is allowed.
+insert into t1 values (1, cast ('hmm' as xml));
+ERROR 42846: Cannot convert types 'CHAR' to 'XML'.
+ij> insert into t1 values (1, cast (2 as xml));
+ERROR 42846: Cannot convert types 'INTEGER' to 'XML'.
+ij> insert into t1 values (1, cast (123.456 as xml));
+ERROR 42846: Cannot convert types 'DECIMAL' to 'XML'.
+ij> insert into t1 values (1, cast (x'01' as xml));
+ERROR 42846: Cannot convert types 'CHAR () FOR BIT DATA' to 'XML'.
+ij> insert into t1 values (1, cast (x'ab' as xml));
+ERROR 42846: Cannot convert types 'CHAR () FOR BIT DATA' to 'XML'.
+ij> insert into t1 values (1, cast (current date as xml));
+ERROR 42846: Cannot convert types 'DATE' to 'XML'.
+ij> insert into t1 values (1, cast (current time as xml));
+ERROR 42846: Cannot convert types 'TIME' to 'XML'.
+ij> insert into t1 values (1, cast (current timestamp as xml));
+ERROR 42846: Cannot convert types 'TIMESTAMP' to 'XML'.
+ij> insert into t1 values (1, cast (('hmm' | | 'andstuff') as xml));
+ERROR 42846: Cannot convert types 'CHAR' to 'XML'.
+ij> -- XML can't be used in non-XML operations.
+select i + x from t1;
+ERROR 42Y95: The '+' operator with a left operand type of 'INTEGER' and a right operand type of 'XML' is not supported.
+ij> select i * x from t1;
+ERROR 42Y95: The '*' operator with a left operand type of 'INTEGER' and a right operand type of 'XML' is not supported.
+ij> select i / x from t1;
+ERROR 42Y95: The '/' operator with a left operand type of 'INTEGER' and a right operand type of 'XML' is not supported.
+ij> select i - x from t1;
+ERROR 42Y95: The '-' operator with a left operand type of 'INTEGER' and a right operand type of 'XML' is not supported.
+ij> select -x from t1;
+ERROR 42X37: The unary '-' operator is not allowed on the 'XML' type.
+ij> select 'hi' | | x from t1;
+ERROR 42846: Cannot convert types 'XML' to 'VARCHAR'.
+ij> select substr(x, 0) from t1;
+ERROR 42X25: The 'SUBSTR' function is not allowed on the 'XML' type.
+ij> select i from t1 where x like 'hmm';
+ERROR 42884: No authorized routine named 'LIKE' of type 'FUNCTION' having compatible arguments was found.
+ij> select max(x) from t1;
+ERROR 42Y22: Aggregate MAX cannot operate on type XML.
+ij> select min(x) from t1;
+ERROR 42Y22: Aggregate MIN cannot operate on type XML.
+ij> select length(x) from t1;
+ERROR 42X25: The 'length' function is not allowed on the 'XML' type.
+ij> -- Comparsions against XML don't work.
+select i from t1 where x = 'hmm';
+ERROR 42818: Comparisons between 'XML' and 'CHAR' are not supported.
+ij> select i from t1 where x > 0;
+ERROR 42818: Comparisons between 'XML' and 'INTEGER' are not supported.
+ij> select i from t1 where x > x;
+ERROR 42818: Comparisons between 'XML' and 'XML' are not supported.
+ij> select i from t1 where x > 'some char';
+ERROR 42818: Comparisons between 'XML' and 'CHAR' are not supported.
+ij> -- Indexing/ordering on XML cols is not allowed.
+create index oops_ix on t1(x);
+ERROR X0X67: Columns of type 'XML' may not be used in CREATE INDEX, ORDER BY, GROUP BY, UNION, INTERSECT, EXCEPT or DISTINCT statements because comparisons are not supported for that type.
+ij> select i from t1 where x is null order by x;
+ERROR X0X67: Columns of type 'XML' may not be used in CREATE INDEX, ORDER BY, GROUP BY, UNION, INTERSECT, EXCEPT or DISTINCT statements because comparisons are not supported for that type.
+ij> -- XML cols can be used in a SET clause, if target value is XML.
+create trigger tr2 after insert on t1 for each row mode db2sql update t1 set x = 'hmm';
+ERROR 42821: Columns of type 'XML' cannot hold values of type 'CHAR'.
+ij> create trigger tr1 after insert on t1 for each row mode db2sql update t1 set x = null;
+0 rows inserted/updated/deleted
+ij> drop trigger tr1;
+0 rows inserted/updated/deleted
+ij> -- Test XMLPARSE operator.
+----- These should fail.
+insert into t1 values (1, xmlparse(document '<hmm/>' strip whitespace));
+ERROR X0X18: XML feature not supported: 'STRIP WHITESPACE'.
+ij> insert into t1 values (1, xmlparse(document '<hmm/>'));
+ERROR X0X16: XML syntax error; missing keyword(s): 'PRESERVE WHITESPACE'.
+ij> insert into t1 values (1, xmlparse('<hmm/>' preserve whitespace));
+ERROR X0X16: XML syntax error; missing keyword(s): 'DOCUMENT'.
+ij> insert into t1 values (1, xmlparse(content '<hmm/>' preserve whitespace));
+ERROR X0X18: XML feature not supported: 'CONTENT'.
+ij> select xmlparse(document xmlparse(document '<hein/>' preserve whitespace) preserve whitespace) from t1;
+ERROR 42X25: The 'XMLParse' function is not allowed on the 'XML' type.
+ij> select i from t1 where xmlparse(document '<hein/>' preserve whitespace);
+ERROR 42X19: The WHERE or HAVING clause or CHECK CONSTRAINT definition is a 'XML' expression. It must be a BOOLEAN expression.
+ij> insert into t1 values (1, xmlparse(document '<oops>' preserve whitespace));
+ERROR 2200L: XMLPARSE operand is not an XML document; see next exception for details. SQLSTATE: XJ001: Java exception: 'XML document structures must start and end within the same entity.: org.xml.sax.SAXParseException'.
+ij> -- These should work.
+insert into t1 values (5, xmlparse(document '<hmm/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t1 values (6, xmlparse(document '<half> <masted> bass </masted> boosted. </half>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t2 values (1, xmlparse(document '<should> work as planned </should>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t5 (x1, x2) values (null, xmlparse(document '<notnull/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> update t1 set x = xmlparse(document '<update> document was inserted as part of an UPDATE </update>' preserve whitespace) where i = 1;
+1 row inserted/updated/deleted
+ij> update t1 set x = xmlparse(document '<update2> document was inserted as part of an UPDATE </update2>' preserve whitespace) where xmlexists('/update' passing by value x);
+1 row inserted/updated/deleted
+ij> select i from t1 where xmlparse(document '<hein/>' preserve whitespace) is not null;
+I
+-----
+1
+2
+4
+3
+5
+6
+ij> select i from t1 where xmlparse(document '<hein/>' preserve whitespace) is not null order by i;
+I
+-----
+1
+2
+3
+4
+5
+6
+ij> -- "is [not] null" should work with XML.
+select i from t1 where x is not null;
+I
+-----
+1
+5
+6
+ij> select i from t1 where x is null;
+I
+-----
+2
+4
+3
+ij> -- XML columns can't be returned in a top-level result set.
+select x from t1;
+ERROR X0X15: XML values are not allowed in top-level result sets; try using XMLSERIALIZE.
+ij> select * from t1;
+ERROR X0X15: XML values are not allowed in top-level result sets; try using XMLSERIALIZE.
+ij> select xmlparse(document vc preserve whitespace) from t4;
+ERROR X0X15: XML values are not allowed in top-level result sets; try using XMLSERIALIZE.
+ij> values xmlparse(document '<bye/>' preserve whitespace);
+ERROR X0X15: XML values are not allowed in top-level result sets; try using XMLSERIALIZE.
+ij> values xmlparse(document '<hel' | | 'lo/>' preserve whitespace);
+ERROR X0X15: XML values are not allowed in top-level result sets; try using XMLSERIALIZE.
+ij> -- Test XMLSERIALIZE operator.
+insert into t4 values ('<hmm/>');
+1 row inserted/updated/deleted
+ij> insert into t4 values 'no good';
+1 row inserted/updated/deleted
+ij> -- These should fail.
+select xmlserialize(x) from t1;
+ERROR X0X16: XML syntax error; missing keyword(s): 'AS <string-type>'.
+ij> select xmlserialize(x as) from t1;
+ERROR X0X16: XML syntax error; missing keyword(s): 'AS <string-type>'.
+ij> select xmlserialize(x as int) from t1;
+ERROR X0X17: Invalid target type for XMLSERIALIZE: 'INTEGER'.
+ij> select xmlserialize(x as varchar(20) for bit data) from t1;
+ERROR X0X17: Invalid target type for XMLSERIALIZE: 'VARCHAR () FOR BIT DATA'.
+ij> select xmlserialize(y as char(10)) from t1;
+ERROR 42X04: Column 'Y' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'Y' is not a column in the target table.
+ij> select xmlserialize(xmlserialize(x as clob) as clob) from t1;
+ERROR 42X25: The 'XMLSerialize' function is not allowed on the 'CLOB' type.
+ij> values xmlserialize('<okay> dokie </okay>' as clob);
+ERROR 42X25: The 'XMLSerialize' function is not allowed on the 'CHAR' type.
+ij> -- These should succeed.
+select xmlserialize(x as clob) from t1;
+1
+-----
+<update2> document was inserted as part of an UPDATE </update2>
+NULL
+NULL
+NULL
+<hmm/>
+<half> <masted> bass </masted> boosted. </half>
+ij> select xmlserialize(x1 as clob), xmlserialize(x2 as clob) from t5;
+1 |2
+-----
+NULL |<notnull/>
+ij> select xmlserialize(x as char(100)) from t1;
+1
+-----
+<update2> document was inserted as part of an UPDATE </update2>
+NULL
+NULL
+NULL
+<hmm/>
+<half> <masted> bass </masted> boosted. </half>
+ij> select xmlserialize(x as varchar(300)) from t1;
+1
+-----
+<update2> document was inserted as part of an UPDATE </update2>
+NULL
+NULL
+NULL
+<hmm/>
+<half> <masted> bass </masted> boosted. </half>
+ij> -- These should succeed at the XMLEXISTS level, but fail with
+----- parse/truncation errors.
+select xmlserialize(xmlparse(document vc preserve whitespace) as char(10)) from t4;
+1
+-----
+ERROR 2200L: XMLPARSE operand is not an XML document; see next exception for details. SQLSTATE: XJ001: Java exception: 'Content is not allowed in prolog.: org.xml.sax.SAXParseException'.
+ij> select xmlserialize(x as char) from t1;
+1
+-----
+ERROR 22001: A truncation error was encountered trying to shrink CHAR '<update2> document was inserted as part of an UPDATE </updat&' to length 1.
+ij> select xmlserialize(x as clob(10)) from t1;
+1
+-----
+ERROR 22001: A truncation error was encountered trying to shrink CLOB '<update2> document was inserted as part of an UPDATE </updat&' to length 10.
+ij> select xmlserialize(x as char(1)) from t1;
+1
+-----
+ERROR 22001: A truncation error was encountered trying to shrink CHAR '<update2> document was inserted as part of an UPDATE </updat&' to length 1.
+ij> select length(xmlserialize(x as char(1))) from t1;
+1
+-----
+ERROR 22001: A truncation error was encountered trying to shrink CHAR '<update2> document was inserted as part of an UPDATE </updat&' to length 1.
+ij> select xmlserialize(x as varchar(1)) from t1;
+1
+-----
+ERROR 22001: A truncation error was encountered trying to shrink VARCHAR '<update2> document was inserted as part of an UPDATE </updat&' to length 1.
+ij> select length(xmlserialize(x as varchar(1))) from t1;
+1
+-----
+ERROR 22001: A truncation error was encountered trying to shrink VARCHAR '<update2> document was inserted as part of an UPDATE </updat&' to length 1.
+ij> -- These checks verify that the XMLSERIALIZE result is the correct
+----- type (the type is indicated as part of the error message).
+create table it (i int);
+0 rows inserted/updated/deleted
+ij> insert into it values (select xmlserialize(x as varchar(10)) from t1);
+ERROR 42821: Columns of type 'INTEGER' cannot hold values of type 'VARCHAR'.
+ij> insert into it values (select xmlserialize(x as char(10)) from t1);
+ERROR 42821: Columns of type 'INTEGER' cannot hold values of type 'CHAR'.
+ij> insert into it values (select xmlserialize(x as clob(10)) from t1);
+ERROR 42821: Columns of type 'INTEGER' cannot hold values of type 'CLOB'.
+ij> -- Test XMLPARSE/XMLSERIALIZE combinations.
+----- These should fail.
+select xmlserialize(xmlparse(document '<hmm>' preserve whitespace) as clob) from t2;
+1
+-----
+ERROR 2200L: XMLPARSE operand is not an XML document; see next exception for details. SQLSTATE: XJ001: Java exception: 'XML document structures must start and end within the same entity.: org.xml.sax.SAXParseException'.
+ij> select xmlserialize(xmlparse(document x preserve whitespace) as char(100)) from t1;
+ERROR 42X25: The 'XMLParse' function is not allowed on the 'XML' type.
+ij> -- These should succeed.
+select xmlserialize(xmlparse(document '<hmm/>' preserve whitespace) as clob) from t2;
+1
+-----
+<hmm/>
+ij> select xmlserialize(xmlparse(document xmlserialize(x as clob) preserve whitespace) as clob) from t1;
+1
+-----
+<update2> document was inserted as part of an UPDATE </update2>
+NULL
+NULL
+NULL
+<hmm/>
+<half> <masted> bass </masted> boosted. </half>
+ij> values xmlserialize(xmlparse(document '<okay> dokie </okay>' preserve whitespace) as clob);
+1
+-----
+<okay> dokie </okay>
+ij> select i from t1 where xmlparse(document xmlserialize(x as clob) preserve whitespace) is not null order by i;
+I
+-----
+1
+5
+6
+ij> -- Test XMLEXISTS operator.
+insert into t1 values (7, xmlparse(document '<lets> <try> this out </try> </lets>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> create table t7 (i int, x1 xml, x2 xml not null);
+0 rows inserted/updated/deleted
+ij> insert into t7 values (1, null, xmlparse(document '<ok/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> -- These should fail.
+select i from t1 where xmlexists(x);
+ERROR 42X01: Syntax error: Encountered ")" at line 1, column 35.
+ij> select i from t1 where xmlexists(i);
+ERROR 42X01: Syntax error: Encountered ")" at line 1, column 35.
+ij> select i from t1 where xmlexists('//*');
+ERROR 42X01: Syntax error: Encountered ")" at line 1, column 39.
+ij> select i from t1 where xmlexists('//*' x);
+ERROR 42X01: Syntax error: Encountered "x" at line 1, column 40.
+ij> select i from t1 where xmlexists('//*' passing x);
+ERROR 42X01: Syntax error: Encountered "x" at line 1, column 48.
+ij> select i from t1 where xmlexists('//*' passing by ref x);
+ERROR X0X18: XML feature not supported: 'BY REF'.
+ij> select i from t1 where xmlexists('//*' passing by value i);
+ERROR 42Y95: The 'XMLExists' operator with a left operand type of 'CHAR' and a right operand type of 'INTEGER' is not supported.
+ij> -- These should succeed.
+select i from t1 where xmlexists('//*' passing by value x);
+I
+-----
+1
+5
+6
+7
+ij> select i from t1 where xmlexists('//person' passing by value x);
+I
+-----
+ij> select i from t1 where xmlexists('//lets' passing by value x);
+I
+-----
+7
+ij> select xmlexists('//lets' passing by value x) from t1;
+1
+-----
+0
+NULL
+NULL
+NULL
+0
+0
+1
+ij> select xmlexists('//try[text()='' this out '']' passing by value x) from t1;
+1
+-----
+0
+NULL
+NULL
+NULL
+0
+0
+1
+ij> select xmlexists('//let' passing by value x) from t1;
+1
+-----
+0
+NULL
+NULL
+NULL
+0
+0
+0
+ij> select xmlexists('//try[text()='' this in '']' passing by value x) from t1;
+1
+-----
+0
+NULL
+NULL
+NULL
+0
+0
+0
+ij> select i, xmlexists('//let' passing by value x) from t1;
+I |2
+-----
+1 |0
+2 |NULL
+4 |NULL
+3 |NULL
+5 |0
+6 |0
+7 |0
+ij> select i, xmlexists('//lets' passing by value x) from t1;
+I |2
+-----
+1 |0
+2 |NULL
+4 |NULL
+3 |NULL
+5 |0
+6 |0
+7 |1
+ij> values xmlexists('//let' passing by value xmlparse(document '<lets> try this </lets>' preserve whitespace));
+1
+-----
+0
+ij> values xmlexists('//lets' passing by value xmlparse(document '<lets> try this </lets>' preserve whitespace));
+1
+-----
+1
+ij> select xmlserialize(x1 as clob) from t5 where xmlexists('//*' passing by value x1);
+1
+-----
+ij> select xmlserialize(x2 as clob) from t5 where xmlexists('//*' passing by value x2);
+1
+-----
+<notnull/>
+ij> select xmlserialize(x1 as clob), xmlexists('//*' passing by value xmlparse(document '<badboy/>' preserve whitespace)) from t5;
+1 |2
+-----
+NULL |1
+ij> select xmlserialize(x1 as clob), xmlexists('//goodboy' passing by value xmlparse(document '<badboy/>' preserve whitespace)) from t5;
+1 |2
+-----
+NULL |0
+ij> select i, xmlserialize(x1 as char(10)), xmlserialize (x2 as char(10)) from t7;
+I |2 |3
+-----
+1 |NULL |<ok/>
+ij> select i from t7 where xmlexists('/ok' passing by value x1) and xmlexists('/ok' passing by value x2);
+I
+-----
+ij> select i from t7 where xmlexists('/ok' passing by value x1) or xmlexists('/ok' passing by value x2);
+I
+-----
+1
+ij> -- XMLEXISTS can be used wherever a boolean function is allowed,
+----- for ex, a check constraint...
+create table t6 (i int, x xml check (xmlexists('//should' passing by value x)));
+0 rows inserted/updated/deleted
+ij> insert into t6 values (1, xmlparse(document '<should/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t6 values (1, xmlparse(document '<shouldnt/>' preserve whitespace));
+ERROR 23513: The check constraint 'xxxxGENERATED-IDxxxx' was violated while performing an INSERT or UPDATE on table 'APP.T6'.
+ij> select xmlserialize(x as char(20)) from t6;
+1
+-----
+<should/>
+ij> -- Do some namespace queries/examples.
+create table t8 (i int, x xml);
+0 rows inserted/updated/deleted
+ij> insert into t8 values (1, xmlparse(document '<a:hi xmlns:a="http://www.hi.there"/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t8 values (2, xmlparse(document '<b:hi xmlns:b="http://www.hi.there"/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t8 values (3, xmlparse(document '<a:bye xmlns:a="http://www.good.bye"/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t8 values (4, xmlparse(document '<b:bye xmlns:b="http://www.hi.there"/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> insert into t8 values (5, xmlparse(document '<hi/>' preserve whitespace));
+1 row inserted/updated/deleted
+ij> select xmlexists('//child::*[name()="none"]' passing by value x) from t8;
+1
+-----
+0
+0
+0
+0
+0
+ij> select xmlexists('//child::*[name()=''hi'']' passing by value x) from t8;
+1
+-----
+0
+0
+0
+0
+1
+ij> select xmlexists('//child::*[local-name()=''hi'']' passing by value x) from t8;
+1
+-----
+1
+1
+0
+0
+1
+ij> select xmlexists('//child::*[local-name()=''bye'']' passing by value x) from t8;
+1
+-----
+0
+0
+1
+1
+0
+ij> select xmlexists('//*[namespace::*[string()=''http://www.hi.there'']]' passing by value x) from t8;
+1
+-----
+1
+1
+0
+1
+0
+ij> select xmlexists('//*[namespace::*[string()=''http://www.good.bye'']]' passing by value x) from t8;
+1
+-----
+0
+0
+1
+0
+0
+ij> select xmlexists('//child::*[local-name()=''hi'' and namespace::*[string()=''http://www.hi.there'']]' passing by value x) from t8;
+1
+-----
+1
+1
+0
+0
+0
+ij> select xmlexists('//child::*[local-name()=''bye'' and namespace::*[string()=''http://www.good.bye'']]' passing by value x) from t8;
+1
+-----
+0
+0
+1
+0
+0
+ij> select xmlexists('//child::*[local-name()=''bye'' and namespace::*[string()=''http://www.hi.there'']]' passing by value x) from t8;
+1
+-----
+0
+0
+0
+1
+0
+ij> -- clean up.
+drop table t0;
+0 rows inserted/updated/deleted
+ij> drop table t1;
+0 rows inserted/updated/deleted
+ij> drop table t2;
+0 rows inserted/updated/deleted
+ij> drop table t3;
+0 rows inserted/updated/deleted
+ij> drop table t4;
+0 rows inserted/updated/deleted
+ij> drop table t5;
+0 rows inserted/updated/deleted
+ij> drop table t6;
+0 rows inserted/updated/deleted
+ij> drop table t7;
+0 rows inserted/updated/deleted
+ij> drop table t8;
+0 rows inserted/updated/deleted
+ij>
Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/xml_general.out
------------------------------------------------------------------------------
svn:eol-style = native