From derby-commits-return-974-apmail-db-derby-commits-archive=db.apache.org@db.apache.org Thu Jun 09 06:49:10 2005 Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 46695 invoked from network); 9 Jun 2005 06:49:09 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 9 Jun 2005 06:49:09 -0000 Received: (qmail 42208 invoked by uid 500); 9 Jun 2005 06:49:09 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 42176 invoked by uid 500); 9 Jun 2005 06:49:08 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 42162 invoked by uid 500); 9 Jun 2005 06:49:08 -0000 Delivered-To: apmail-incubator-derby-cvs@incubator.apache.org Received: (qmail 42159 invoked by uid 99); 9 Jun 2005 06:49:08 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Wed, 08 Jun 2005 23:49:01 -0700 Received: (qmail 46493 invoked by uid 65534); 9 Jun 2005 06:48:45 -0000 Message-ID: <20050609064845.46490.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: 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/ Date: Thu, 09 Jun 2005 06:48:36 -0000 To: derby-cvs@incubator.apache.org From: bandaram@apache.org X-Mailer: svnmailer-1.0.0-dev X-Virus-Checked: Checked X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N 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/o= rg/apache/derby/impl/sql/compile/ParameterNode.java?rev=3D189721&r1=3D18972= 0&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/ParameterNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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; =20 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; =20 @@ -379,6 +380,18 @@ MethodBuilder mb) throws StandardException { + DataTypeDescriptor dtd =3D getTypeServices(); + if ((dtd !=3D 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 !=3D 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 =3D getTypeServices(); =20 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/o= rg/apache/derby/impl/sql/compile/QueryTreeNode.java?rev=3D189721&r1=3D18972= 0&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/QueryTreeNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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 =3D nf.getNode( C_NodeTypes.BLOB_CONSTANT_NODE, + typeId, + cm); + break; + + case StoredFormatIds.XML_TYPE_ID: + constantNode =3D 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/o= rg/apache/derby/impl/sql/compile/ReadCursorNode.java?rev=3D189721&r1=3D1897= 20&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/ReadCursorNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/ReadCursorNode.java Wed Jun 8 23:48:34 2005 @@ -81,6 +81,10 @@ // types for this node resultSet.bindUntypedNullsToResultColumns(null); =20 + // 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/o= rg/apache/derby/impl/sql/compile/ResultColumnList.java?rev=3D189721&r1=3D18= 9720&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/ResultColumnList.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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; =20 + // Number of RCs in this RCL at "init" time, before additional + // ones were added internally. + private int initialListSize =3D 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 @@ } =20 /** + * 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 =3D size(); + ResultColumn rc =3D null; + for (int i =3D 1; i <=3D 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 =3D getResultColumn(i); + if ((rc !=3D null) && (rc.getType() !=3D 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 =3D 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 =3D 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/o= rg/apache/derby/impl/sql/compile/ResultSetNode.java?rev=3D189721&r1=3D18972= 0&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/ResultSetNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/ResultSetNode.java Wed Jun 8 23:48:34 2005 @@ -991,6 +991,26 @@ } =20 /** + * 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 !=3D 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/o= rg/apache/derby/impl/sql/compile/RowResultSetNode.java?rev=3D189721&r1=3D18= 9720&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/RowResultSetNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/RowResultSetNode.java Wed Jun 8 23:48:34 2005 @@ -80,6 +80,8 @@ { super.init(null, tableProperties); resultColumns =3D (ResultColumnList) valuesClause; + if (resultColumns !=3D null) + resultColumns.markInitialSize(); } =20 /** 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/o= rg/apache/derby/impl/sql/compile/SelectNode.java?rev=3D189721&r1=3D189720&r= 2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/SelectNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/SelectNode.java Wed Jun 8 23:48:34 2005 @@ -132,6 +132,8 @@ * Consider adding selectAggregates and whereAggregates=20 */ resultColumns =3D (ResultColumnList) selectList; + if (resultColumns !=3D null) + resultColumns.markInitialSize(); this.fromList =3D (FromList) fromList; this.whereClause =3D (ValueNode) whereClause; this.originalWhereClause =3D (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/o= rg/apache/derby/impl/sql/compile/TypeCompilerFactoryImpl.java?rev=3D189721&= r1=3D189720&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/TypeCompilerFactoryImpl.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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; =20 +import org.apache.derby.iapi.services.io.StoredFormatIds; import java.util.Properties; =20 import java.sql.Types; @@ -65,6 +66,7 @@ static TypeCompiler blobTypeCompiler ; static TypeCompiler clobTypeCompiler ; static TypeCompiler nclobTypeCompiler ; + static TypeCompiler xmlTypeCompiler ; =20 /** * Get a TypeCompiler corresponding to the given TypeId @@ -256,6 +258,13 @@ btc.setTypeId(typeId); return btc; } + + case StoredFormatIds.XML_TYPE_ID: + return xmlTypeCompiler =3D + getAnInstance(PACKAGE_NAME + "XMLTypeCompi= ler", + xmlTypeCom= piler, + typeId); + } =20 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/o= rg/apache/derby/impl/sql/compile/UnaryOperatorNode.java?rev=3D189721&r1=3D1= 89720&r2=3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/UnaryOperatorNode.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/UnaryOperatorNode.java Wed Jun 8 23:48:34 2005 @@ -28,10 +28,15 @@ import org.apache.derby.iapi.sql.dictionary.DataDictionary; =20 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; =20 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; =20 +import java.sql.Types; import java.util.Vector; =20 /** @@ -50,10 +56,14 @@ * @author Jeff Lichtman */ =20 -public abstract class UnaryOperatorNode extends ValueNode +public class UnaryOperatorNode extends ValueNode { String operator; String methodName; + int operatorType; + + String resultInterfaceType; + String receiverInterfaceType; =20 /** * WARNING: operand may be NULL for COUNT(*). =20 @@ -65,22 +75,87 @@ public final static int NOT =3D 3; public final static int IS_NULL =3D 4; =20 + // 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 =3D 0; + public final static int XMLSERIALIZE_OP =3D 1; + + // NOTE: in the following 4 arrays, order + // IS important. + + static final String[] UnaryOperators =3D { + "xmlparse", + "xmlserialize" + }; + + static final String[] UnaryMethodNames =3D { + "XMLParse", + "XMLSerialize" + }; + + static final String[] UnaryResultTypes =3D { + ClassName.XMLDataValue, // XMLParse + ClassName.StringDataValue // XMLSerialize + }; + + static final String[] UnaryArgTypes =3D { + 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. */ =20 public void init( Object operand, - Object operator, - Object methodName) + Object operatorOrOpType, + Object methodNameOrAddedArgs) { this.operand =3D (ValueNode) operand; - this.operator =3D (String) operator; - this.methodName =3D (String) methodName; + if (operatorOrOpType instanceof String) { + // then 2nd and 3rd params are operator and methodName, + // respectively. + this.operator =3D (String) operatorOrOpType; + this.methodName =3D (String) methodNameOrAddedArgs; + this.operatorType =3D -1; + } + else { + // 2nd and 3rd params are operatorType and additional args, + // respectively. + if (SanityManager.DEBUG) { + SanityManager.ASSERT( + ((operatorOrOpType instanceof Integer) && + ((methodNameOrAddedArgs =3D=3D null) || + (methodNameOrAddedArgs instanceof Object[]))), + "Init params in UnaryOperator node have the " + + "wrong type."); + } + this.operatorType =3D ((Integer) operatorOrOpType).intValue(); + this.operator =3D UnaryOperators[this.operatorType]; + this.methodName =3D UnaryMethodNames[this.operatorType]; + this.resultInterfaceType =3D UnaryResultTypes[this.operatorType]; + this.receiverInterfaceType =3D UnaryArgTypes[this.operatorType]; + this.additionalArgs =3D (Object[])methodNameOrAddedArgs; + } } =20 /** @@ -91,6 +166,7 @@ public void init(Object operand) { this.operand =3D (ValueNode) operand; + this.operatorType =3D -1; } =20 /** @@ -103,6 +179,7 @@ void setOperator(String operator) { this.operator =3D operator; + this.operatorType =3D -1; } =20 /** @@ -125,6 +202,7 @@ void setMethodName(String methodName) { this.methodName =3D methodName; + this.operatorType =3D -1; } =20 /** @@ -257,9 +335,103 @@ operand =3D operand.genSQLJavaSQLTree(); } =20 + if (operatorType =3D=3D XMLPARSE_OP) + bindXMLParse(); + else if (operatorType =3D=3D XMLSERIALIZE_OP) + bindXMLSerialize(); + return this; } =20 + /** + * 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 =3D operand.getTypeId(); + if (operandType !=3D 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,=20 + 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 =3D operand.getTypeId(); + if ((operandType !=3D null) && !operandType.isXMLTypeId()) + { + throw StandardException.newException( + SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,=20 + 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 !=3D null) && (additionalArgs.length > 0)= ), + "Failed to locate target type for XMLSERIALIZE operator"); + } + + DataTypeDescriptor targetType =3D + (DataTypeDescriptor)additionalArgs[0]; + + TypeId targetTypeId =3D 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 @@ =20 void bindParameter() throws StandardException { - if (operand.getTypeServices() =3D=3D null) + if (operatorType =3D=3D 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 =3D=3D 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() =3D=3D null) { throw StandardException.newException(SQLState.LANG_UNARY_OPERAND_PARM, = operator); } @@ -399,7 +586,11 @@ if (operand =3D=3D null) return; =20 - String resultTypeName =3D getTypeCompiler().interfaceName(); + String resultTypeName =3D=20 + (operatorType =3D=3D -1) + ? getTypeCompiler().interfaceName() + : resultInterfaceType; + =09 // System.out.println("resultTypeName " + resultTypeName + " method " + = methodName); // System.out.println("isBooleanTypeId() " + getTypeId().isBooleanTypeId= ()); =20 @@ -414,7 +605,8 @@ /* Allocate an object for re-use to hold the result of the operator */ LocalField field =3D acb.newFieldDeclaration(Modifier.PRIVATE, resultTy= peName); mb.getField(field); - mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resu= ltTypeName, 1); + int numParams =3D 1 + addMethodParams(mb); + mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resu= ltTypeName, numParams); =20 /* ** 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, resu= ltTypeName, 0); + int numParams =3D addMethodParams(mb); + mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resu= ltTypeName, numParams); } } =20 @@ -442,6 +635,9 @@ "cannot get interface without operand"); } =20 + if (operatorType !=3D -1) + return receiverInterfaceType; + =09 return operand.getTypeCompiler().interfaceName(); } =20 @@ -495,4 +691,35 @@ =20 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 =3D=3D XMLPARSE_OP) { + // We push whether or not we want to preserve whitespace. + mb.push(((Boolean)additionalArgs[0]).booleanValue()); + return 1; + } + + if (operatorType =3D=3D 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 =3D + (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/com= pile/XMLConstantNode.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/o= rg/apache/derby/impl/sql/compile/XMLConstantNode.java?rev=3D189721&view=3Da= uto =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/XMLConstantNode.java (added) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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 appl= icable. + + 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=20 + { + 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,=20 + * + * @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/sq= l/compile/XMLConstantNode.java ---------------------------------------------------------------------------= --- svn:eol-style =3D native Added: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/com= pile/XMLTypeCompiler.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/engine/o= rg/apache/derby/impl/sql/compile/XMLTypeCompiler.java?rev=3D189721&view=3Da= uto =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/XMLTypeCompiler.java (added) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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 appl= icable. + + 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 + * + * @see TypeCompiler#convertible + */ + public boolean convertible(TypeId otherType,=20 + 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 =3D getStoredFormatIdFromTypeId(); + if (formatId =3D=3D 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 =3D getStoredFormatIdFromTypeId(); + if (formatId =3D=3D 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 =3D getStoredFormatIdFromTypeId(); + if (formatId =3D=3D StoredFormatIds.XML_TYPE_ID) + return "getXMLDataValue"; + + if (SanityManager.DEBUG) { + SanityManager.THROWASSERT( + "unexpected formatId in dataValueMethodName() - " + format= Id); + } + + return null; + } +} Propchange: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sq= l/compile/XMLTypeCompiler.java ---------------------------------------------------------------------------= --- svn:eol-style =3D 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/o= rg/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=3D189721&r1=3D189720&r2= =3D189721&view=3Ddiff =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/sqlgrammar.jj (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compil= e/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; =20 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 =3D true; break; =20 @@ -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. */ =20 /* NOTE - If you add a keyword, then you must add it to reservedKeyword() @@ -1904,10 +1910,19 @@ | | | +| +| +| +| } =20 /* 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 N= ON- + * 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 @@ | | | +| | | | | +| | | | @@ -1939,8 +1956,10 @@ | | | +| | | +| | | | @@ -1955,10 +1974,12 @@ | | | +| | | | | +| } =20 TOKEN : @@ -3377,6 +3398,8 @@ typeDescriptor =3D longType() | typeDescriptor =3D LOBType() +| + typeDescriptor =3D XMLType() ) { return typeDescriptor; @@ -3790,6 +3813,55 @@ } =20 /* + * XMLType + */ +DataTypeDescriptor +XMLType() throws StandardException : +{ + DataTypeDescriptor value; +} +{ + + { + checkVersion(DataDictionary.DD_VERSION_DERBY_10_1, "XML"); + return DataTypeDescriptor.getBuiltInDataTypeDescriptor( + StoredFormatIds.XML_TYPE_ID); + } +} + +/* + * xmlDocOrContent + * + * 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 !=3D DOCUMENT) && + (getToken(1).kind !=3D CONTENT) }) + { + throw StandardException.newException( + SQLState.LANG_XML_KEYWORD_MISSING, "DOCUMENT"); + } +| + LOOKAHEAD({ getToken(1).kind =3D=3D CONTENT }) + { + throw StandardException.newException( + SQLState.LANG_UNSUPPORTED_XML_FEATURE, "CONTENT"); + } +| + LOOKAHEAD({ getToken(1).kind =3D=3D DOCUMENT }) + { + return; + } +} + +/* * javaType */ DataTypeDescriptor @@ -5995,7 +6067,10 @@ getToken(1).kind =3D=3D MINUTE || getToken(1).kind =3D=3D SECOND || getToken(1).kind =3D=3D LENGTH || - getToken(1).kind =3D=3D LOCATE ) && + getToken(1).kind =3D=3D LOCATE || + getToken(1).kind =3D=3D XMLPARSE || + getToken(1).kind =3D=3D XMLSERIALIZE || + getToken(1).kind =3D=3D XMLEXISTS ) && getToken(2).kind =3D=3D LEFT_PAREN ) } ) @@ -6094,6 +6169,11 @@ value, localCM); } +| + value =3D xmlFunction() + { + return value; + } } =20 =20 @@ -6144,6 +6224,237 @@ } } =20 +/* + * xmlFunction + * + * 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"); +} +{ + + xmlDocOrContent() value =3D xmlParseValue() + { + return value; + } +| + value =3D xmlSerializeValue() + { + return value; + } +| + value =3D xmlExistsValue() + { + return value; + } +} + +/* + * xmlParseValue + * + * Syntax is as follows: + * + * XMLPARSE( DOCUMENT 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 ' doc ' + * 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 th= at + * if no whitespace option is given, the default is "STRIP WHITESPACE", wh= ich + * 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 =3D additiveExpression(null,0,false) wsOption =3D xmlPreserveWhites= pace() { + return (ValueNode) nodeFactory.getNode( + C_NodeTypes.XML_PARSE_OPERATOR_NODE, + value, + ReuseFactory.getInteger(UnaryOperatorNode.XMLPARSE_OP), + new Object[] {(wsOption ? Boolean.TRUE : Boolean.FALSE)}, + getContextManager()); + } +} + +/* + * xmlPreserveWhitespace + * + * For now, we only support the PRESERVE WHITESPACE option. + * + */ +boolean + xmlPreserveWhitespace() throws StandardException : +{ +} +{ + LOOKAHEAD({ (getToken(1).kind !=3D STRIP) && + (getToken(1).kind !=3D PRESERVE) }) + { + throw StandardException.newException( + SQLState.LANG_XML_KEYWORD_MISSING, "PRESERVE WHITESPACE"); + } +| + + { // don't preserve whitespace. + throw StandardException.newException( + SQLState.LANG_UNSUPPORTED_XML_FEATURE, "STRIP WHITESPACE"); + } +| + + { // must preserve whitespace. + return true; + } +} + +/* + * xmlSerializeValue + * + * Syntax is as follows: + * + * XMLSERIALIZE( AS ) + * + * The result of this operation will be a string value with the type speci= fied + * by the user. For example: + * + * ij> SELECT id, XMLSERIALIZE(xdoc AS varchar(30)) FROM x_table; + * ID |2 + * ------------------------------------------ + * 1 | doc + * + */ +ValueNode + xmlSerializeValue() throws StandardException : +{ + ValueNode value; + DataTypeDescriptor targetType; +} +{ + value =3D additiveExpression(null,0,false) + targetType =3D xmlSerializeTargetType() + { + return (ValueNode) nodeFactory.getNode( + C_NodeTypes.XML_SERIALIZE_OPERATOR_NODE, + value, + ReuseFactory.getInteger(UnaryOperatorNode.XMLSERIALIZE_OP), + new Object[] {targetType}, + getContextManager()); + } +} + +/* + * xmlSerializeTargetType + * + * Parse the target type of an XMLSERIALIZE operation. + * + */ +DataTypeDescriptor xmlSerializeTargetType() throws StandardException : +{ + DataTypeDescriptor targetType; +} +{ + LOOKAHEAD({ (getToken(1).kind !=3D AS) || (getToken(2).kind =3D=3D RIGHT_= PAREN) }) + { + throw StandardException.newException( + SQLState.LANG_XML_KEYWORD_MISSING, "AS "); + } +| + targetType =3D dataTypeDDL() + { + return targetType; + } +} + +/* + * xmlExistsValue + * + * Syntax is as follows: + * + * XMLEXISTS( PASSING BY VALUE = ) + * + * The result of this operation will be a boolean true/false/unknown value: + * -- Unknown if either or 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 x= doc); + * ID + * ----------- + * 1 + * + */ +ValueNode + xmlExistsValue() throws StandardException : +{ + ValueNode xpathExpr; + ValueNode xmlValue; +} +{ + xpathExpr =3D additiveExpression(null,0,false) + xmlPassingMechanism() xmlValue =3D additiveExpression(null, 0, false) + { + return (ValueNode) nodeFactory.getNode( + C_NodeTypes.XML_EXISTS_OPERATOR_NODE, + xpathExpr, + xmlValue, + ReuseFactory.getInteger(BinaryOperatorNode.XMLEXISTS_OP), + getContextManager()); + } +} + +/* + * xmlPassingMechanism + * + * 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 =3D=3D REF }) + + { // pass the XML value by reference + throw StandardException.newException( + SQLState.LANG_UNSUPPORTED_XML_FEATURE, "BY REF"); + } +| + + { // pass a 'copy' of the XML value. + return; + } +} =20 /* * numericFunctionType @@ -11432,6 +11743,10 @@ | tok =3D | tok =3D | tok =3D +| tok =3D +| tok =3D +| tok =3D +| tok =3D ) { // Remember whether last token was a delimited identifier @@ -11476,6 +11791,7 @@ | tok =3D | tok =3D | tok =3D + | tok =3D | tok =3D | tok =3D | tok =3D @@ -11487,6 +11803,7 @@ | tok =3D | tok =3D | tok =3D + | tok =3D | tok =3D | tok =3D | tok =3D @@ -11533,10 +11850,12 @@ | tok =3D | tok =3D | tok =3D + | tok =3D | tok =3D | tok =3D | tok =3D | tok =3D + | tok =3D // SQL92 says it is reserved, but we want it to be non-reserved. | tok =3D | tok =3D @@ -11571,6 +11890,7 @@ | tok =3D | tok =3D | tok =3D + | tok =3D | tok =3D | tok =3D