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 dj...@apache.org on 2004/09/24 19:33:21 UTC
svn commit: rev 47170 - in incubator/derby/code/trunk: . java/engine/org/apache/derby/iapi/services/cache java/engine/org/apache/derby/iapi/services/classfile java/engine/org/apache/derby/iapi/services/stream java/engine/org/apache/derby/iapi/services/uuid java/engine/org/apache/derby/iapi/sql java/engine/org/apache/derby/iapi/sql/compile java/engine/org/apache/derby/impl/sql/compile java/tools/org/apache/derby/impl/tools/ij java/tools/org/apache/derby/impl/tools/sysinfo java/tools/org/apache/derby/tools
Author: djd
Date: Fri Sep 24 10:33:20 2004
New Revision: 47170
Modified:
incubator/derby/code/trunk/BUILDING.txt (props changed)
incubator/derby/code/trunk/build.xml (props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/cache/SizedCacheable.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/AttributeEntry.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/Attributes.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Double_info.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Float_info.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Index_info.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Integer_info.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassEnumeration.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassFormatOutput.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassHolder.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInput.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInvestigator.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassMember.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ConstantPoolEntry.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/HeaderPrintWriter.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/InfoStreams.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/PrintWriterGetHeader.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/uuid/UUIDFactory.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageFactory.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageProperties.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ParameterValueSet.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/PreparedStatement.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultColumnDescriptor.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultSet.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Row.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Statement.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementType.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementUtil.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StorablePreparedStatement.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/AccessPath.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SQLToJavaValueNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticClassFieldReferenceNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StringSlicer.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SumAvgAggregateDefinition.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableName.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableOperatorNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TestConstraintNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimeTypeCompiler.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampOperatorNode.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampTypeCompiler.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Token.java (contents, props changed)
incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TransactionStatementNode.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ConnectionEnv.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main14.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ParseException.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Session.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/StatementFinder.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/UCode_CharStream.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijConnectionResult.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijException.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijExceptionResult.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijFatalException.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijMultiResult.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijResult.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijVectorResult.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijWarningResult.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestCase.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestSuite.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTester.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTime.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/util.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain14.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaAbstractHelper.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaHelper.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/Main.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/ZipInfoProperties.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/tools/JDBCDisplayUtil.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/tools/URLCheck.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/tools/dblook.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/tools/ij.java (contents, props changed)
incubator/derby/code/trunk/java/tools/org/apache/derby/tools/sysinfo.java (contents, props changed)
Log:
Set svn:eol-style to native on remaining text files.
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/cache/SizedCacheable.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/cache/SizedCacheable.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/cache/SizedCacheable.java Fri Sep 24 10:33:20 2004
@@ -1,40 +1,40 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.cache
- (C) Copyright IBM Corp. 2002, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.cache;
-
-/**
- * This interface extends the Cacheable interface (@see Cacheable) with a method that
- * estimates the size of the Cacheable object, in bytes. CacheManagers constructed with the SizedCacheFactory
- * interface regulate the total estimated cache size, in bytes.
- * CacheManagers constructed with the CacheFactory use regulate the total number of cache entries.
- *
- * @see Cacheable
- * @see SizedCacheableFactory
- * @see CacheFactory
- *
- * @author Jack Klebanoff
- */
-
-public interface SizedCacheable extends Cacheable
-{
- /**
- IBM Copyright © notice.
- */
-
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2002_2004;
-
- /**
- * Get the estimated size of the cacheable object.
- *
- * @return the estimated size, in bytes
- */
- public int getSize();
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.cache
+ (C) Copyright IBM Corp. 2002, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.cache;
+
+/**
+ * This interface extends the Cacheable interface (@see Cacheable) with a method that
+ * estimates the size of the Cacheable object, in bytes. CacheManagers constructed with the SizedCacheFactory
+ * interface regulate the total estimated cache size, in bytes.
+ * CacheManagers constructed with the CacheFactory use regulate the total number of cache entries.
+ *
+ * @see Cacheable
+ * @see SizedCacheableFactory
+ * @see CacheFactory
+ *
+ * @author Jack Klebanoff
+ */
+
+public interface SizedCacheable extends Cacheable
+{
+ /**
+ IBM Copyright © notice.
+ */
+
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2002_2004;
+
+ /**
+ * Get the estimated size of the cacheable object.
+ *
+ * @return the estimated size, in bytes
+ */
+ public int getSize();
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/AttributeEntry.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/AttributeEntry.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/AttributeEntry.java Fri Sep 24 10:33:20 2004
@@ -1,58 +1,58 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import java.io.IOException;
-
-class AttributeEntry {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
- private int attribute_name_index;
- private ClassFormatOutput infoOut;
- byte[] infoIn;
-
- AttributeEntry(int name_index, ClassFormatOutput info) {
- super();
-
- attribute_name_index = name_index;
- this.infoOut = info;
- }
-
-
- AttributeEntry(ClassInput in) throws IOException {
- attribute_name_index = in.getU2();
- infoIn = in.getU1Array(in.getU4());
- }
-
- int getNameIndex() { return attribute_name_index; }
-
- void put(ClassFormatOutput out) throws IOException {
- out.putU2(attribute_name_index);
- if (infoOut != null) {
- out.putU4(infoOut.size());
- infoOut.writeTo(out);
- } else {
- out.putU4(infoIn.length);
- out.write(infoIn);
- }
- }
-
- /**
- This is exact.
- */
- int classFileSize() {
- return 2 + 4 +
- ((infoOut != null) ? infoOut.size() : infoIn.length);
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import java.io.IOException;
+
+class AttributeEntry {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+ private int attribute_name_index;
+ private ClassFormatOutput infoOut;
+ byte[] infoIn;
+
+ AttributeEntry(int name_index, ClassFormatOutput info) {
+ super();
+
+ attribute_name_index = name_index;
+ this.infoOut = info;
+ }
+
+
+ AttributeEntry(ClassInput in) throws IOException {
+ attribute_name_index = in.getU2();
+ infoIn = in.getU1Array(in.getU4());
+ }
+
+ int getNameIndex() { return attribute_name_index; }
+
+ void put(ClassFormatOutput out) throws IOException {
+ out.putU2(attribute_name_index);
+ if (infoOut != null) {
+ out.putU4(infoOut.size());
+ infoOut.writeTo(out);
+ } else {
+ out.putU4(infoIn.length);
+ out.write(infoIn);
+ }
+ }
+
+ /**
+ This is exact.
+ */
+ int classFileSize() {
+ return 2 + 4 +
+ ((infoOut != null) ? infoOut.size() : infoIn.length);
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/Attributes.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/Attributes.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/Attributes.java Fri Sep 24 10:33:20 2004
@@ -1,47 +1,47 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import java.util.Vector;
-
-import java.io.IOException;
-
-class Attributes extends Vector {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- private int classFileSize;
-
- Attributes(int count) {
- super(count);
- }
-
- void put(ClassFormatOutput out) throws IOException {
- int size = size();
- for (int i = 0; i < size; i++) {
- ((AttributeEntry) elementAt(i)).put(out);
- }
- }
-
- int classFileSize() {
- return classFileSize;
- }
-
- /**
- */
-
- void addEntry(AttributeEntry item) {
- addElement(item);
- classFileSize += item.classFileSize();
- }
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import java.util.Vector;
+
+import java.io.IOException;
+
+class Attributes extends Vector {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ private int classFileSize;
+
+ Attributes(int count) {
+ super(count);
+ }
+
+ void put(ClassFormatOutput out) throws IOException {
+ int size = size();
+ for (int i = 0; i < size; i++) {
+ ((AttributeEntry) elementAt(i)).put(out);
+ }
+ }
+
+ int classFileSize() {
+ return classFileSize;
+ }
+
+ /**
+ */
+
+ void addEntry(AttributeEntry item) {
+ addElement(item);
+ classFileSize += item.classFileSize();
+ }
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Double_info.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Double_info.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Double_info.java Fri Sep 24 10:33:20 2004
@@ -1,56 +1,56 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-
-import java.io.IOException;
-
-/** Double Constant - page 97 - Section 4.4.5 */
-final class CONSTANT_Double_info extends ConstantPoolEntry {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- private final double value;
-
- CONSTANT_Double_info(double value) {
- super(VMDescriptor.CONSTANT_Double);
- doubleSlot = true; //See page 98.
- this.value = value;
- }
-
- public int hashCode() {
- return (int) value;
- }
-
- int classFileSize() {
- // 1 (tag) + 8 (double length)
- return 1 + 8;
- }
- void put(ClassFormatOutput out) throws IOException {
- super.put(out);
- out.writeDouble(value);
- }
-
- public boolean equals(Object other) {
-
- // check it is the right type
- if (other instanceof CONSTANT_Double_info) {
-
- return value == ((CONSTANT_Double_info) other).value;
- }
-
- return false;
- }
-}
-
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+
+import java.io.IOException;
+
+/** Double Constant - page 97 - Section 4.4.5 */
+final class CONSTANT_Double_info extends ConstantPoolEntry {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ private final double value;
+
+ CONSTANT_Double_info(double value) {
+ super(VMDescriptor.CONSTANT_Double);
+ doubleSlot = true; //See page 98.
+ this.value = value;
+ }
+
+ public int hashCode() {
+ return (int) value;
+ }
+
+ int classFileSize() {
+ // 1 (tag) + 8 (double length)
+ return 1 + 8;
+ }
+ void put(ClassFormatOutput out) throws IOException {
+ super.put(out);
+ out.writeDouble(value);
+ }
+
+ public boolean equals(Object other) {
+
+ // check it is the right type
+ if (other instanceof CONSTANT_Double_info) {
+
+ return value == ((CONSTANT_Double_info) other).value;
+ }
+
+ return false;
+ }
+}
+
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Float_info.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Float_info.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Float_info.java Fri Sep 24 10:33:20 2004
@@ -1,55 +1,55 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-import java.io.IOException;
-
-
-/** Float Constant - page 96 */
-final class CONSTANT_Float_info extends ConstantPoolEntry {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- private final float value;
-
- CONSTANT_Float_info(float value) {
- super(VMDescriptor.CONSTANT_Float);
- this.value = value;
- }
-
- public int hashCode() {
- return (int) value;
- }
-
- public boolean equals(Object other) {
-
- // check it is the right type
- if (other instanceof CONSTANT_Float_info) {
-
- return value == ((CONSTANT_Float_info) other).value;
- }
-
- return false;
- }
-
- int classFileSize() {
- // 1 (tag) + 4 (float length)
- return 1 + 4;
- }
-
- void put(ClassFormatOutput out) throws IOException {
- super.put(out);
- out.writeFloat(value);
- }
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+import java.io.IOException;
+
+
+/** Float Constant - page 96 */
+final class CONSTANT_Float_info extends ConstantPoolEntry {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ private final float value;
+
+ CONSTANT_Float_info(float value) {
+ super(VMDescriptor.CONSTANT_Float);
+ this.value = value;
+ }
+
+ public int hashCode() {
+ return (int) value;
+ }
+
+ public boolean equals(Object other) {
+
+ // check it is the right type
+ if (other instanceof CONSTANT_Float_info) {
+
+ return value == ((CONSTANT_Float_info) other).value;
+ }
+
+ return false;
+ }
+
+ int classFileSize() {
+ // 1 (tag) + 4 (float length)
+ return 1 + 4;
+ }
+
+ void put(ClassFormatOutput out) throws IOException {
+ super.put(out);
+ out.writeFloat(value);
+ }
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Index_info.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Index_info.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Index_info.java Fri Sep 24 10:33:20 2004
@@ -1,85 +1,85 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-
-import java.io.IOException;
-
- /**
-
- A generic constant pool entry for entries that simply hold indexes
- into other entries.
-
- <BR>
- Ref Constant Pool Entry - page 94 - Section 4.4.2 - Two indexes
- <BR>
- NameAndType Constant Pool Entry - page 99 - Section 4.4.6 - Two indexes
- <BR>
- String Constant Pool Entry - page 96 - Section 4.4.3 - One index
- <BR>
- Class Reference Constant Pool Entry - page 93 - Section 4.4.1 - One index
-
-*/
-final class CONSTANT_Index_info extends ConstantPoolEntry {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
- private int i1;
- private int i2;
-
- CONSTANT_Index_info(int tag, int i1, int i2) {
- super(tag);
- this.i1 = i1;
- this.i2 = i2;
- }
-
- public int hashCode() {
- return (tag << 16) | ((i1 << 8) ^ i2);
- }
-
- public boolean equals(Object other) {
- if (other instanceof CONSTANT_Index_info) {
- CONSTANT_Index_info o = (CONSTANT_Index_info) other;
-
- return (tag == o.tag) && (i1 == o.i1) && (i2 == o.i2);
- }
- return false;
- }
-
-
- /**
- Used when searching
- */
- void set(int tag, int i1, int i2) {
- this.tag = tag;
- this.i1 = i1;
- this.i2 = i2;
- }
-
- int classFileSize() {
- // 1 (tag) + 2 (index length) [ + 2 (index length) ]
- return 1 + 2 + ((i2 != 0) ? 2 : 0);
- }
-
- void put(ClassFormatOutput out) throws IOException {
- super.put(out);
- out.putU2(i1);
- if (i2 != 0)
- out.putU2(i2);
- }
-
- public int getI1() { return i1; }
-
- public int getI2() { return i2; }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+
+import java.io.IOException;
+
+ /**
+
+ A generic constant pool entry for entries that simply hold indexes
+ into other entries.
+
+ <BR>
+ Ref Constant Pool Entry - page 94 - Section 4.4.2 - Two indexes
+ <BR>
+ NameAndType Constant Pool Entry - page 99 - Section 4.4.6 - Two indexes
+ <BR>
+ String Constant Pool Entry - page 96 - Section 4.4.3 - One index
+ <BR>
+ Class Reference Constant Pool Entry - page 93 - Section 4.4.1 - One index
+
+*/
+final class CONSTANT_Index_info extends ConstantPoolEntry {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+ private int i1;
+ private int i2;
+
+ CONSTANT_Index_info(int tag, int i1, int i2) {
+ super(tag);
+ this.i1 = i1;
+ this.i2 = i2;
+ }
+
+ public int hashCode() {
+ return (tag << 16) | ((i1 << 8) ^ i2);
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof CONSTANT_Index_info) {
+ CONSTANT_Index_info o = (CONSTANT_Index_info) other;
+
+ return (tag == o.tag) && (i1 == o.i1) && (i2 == o.i2);
+ }
+ return false;
+ }
+
+
+ /**
+ Used when searching
+ */
+ void set(int tag, int i1, int i2) {
+ this.tag = tag;
+ this.i1 = i1;
+ this.i2 = i2;
+ }
+
+ int classFileSize() {
+ // 1 (tag) + 2 (index length) [ + 2 (index length) ]
+ return 1 + 2 + ((i2 != 0) ? 2 : 0);
+ }
+
+ void put(ClassFormatOutput out) throws IOException {
+ super.put(out);
+ out.putU2(i1);
+ if (i2 != 0)
+ out.putU2(i2);
+ }
+
+ public int getI1() { return i1; }
+
+ public int getI2() { return i2; }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Integer_info.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Integer_info.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/CONSTANT_Integer_info.java Fri Sep 24 10:33:20 2004
@@ -1,54 +1,54 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-import java.io.IOException;
-
-/** Integer Constant - page 96 */
-class CONSTANT_Integer_info extends ConstantPoolEntry {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- private final int value;
-
- CONSTANT_Integer_info(int value) {
- super(VMDescriptor.CONSTANT_Integer);
- this.value = value;
- }
-
- public int hashCode() {
- return value;
- }
-
- void put(ClassFormatOutput out) throws IOException {
- super.put(out);
- out.putU4(value);
- }
-
- public boolean equals(Object other) {
-
- // check it is the right type
- if (other instanceof CONSTANT_Integer_info) {
-
- return value == ((CONSTANT_Integer_info) other).value;
- }
-
- return false;
- }
-
- int classFileSize() {
- // 1 (tag) + 4 (int length)
- return 1 + 4;
- }
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+import java.io.IOException;
+
+/** Integer Constant - page 96 */
+class CONSTANT_Integer_info extends ConstantPoolEntry {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ private final int value;
+
+ CONSTANT_Integer_info(int value) {
+ super(VMDescriptor.CONSTANT_Integer);
+ this.value = value;
+ }
+
+ public int hashCode() {
+ return value;
+ }
+
+ void put(ClassFormatOutput out) throws IOException {
+ super.put(out);
+ out.putU4(value);
+ }
+
+ public boolean equals(Object other) {
+
+ // check it is the right type
+ if (other instanceof CONSTANT_Integer_info) {
+
+ return value == ((CONSTANT_Integer_info) other).value;
+ }
+
+ return false;
+ }
+
+ int classFileSize() {
+ // 1 (tag) + 4 (int length)
+ return 1 + 4;
+ }
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassEnumeration.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassEnumeration.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassEnumeration.java Fri Sep 24 10:33:20 2004
@@ -1,194 +1,194 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.StringTokenizer;
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-
-/**
- An enumeration that filters only classes
- from the enumeration of the class pool.
-
- Code has been added to also include classes referenced in method and
- field signatures.
-*/
-
-
-class ClassEnumeration implements Enumeration {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- ClassHolder cpt;
- Enumeration inner;
- CONSTANT_Index_info position;
- HashSet foundClasses;
- Enumeration classList;
-
- ClassEnumeration( ClassHolder cpt,
- Enumeration e,
- Enumeration methods,
- Enumeration fields)
- {
- this.cpt = cpt;
- inner = e;
- foundClasses = new HashSet(30, 0.8f);
- findMethodReferences(methods, foundClasses);
- findFieldReferences(fields, foundClasses);
- findClassReferences(foundClasses);
- classList = java.util.Collections.enumeration(foundClasses);
-
- }
-
- public boolean hasMoreElements() {
- return classList.hasMoreElements();
- }
-
- // uses cpt and inner
- private void findClassReferences(HashSet foundClasses)
- {
-
- ConstantPoolEntry item;
- CONSTANT_Index_info ref;
-
-
- while (inner.hasMoreElements())
- {
- item = (ConstantPoolEntry) inner.nextElement();
- if (item == null)
- continue;
- if (item.getTag() == VMDescriptor.CONSTANT_Class)
- {
- ref = (CONSTANT_Index_info) item;
-
- String className = cpt.className(ref.getIndex());
-
- // if this is an array type, distillClasses can
- // handle it
- if (className.startsWith("["))
- {
- distillClasses(className, foundClasses);
- continue;
- }
-
- // now we've got either a primitive type or a classname
- // primitive types are all a single char
-
- if (className.length() > 1)
- {
- //we've got a class
- if (className.startsWith("java"))
- {
- //skip it
- continue;
- }
-
- foundClasses.add(className);
- }
- }
- }
-
- }
-
- private void findMethodReferences( Enumeration methods,
- HashSet foundClasses)
- {
- while (methods.hasMoreElements())
- {
- ClassMember member = (ClassMember) methods.nextElement();
- String description = member.getDescriptor();
- distillClasses(description, foundClasses);
- }
- }
-
- private void findFieldReferences( Enumeration fields,
- HashSet foundClasses)
- {
- while (fields.hasMoreElements())
- {
- ClassMember member = (ClassMember) fields.nextElement();
- String description = member.getDescriptor();
- distillClasses(description, foundClasses);
- }
- }
-
- void distillClasses(String fieldOrMethodSig, HashSet foundClasses)
- {
- if (fieldOrMethodSig == null || fieldOrMethodSig.length() < 1)
- {
- //empty string
- return;
- }
-
- if (fieldOrMethodSig.charAt(0) != '(')
- {
- // first time through, we're dealing with a field here
- // otherwise, it is a token from a method signature
-
- int classNameStart = fieldOrMethodSig.indexOf('L');
-
- if (classNameStart == -1)
- {
- // no class in the type, so stop
- return;
- }
-
- // chop off any leading ['s or other Java-primitive type
- // signifiers (like I or L) *AND* substitute the dots
- String fieldType =
- fieldOrMethodSig.substring(classNameStart + 1).replace('/', '.');
-
- // we have to check for the semi-colon in case we are
- // actually looking at a token from a method signature
- if (fieldType.endsWith(";"))
- {
- fieldType = fieldType.substring(0,fieldType.length()-1);
- }
-
- if (fieldType.startsWith("java"))
- {
- return; // it's a java base class and we don't care about
- // that either
- }
-
- foundClasses.add(fieldType);
- return;
- }
- else
- {
- // it's a method signature
- StringTokenizer tokens = new StringTokenizer(fieldOrMethodSig, "();[");
- while (tokens.hasMoreElements())
- {
- String aToken = (String) tokens.nextToken();
- // because of the semi-colon delimiter in the tokenizer, we
- // can have only one class name per token and it must be the
- // last item in the token
- int classNameStart = aToken.indexOf('L');
- if (classNameStart != -1)
- {
- distillClasses(aToken, foundClasses);
- }
- else
- {
- continue;
- }
- }
- }
- }
-
- public Object nextElement() {
- return classList.nextElement();
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+
+/**
+ An enumeration that filters only classes
+ from the enumeration of the class pool.
+
+ Code has been added to also include classes referenced in method and
+ field signatures.
+*/
+
+
+class ClassEnumeration implements Enumeration {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ ClassHolder cpt;
+ Enumeration inner;
+ CONSTANT_Index_info position;
+ HashSet foundClasses;
+ Enumeration classList;
+
+ ClassEnumeration( ClassHolder cpt,
+ Enumeration e,
+ Enumeration methods,
+ Enumeration fields)
+ {
+ this.cpt = cpt;
+ inner = e;
+ foundClasses = new HashSet(30, 0.8f);
+ findMethodReferences(methods, foundClasses);
+ findFieldReferences(fields, foundClasses);
+ findClassReferences(foundClasses);
+ classList = java.util.Collections.enumeration(foundClasses);
+
+ }
+
+ public boolean hasMoreElements() {
+ return classList.hasMoreElements();
+ }
+
+ // uses cpt and inner
+ private void findClassReferences(HashSet foundClasses)
+ {
+
+ ConstantPoolEntry item;
+ CONSTANT_Index_info ref;
+
+
+ while (inner.hasMoreElements())
+ {
+ item = (ConstantPoolEntry) inner.nextElement();
+ if (item == null)
+ continue;
+ if (item.getTag() == VMDescriptor.CONSTANT_Class)
+ {
+ ref = (CONSTANT_Index_info) item;
+
+ String className = cpt.className(ref.getIndex());
+
+ // if this is an array type, distillClasses can
+ // handle it
+ if (className.startsWith("["))
+ {
+ distillClasses(className, foundClasses);
+ continue;
+ }
+
+ // now we've got either a primitive type or a classname
+ // primitive types are all a single char
+
+ if (className.length() > 1)
+ {
+ //we've got a class
+ if (className.startsWith("java"))
+ {
+ //skip it
+ continue;
+ }
+
+ foundClasses.add(className);
+ }
+ }
+ }
+
+ }
+
+ private void findMethodReferences( Enumeration methods,
+ HashSet foundClasses)
+ {
+ while (methods.hasMoreElements())
+ {
+ ClassMember member = (ClassMember) methods.nextElement();
+ String description = member.getDescriptor();
+ distillClasses(description, foundClasses);
+ }
+ }
+
+ private void findFieldReferences( Enumeration fields,
+ HashSet foundClasses)
+ {
+ while (fields.hasMoreElements())
+ {
+ ClassMember member = (ClassMember) fields.nextElement();
+ String description = member.getDescriptor();
+ distillClasses(description, foundClasses);
+ }
+ }
+
+ void distillClasses(String fieldOrMethodSig, HashSet foundClasses)
+ {
+ if (fieldOrMethodSig == null || fieldOrMethodSig.length() < 1)
+ {
+ //empty string
+ return;
+ }
+
+ if (fieldOrMethodSig.charAt(0) != '(')
+ {
+ // first time through, we're dealing with a field here
+ // otherwise, it is a token from a method signature
+
+ int classNameStart = fieldOrMethodSig.indexOf('L');
+
+ if (classNameStart == -1)
+ {
+ // no class in the type, so stop
+ return;
+ }
+
+ // chop off any leading ['s or other Java-primitive type
+ // signifiers (like I or L) *AND* substitute the dots
+ String fieldType =
+ fieldOrMethodSig.substring(classNameStart + 1).replace('/', '.');
+
+ // we have to check for the semi-colon in case we are
+ // actually looking at a token from a method signature
+ if (fieldType.endsWith(";"))
+ {
+ fieldType = fieldType.substring(0,fieldType.length()-1);
+ }
+
+ if (fieldType.startsWith("java"))
+ {
+ return; // it's a java base class and we don't care about
+ // that either
+ }
+
+ foundClasses.add(fieldType);
+ return;
+ }
+ else
+ {
+ // it's a method signature
+ StringTokenizer tokens = new StringTokenizer(fieldOrMethodSig, "();[");
+ while (tokens.hasMoreElements())
+ {
+ String aToken = (String) tokens.nextToken();
+ // because of the semi-colon delimiter in the tokenizer, we
+ // can have only one class name per token and it must be the
+ // last item in the token
+ int classNameStart = aToken.indexOf('L');
+ if (classNameStart != -1)
+ {
+ distillClasses(aToken, foundClasses);
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
+ }
+
+ public Object nextElement() {
+ return classList.nextElement();
+ }
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassFormatOutput.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassFormatOutput.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassFormatOutput.java Fri Sep 24 10:33:20 2004
@@ -1,68 +1,68 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.io.AccessibleByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-
-/** A wrapper around DataOutputStream to provide input functions in terms
- of the types defined on pages 83.
-
- For this types use these methods of DataOutputStream
- <UL>
- <LI>float - writeFloat
- <LI>long - writeLong
- <LI>double - writeDouble
- <LI>UTF/String - writeUTF
- <LI>U1Array - write(byte[])
- </UL>
- */
-
-public final class ClassFormatOutput extends DataOutputStream {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
- public ClassFormatOutput() {
- this(512);
- }
-
- public ClassFormatOutput(int size) {
- super(new AccessibleByteArrayOutputStream(size));
- }
-
- public void putU1(int i) throws IOException {
- write(i);
- }
- public void putU2(int i) throws IOException {
- write(i >> 8);
- write(i);
- }
- public void putU4(int i) throws IOException {
- writeInt(i);
- }
-
- public void writeTo(OutputStream outTo) throws IOException {
- ((AccessibleByteArrayOutputStream) out).writeTo(outTo);
- }
-
- /**
- Get a reference to the data array the class data is being built
- in. No copy is made.
- */
- public byte[] getData() {
- return ((AccessibleByteArrayOutputStream) out).getInternalByteArray();
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.io.AccessibleByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+
+/** A wrapper around DataOutputStream to provide input functions in terms
+ of the types defined on pages 83.
+
+ For this types use these methods of DataOutputStream
+ <UL>
+ <LI>float - writeFloat
+ <LI>long - writeLong
+ <LI>double - writeDouble
+ <LI>UTF/String - writeUTF
+ <LI>U1Array - write(byte[])
+ </UL>
+ */
+
+public final class ClassFormatOutput extends DataOutputStream {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+ public ClassFormatOutput() {
+ this(512);
+ }
+
+ public ClassFormatOutput(int size) {
+ super(new AccessibleByteArrayOutputStream(size));
+ }
+
+ public void putU1(int i) throws IOException {
+ write(i);
+ }
+ public void putU2(int i) throws IOException {
+ write(i >> 8);
+ write(i);
+ }
+ public void putU4(int i) throws IOException {
+ writeInt(i);
+ }
+
+ public void writeTo(OutputStream outTo) throws IOException {
+ ((AccessibleByteArrayOutputStream) out).writeTo(outTo);
+ }
+
+ /**
+ Get a reference to the data array the class data is being built
+ in. No copy is made.
+ */
+ public byte[] getData() {
+ return ((AccessibleByteArrayOutputStream) out).getInternalByteArray();
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassHolder.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassHolder.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassHolder.java Fri Sep 24 10:33:20 2004
@@ -1,894 +1,894 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Enumeration;
-
-import java.io.IOException;
-import java.util.Vector;
-
-import org.apache.derby.iapi.util.ByteArray;
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Enumeration;
-
-
-/** Based upon "THE class FILE FORMAT" chapter of "The Java Virtual Machine Specification"
- corresponding to version 1.0.2 of the Java Virtual Machine and 1.0.2 of the
- Java Language Specification.
-
- ISBN 0-201-63452-X, September 1996.
- */
-
-public class ClassHolder {
- /**
- IBM Copyright © notice.
- */
-
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
-
- /*
- ** Constants.
- */
-
- /*
- ** Fields
- */
-
- protected int access_flags;
- protected int this_class;
- protected int super_class;
-
- // protected InterfacesArray interfaces; // can be null
- protected int[] interfaces; //can be null
-
- protected MemberTable field_info; // can be null
- protected MemberTable method_info; // can be null
- protected Attributes attribute_info; // can be null
-
- /*
- ** Fields for Constant Pool Table
- */
- protected Hashtable cptHashTable;
- protected Vector cptEntries;
- private int cptEstimatedSize;
-
- /**
- Used to search for index entries to avoid object allocation
- in the case a referecne already exists.
- */
- private final CONSTANT_Index_info searchIndex = new CONSTANT_Index_info(0, 0, 0);
-
- /*
- ** Constructors.
- */
-
- protected ClassHolder(int estimatedConstantPoolCount) {
- // Constant Pool Information
- // 100 is the estimate of the number of entries that will be generated
- cptEntries = new Vector(estimatedConstantPoolCount);
- cptHashTable = new Hashtable(estimatedConstantPoolCount, (float)0.75);
-
- // reserve the 0'th constant pool entry
- cptEntries.setSize(1);
- }
-
-
- /**
- This will not define a constructor -- it is up
- to the caller to add at least one.
- */
-
- public ClassHolder(String fullyQualifiedName, String superClassName,
- int modifiers) {
-
- this(100);
-
- access_flags = modifiers | /* Modifier.SUPER */ 0x0020;
-
- this_class = addClassReference(fullyQualifiedName);
- super_class = addClassReference(superClassName);
- method_info = new MemberTable(0);
- }
-
- public void put(ClassFormatOutput out) throws IOException {
-
- /* Write out the header */
- out.putU4(VMDescriptor.JAVA_CLASS_FORMAT_MAGIC);
- out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MINOR_VERSION);
- out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MAJOR_VERSION);
-
- out.putU2(cptEntries.size());
- cptPut(out);
-
- out.putU2(access_flags);
- out.putU2(this_class);
- out.putU2(super_class);
-
- if (interfaces != null) {
- int ilen = interfaces.length;
- out.putU2(ilen);
- for (int i = 0; i < ilen; i++) {
- out.putU2(interfaces[i]);
- }
- } else {
- out.putU2(0);
- }
-
- if (field_info != null) {
- out.putU2(field_info.size());
- field_info.put(out);
- } else {
- out.putU2(0);
- }
-
- if (method_info != null) {
- out.putU2(method_info.size());
- method_info.put(out);
- } else {
- out.putU2(0);
- }
-
- if (attribute_info != null) {
- out.putU2(attribute_info.size());
- attribute_info.put(out);
- } else {
- out.putU2(0);
- }
-
- }
-
-
- /*
- ** Public methods from ClassHolder.
- */
-
-
- public ByteArray getFileFormat() {
-
- int classFileSize = 4 + (10 * 2);
- classFileSize += cptEstimatedSize;
-
- if (interfaces != null)
- classFileSize += (interfaces.length * 2);
-
- if (field_info != null)
- classFileSize += field_info.classFileSize();
-
- if (method_info != null)
- classFileSize += method_info.classFileSize();
-
- if (attribute_info != null)
- classFileSize += attribute_info.classFileSize();
-
- try {
- ClassFormatOutput cfo = new ClassFormatOutput(classFileSize + 200);
-
- put(cfo);
-
- return new ByteArray(cfo.getData(), 0, cfo.size());
-
- } catch (IOException e) {
- return null;
- }
-
- }
-
- /*
- ** Public methods from ClassMember
- */
-
- /** @see ClassMember
- */
- public int getModifier() { return access_flags; }
-
- /** @see ClassMember
- */
- public String getName() {
- return className(this_class).replace('/', '.');
- }
- /*
- ** Public methods from ClassHolder
- */
-
- /** @see ClassHolder#addMember */
- public ClassMember addMember(String simpleName, String descriptor, int modifier)
- {
- if (SanityManager.DEBUG)
- {
- if (descriptor.startsWith("(")) {
- if (method_info != null) {
- if (method_info.find(simpleName, descriptor) != null) {
- SanityManager.THROWASSERT("Method already exists " + simpleName + " " + descriptor);
- }
- }
-
- } else {
- if (field_info != null) {
- if (field_info.find(simpleName, descriptor) != null) {
- SanityManager.THROWASSERT("Field already exists " + simpleName + " " + descriptor);
- }
- }
- }
- }
-
- CONSTANT_Utf8_info utf = addUtf8Entry(simpleName);
-
- int nameIndex = utf.getIndex();
- int descriptorIndex = addUtf8Entry(descriptor).getIndex();
-
- ClassMember item = new ClassMember(this, modifier, nameIndex, descriptorIndex);
- MemberTable mt;
- if (descriptor.startsWith("(")) {
- mt = method_info;
- if (mt == null)
- mt = method_info = new MemberTable(0);
-
- }
- else {
- mt = field_info;
- if (mt == null)
- mt = field_info = new MemberTable(0);
- }
-
- mt.addEntry(item);
- return item;
- }
-
- /** @see ClassHolder#addFieldReference */
- public int addFieldReference(String className, String simpleName, String descriptor) {
- return addReference(VMDescriptor.CONSTANT_Fieldref, className, simpleName, descriptor);
- }
-
- public int addFieldReference(ClassMember field) {
- return addReference(VMDescriptor.CONSTANT_Fieldref, (ClassMember) field);
- }
-
- /** @see ClassHolder#addMethodReference */
- public int addMethodReference(String className, String simpleName, String descriptor, boolean isInterface) {
-
- int tag = isInterface ? VMDescriptor.CONSTANT_InterfaceMethodref :
- VMDescriptor.CONSTANT_Methodref;
-
- return addReference(tag, className, simpleName, descriptor);
- }
-
- private int addReference(int tag, String className, String simpleName, String descriptor) {
-
- int classIndex = addClassReference(className);
- int nameTypeIndex = addNameAndType(simpleName, descriptor);
-
- return addIndexReference(tag, classIndex, nameTypeIndex);
- }
-
- private int addReference(int tag, ClassMember member) {
-
- int nameTypeIndex = addIndexReference(VMDescriptor.CONSTANT_NameAndType,
- member.name_index, member.descriptor_index);
-
- return addIndexReference(tag, this_class, nameTypeIndex);
- }
-
- /** @see ClassHolder#addConstant */
- public int addConstant(String value) {
-
- return addString(value);
- }
-
- /** @see ClassHolder#addUtf8 */
- public int addUtf8(String value) {
-
- return addUtf8Entry(value).getIndex();
- }
-
-
- /** @see ClassHolder#addInteger */
- public int addConstant(int value) {
- return addDirectEntry(new CONSTANT_Integer_info(value));
- }
-
- /** @see ClassHolder#addFloat */
- public int addConstant(float value) {
- return addDirectEntry(new CONSTANT_Float_info(value));
- }
-
- /** @see ClassHolder#addLong */
- public int addConstant(long value) {
- return addDirectEntry(new CONSTANT_Long_info(value));
- }
-
- /** @see ClassHolder#addDouble */
- public int addConstant(double value) {
- return addDirectEntry(new CONSTANT_Double_info(value));
- }
-
-
- /** @see ClassMember
- */
- public int getConstantPoolIndex() { return this_class; }
-
- public void addAttribute(String attributeName, ClassFormatOutput info) {
-
- if (attribute_info == null)
- attribute_info = new Attributes(1);
-
-
- CONSTANT_Utf8_info autf = addUtf8Entry(attributeName);
-
- int index = autf.getIndex();
-
- attribute_info.addEntry(new AttributeEntry(index, info));
- }
-
-
- public String getSuperClassName() {
- if (super_class == 0)
- return null;
- else
- return className(super_class).replace('/', '.');
- }
-
-
-/*
- public ClassMember getMemberReference(String fullyQualifiedClassName, String simpleName, String descriptor) {
-
- int classIndex;
-
- if (fullyQualifiedClassName == null)
- classIndex = this_class;
- else
- classIndex = constantPool.findClass(fullyQualifiedClassName);
-
- if (classIndex < 0)
- return null;
-
- int nameAndTypeIndex = constantPool.findNameAndType(simpleName, descriptor);
- if (nameAndTypeIndex < 0)
- return null;
-
- return constantPool.findReference(classIndex, nameAndTypeIndex);
- }
-*/
- /*
- ** Public methods from ClassRead
- */
-
-
-
- /*
- ** Implementation specific methods.
- */
-
- /*
- ** Methods related to Constant Pool Table
- */
- /**
- Generic add entry to constant pool. Includes the logic
- for an entry to occupy more than one slot (e.g. long).
-
- @return The number of slots occupied by the entry.
-.
- */
- protected int addEntry(Object key, ConstantPoolEntry item) {
-
- item.setIndex(cptEntries.size());
- if (key != null)
- cptHashTable.put(key, item);
- cptEntries.addElement(item);
-
- cptEstimatedSize += item.classFileSize();
-
- if (item.doubleSlot()) {
- cptEntries.addElement(null);
- return 2;
- } else {
- return 1;
- }
- }
-
- /**
- Add an entry, but only if it doesn't exist.
-
- @return the constant pool index of the added
- or existing item.
- */
- private int addDirectEntry(ConstantPoolEntry item) {
- ConstantPoolEntry existingItem = findMatchingEntry(item);
- if (existingItem != null) {
- item = existingItem;
- //foundCount++;
- }
- else {
- addEntry(item.getKey(), item);
- }
- return item.getIndex();
- }
-
- /**
- Add an index reference.
- */
- private int addIndexReference(int tag, int i1, int i2) {
-
- // search for the item using the pre-allocated object
- searchIndex.set(tag, i1, i2);
-
- ConstantPoolEntry item = findMatchingEntry(searchIndex);
-
- if (item == null) {
- item = new CONSTANT_Index_info(tag, i1, i2);
- addEntry(item.getKey(), item);
- }
-
- return item.getIndex();
- }
-
- /**
- Add a class entry to the pool.
- */
- public int addClassReference(String fullyQualifiedName) {
- if (ClassHolder.isExternalClassName(fullyQualifiedName)) {
- fullyQualifiedName = ClassHolder.convertToInternalClassName(fullyQualifiedName);
- // System.out.println("addClassReference " + fullyQualifiedName);
- }
-
- int name_index = addUtf8Entry(fullyQualifiedName).getIndex();
-
- return addIndexReference(VMDescriptor.CONSTANT_Class, name_index, 0);
- }
-
- /**
- Add a name and type entry
- */
- private int addNameAndType(String name, String descriptor) {
- int nameIndex = addUtf8Entry(name).getIndex();
-
- int descriptorIndex = addUtf8Entry(descriptor).getIndex();
-
- return addIndexReference(VMDescriptor.CONSTANT_NameAndType, nameIndex, descriptorIndex);
- }
-
- /**
- Add a UTF8 into the pool and return the index to it.
- */
- private CONSTANT_Utf8_info addUtf8Entry(String value) {
-
- CONSTANT_Utf8_info item = (CONSTANT_Utf8_info) findMatchingEntry(value);
-
- if (item == null) {
-
- item = new CONSTANT_Utf8_info(value);
- addEntry(value, item);
- }
- return item;
- }
- /**
- Add an extra UTF8 into the pool
- */
- private CONSTANT_Utf8_info addExtraUtf8(String value) {
-
- CONSTANT_Utf8_info item = new CONSTANT_Utf8_info(value);
- addEntry(null, item);
-
- return item;
- }
-
- /**
- Add a string entry
- */
- private int addString(String value) {
- CONSTANT_Utf8_info sutf = addUtf8Entry(value);
- int valueIndex = sutf.setAsString();
- if (valueIndex == 0) {
- // string is already being used as code
- valueIndex = addExtraUtf8(value).getIndex();
- sutf.setAlternative(valueIndex);
- }
-
- return addIndexReference(VMDescriptor.CONSTANT_String, valueIndex, 0);
- }
-
- /**
- Add a string entry
- */
- private int addCodeUtf8(String value) {
- CONSTANT_Utf8_info sutf = addUtf8Entry(value);
- int index = sutf.setAsCode();
- if (index == 0) {
- // code string is already being used as string
- CONSTANT_Utf8_info eutf = addExtraUtf8(value);
- eutf.setAsCode(); // ensure the replace will happen
- index = eutf.getIndex();
- sutf.setAlternative(index);
- }
-
- return index;
- }
- protected void cptPut(ClassFormatOutput out) throws IOException {
-
- for (Enumeration e = cptEntries.elements(); e.hasMoreElements(); ) {
- ConstantPoolEntry item = (ConstantPoolEntry) e.nextElement();
- if (item == null) {
- continue;
- }
-
- item.put(out);
- }
- }
-
- /*
- ** Methods to convert indexes to constant pool entries and vice-versa.
- */
-
- ConstantPoolEntry getEntry(int index) {
- return (ConstantPoolEntry) cptEntries.elementAt(index);
- }
-
- /**
- Return the class name for an index to a CONSTANT_Class_info.
- */
-
- protected String className(int classIndex) {
- CONSTANT_Index_info ci = (CONSTANT_Index_info) getEntry(classIndex);
-
- return nameIndexToString(ci.getI1()).replace('/', '.');
-
- }
-
- /*
- ** Methods to find specific types of constant pool entries.
- In these methods we try to avoid using the ConstantPoolEntry.matchValue()
- as that requires creating a new object for the search. The matchValue()
- call is really intended for when objects are being added to the constant pool.
- */
-
- /**
- Return the index of a UTF entry or -1 if it doesn't exist.
- */
- int findUtf8(String value) {
-
- ConstantPoolEntry item = findMatchingEntry(value);
- if (item == null)
- return -1;
-
- return item.getIndex();
- }
-
- /**
- Find a class descriptor (section 4.4.1) and return its
- index, returns -1 if not found.
- */
- public int findClass(String fullyQualifiedName) {
- String internalName = ClassHolder.convertToInternalClassName(fullyQualifiedName);
- int utf_index = findUtf8(internalName);
- if (utf_index < 0)
- return -1;
-
- return findIndexIndex(VMDescriptor.CONSTANT_Class,
- utf_index, 0);
- }
-
-
- /**
- Find a name and type descriptor (section 4.4.6) and
- return ita index. returns -1 if not found.
- */
- public int findNameAndType(String name, String descriptor) {
-
- int name_index = findUtf8(name);
- if (name_index < 0)
- return -1;
- int descriptor_index = findUtf8(descriptor);
- if (descriptor_index < 0)
- return -1;
-
- return findIndexIndex(VMDescriptor.CONSTANT_NameAndType,
- name_index, descriptor_index);
- }
-/*
- public ClassMember findReference(int classIndex, int nameAndTypeIndex) {
-
- CONSTANT_Index_info item = findIndexEntry(VMDescriptor.CONSTANT_Methodref,
- classIndex, nameAndTypeIndex);
-
- if (item == null) {
-
- item = findIndexEntry(VMDescriptor.CONSTANT_InterfaceMethodref,
- classIndex, nameAndTypeIndex);
-
- if (item == null) {
- item = findIndexEntry(VMDescriptor.CONSTANT_Fieldref,
- classIndex, nameAndTypeIndex);
-
- if (item == null)
- return null;
-
- }
- }
-
- return new ReferenceMember(this, item);
- }
-*/
- protected CONSTANT_Index_info findIndexEntry(int tag, int i1, int i2) {
- // search for the item using the pre-allocated object
- searchIndex.set(tag, i1, i2);
-
- return (CONSTANT_Index_info) findMatchingEntry(searchIndex);
- }
-
- protected int findIndexIndex(int tag, int i1, int i2) {
- CONSTANT_Index_info item = findIndexEntry(tag, i1, i2);
- if (item == null)
- return -1;
-
- return item.getIndex();
- }
-
- protected ConstantPoolEntry findMatchingEntry(Object key) {
- return (ConstantPoolEntry) cptHashTable.get(key);
- }
-
- /** get a string (UTF) given a name_index into the constant pool
- */
- String nameIndexToString(int index) {
-
- return getEntry(index).toString();
- }
-
- /** get the class name of a Class given the index of its CONSTANT_Class_info
- entry in the Constant Pool.
- */
-
- protected String getClassName(int index) {
-
- if (index == 0)
- return ""; // must be the super class of java.lang.Object, ie. nothing.
-
- return nameIndexToString(getEntry(index).getI1());
- }
-
- /*
- * Determine whether the class descriptor string is
- * in external format or not. Assumes that to be in external
- * format means it must have a '.' or end in an ']'.
- *
- * @param className the name of the class to check
- *
- * @return true/false
- */
- public static boolean isExternalClassName(String className)
- {
- int len;
- if (className.indexOf('.') != -1)
- {
- return true;
- }
- else if ((len = className.length()) == 0)
- {
- return false;
- }
- return (className.charAt(len - 1) == ']');
- }
-
- /*
- * Convert a class name to the internal VM class name format.
- See sections 4.3.2, 4.4.1 of the vm spec.
- * The normal leading 'L' and trailing ';' are left
- * off of objects. This is intended primarily for
- * the class manager.
- * <p>
- * An example of a conversion would be java.lang.Double[]
- * to "[Ljava/lang/Double;".
- <BR>
- java.lang.Double would be converted to "java/lang/Double"
-
- <BR>
- Note that for array types the result of convertToInternalClassName()
- and convertToInternalDescriptor() are identical.
-
- *
- * @param the external name (cannot be null)
- *
- * @return the internal string
- */
- public static String convertToInternalClassName(String externalName)
- {
- return convertToInternal(externalName, false);
- }
-
- /*
- * Convert a class name to internal JVM descriptor format.
- See sections 4.3.2 of the vm spec.
- * <p>
- * An example of a conversion would be "java.lang.Double[]"
- * to "[Ljava/lang/Double;".
- *
- <BR>
- java.lang.Double would be converted to "Ljava/lang/Double;"
-
- <BR>
- Note that for array types the result of convertToInternalClassName()
- and convertToInternalDescriptor() are identical.
-
- * @param the external name (cannot be null)
- *
- * @return the internal string
- */
- public static String convertToInternalDescriptor(String externalName)
- {
- return convertToInternal(externalName, true);
- }
-
- /*
- ** Workhorse method. Convert to internal format.
-
- @param descriptor True if converting to descriptor format, false if
- converting to class name format.
- **
- ** Lifted from BCClass.java.
- **
- ** Returns the result string.
- */
- private static String convertToInternal(String externalName, boolean descriptor)
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(externalName != null, "unexpected null");
- }
-
- int len = externalName.length();
-
- String internalName;
- String retVal = null;
- int origLen = len;
- int arity = 0;
-
- // first walk through all array-ness
- if (externalName.charAt(len-1) == ']')
- {
- while (len > 0
- && externalName.charAt(len-1) == ']'
- && externalName.charAt(len-2) == '[')
- {
- len -= 2;
- arity++;
- }
- }
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(len > 0);
- }
-
- internalName = (origLen == len)?
- externalName
- : externalName.substring(0,len);
-
- // then check for primitive types ...
- // in length by expected frequency order
-
- switch (len) {
- case 7 :
- if ("boolean".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_BOOLEAN, arity);
- }
- break;
- case 4 :
- if ("void".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_VOID, arity);
- }
- else if ("long".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_LONG, arity);
- }
- else if ("byte".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_BYTE, arity);
- }
- else if ("char".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_CHAR, arity);
- }
- break;
- case 3 :
- if ("int".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_INT, arity);
- }
- break;
- case 6 :
- if ("double".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_DOUBLE, arity);
- }
- break;
- case 5 :
- if ("short".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_SHORT, arity);
- }
- else if ("float".equals(internalName)) {
- retVal = makeDesc(VMDescriptor.C_FLOAT, arity);
- }
- break;
- }
-
- // then it must be a Java class
- if (retVal == null)
- retVal = makeDesc(internalName, arity, descriptor);
-
- return retVal;
- }
-
- /**
- A helper to build a type description based on a built-in type
- and an array arity.
- */
- static private String makeDesc (char builtin, int arity) {
- if (arity == 0)
- switch (builtin) {
- case VMDescriptor.C_BYTE : return VMDescriptor.BYTE;
- case VMDescriptor.C_CHAR : return VMDescriptor.CHAR;
- case VMDescriptor.C_DOUBLE : return VMDescriptor.DOUBLE;
- case VMDescriptor.C_FLOAT : return VMDescriptor.FLOAT;
- case VMDescriptor.C_INT : return VMDescriptor.INT;
- case VMDescriptor.C_LONG : return VMDescriptor.LONG;
- case VMDescriptor.C_SHORT : return VMDescriptor.SHORT;
- case VMDescriptor.C_BOOLEAN : return VMDescriptor.BOOLEAN;
- case VMDescriptor.C_VOID : return VMDescriptor.VOID;
- default:
- if (SanityManager.DEBUG)
- SanityManager.THROWASSERT("No type match");
- return null;
- }
- else {
- StringBuffer desc = new StringBuffer(arity+3);
-
- for (int i=0;i<arity;i++)
- desc.append(VMDescriptor.C_ARRAY);
-
- desc.append(ClassHolder.makeDesc(builtin, 0));
-
- return desc.toString();
- }
- }
-
- /**
- A helper to build a type description based on a Java class
- and an array arity.
-
- If descriptor is true create a descriptor according to
- section 4.3.2 of the vm spec. If false create a class name
- according to sections 4.3.2 and 4.4.1 of the vm spec.
-
- */
- static private String makeDesc (String className, int arity, boolean descriptor) {
-
- if (!descriptor && (arity == 0)) {
- return className.replace('.','/');
- }
-
- StringBuffer desc = new StringBuffer(arity+2+className.length());
-
- for (int i=0;i<arity;i++)
- desc.append(VMDescriptor.C_ARRAY);
-
- desc.append(VMDescriptor.C_CLASS);
-
- desc.append(className.replace('.','/'));
-
- desc.append(VMDescriptor.C_ENDCLASS);
-
- return desc.toString();
- }
-
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+
+import java.io.IOException;
+import java.util.Vector;
+
+import org.apache.derby.iapi.util.ByteArray;
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+
+
+/** Based upon "THE class FILE FORMAT" chapter of "The Java Virtual Machine Specification"
+ corresponding to version 1.0.2 of the Java Virtual Machine and 1.0.2 of the
+ Java Language Specification.
+
+ ISBN 0-201-63452-X, September 1996.
+ */
+
+public class ClassHolder {
+ /**
+ IBM Copyright © notice.
+ */
+
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+
+ /*
+ ** Constants.
+ */
+
+ /*
+ ** Fields
+ */
+
+ protected int access_flags;
+ protected int this_class;
+ protected int super_class;
+
+ // protected InterfacesArray interfaces; // can be null
+ protected int[] interfaces; //can be null
+
+ protected MemberTable field_info; // can be null
+ protected MemberTable method_info; // can be null
+ protected Attributes attribute_info; // can be null
+
+ /*
+ ** Fields for Constant Pool Table
+ */
+ protected Hashtable cptHashTable;
+ protected Vector cptEntries;
+ private int cptEstimatedSize;
+
+ /**
+ Used to search for index entries to avoid object allocation
+ in the case a referecne already exists.
+ */
+ private final CONSTANT_Index_info searchIndex = new CONSTANT_Index_info(0, 0, 0);
+
+ /*
+ ** Constructors.
+ */
+
+ protected ClassHolder(int estimatedConstantPoolCount) {
+ // Constant Pool Information
+ // 100 is the estimate of the number of entries that will be generated
+ cptEntries = new Vector(estimatedConstantPoolCount);
+ cptHashTable = new Hashtable(estimatedConstantPoolCount, (float)0.75);
+
+ // reserve the 0'th constant pool entry
+ cptEntries.setSize(1);
+ }
+
+
+ /**
+ This will not define a constructor -- it is up
+ to the caller to add at least one.
+ */
+
+ public ClassHolder(String fullyQualifiedName, String superClassName,
+ int modifiers) {
+
+ this(100);
+
+ access_flags = modifiers | /* Modifier.SUPER */ 0x0020;
+
+ this_class = addClassReference(fullyQualifiedName);
+ super_class = addClassReference(superClassName);
+ method_info = new MemberTable(0);
+ }
+
+ public void put(ClassFormatOutput out) throws IOException {
+
+ /* Write out the header */
+ out.putU4(VMDescriptor.JAVA_CLASS_FORMAT_MAGIC);
+ out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MINOR_VERSION);
+ out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MAJOR_VERSION);
+
+ out.putU2(cptEntries.size());
+ cptPut(out);
+
+ out.putU2(access_flags);
+ out.putU2(this_class);
+ out.putU2(super_class);
+
+ if (interfaces != null) {
+ int ilen = interfaces.length;
+ out.putU2(ilen);
+ for (int i = 0; i < ilen; i++) {
+ out.putU2(interfaces[i]);
+ }
+ } else {
+ out.putU2(0);
+ }
+
+ if (field_info != null) {
+ out.putU2(field_info.size());
+ field_info.put(out);
+ } else {
+ out.putU2(0);
+ }
+
+ if (method_info != null) {
+ out.putU2(method_info.size());
+ method_info.put(out);
+ } else {
+ out.putU2(0);
+ }
+
+ if (attribute_info != null) {
+ out.putU2(attribute_info.size());
+ attribute_info.put(out);
+ } else {
+ out.putU2(0);
+ }
+
+ }
+
+
+ /*
+ ** Public methods from ClassHolder.
+ */
+
+
+ public ByteArray getFileFormat() {
+
+ int classFileSize = 4 + (10 * 2);
+ classFileSize += cptEstimatedSize;
+
+ if (interfaces != null)
+ classFileSize += (interfaces.length * 2);
+
+ if (field_info != null)
+ classFileSize += field_info.classFileSize();
+
+ if (method_info != null)
+ classFileSize += method_info.classFileSize();
+
+ if (attribute_info != null)
+ classFileSize += attribute_info.classFileSize();
+
+ try {
+ ClassFormatOutput cfo = new ClassFormatOutput(classFileSize + 200);
+
+ put(cfo);
+
+ return new ByteArray(cfo.getData(), 0, cfo.size());
+
+ } catch (IOException e) {
+ return null;
+ }
+
+ }
+
+ /*
+ ** Public methods from ClassMember
+ */
+
+ /** @see ClassMember
+ */
+ public int getModifier() { return access_flags; }
+
+ /** @see ClassMember
+ */
+ public String getName() {
+ return className(this_class).replace('/', '.');
+ }
+ /*
+ ** Public methods from ClassHolder
+ */
+
+ /** @see ClassHolder#addMember */
+ public ClassMember addMember(String simpleName, String descriptor, int modifier)
+ {
+ if (SanityManager.DEBUG)
+ {
+ if (descriptor.startsWith("(")) {
+ if (method_info != null) {
+ if (method_info.find(simpleName, descriptor) != null) {
+ SanityManager.THROWASSERT("Method already exists " + simpleName + " " + descriptor);
+ }
+ }
+
+ } else {
+ if (field_info != null) {
+ if (field_info.find(simpleName, descriptor) != null) {
+ SanityManager.THROWASSERT("Field already exists " + simpleName + " " + descriptor);
+ }
+ }
+ }
+ }
+
+ CONSTANT_Utf8_info utf = addUtf8Entry(simpleName);
+
+ int nameIndex = utf.getIndex();
+ int descriptorIndex = addUtf8Entry(descriptor).getIndex();
+
+ ClassMember item = new ClassMember(this, modifier, nameIndex, descriptorIndex);
+ MemberTable mt;
+ if (descriptor.startsWith("(")) {
+ mt = method_info;
+ if (mt == null)
+ mt = method_info = new MemberTable(0);
+
+ }
+ else {
+ mt = field_info;
+ if (mt == null)
+ mt = field_info = new MemberTable(0);
+ }
+
+ mt.addEntry(item);
+ return item;
+ }
+
+ /** @see ClassHolder#addFieldReference */
+ public int addFieldReference(String className, String simpleName, String descriptor) {
+ return addReference(VMDescriptor.CONSTANT_Fieldref, className, simpleName, descriptor);
+ }
+
+ public int addFieldReference(ClassMember field) {
+ return addReference(VMDescriptor.CONSTANT_Fieldref, (ClassMember) field);
+ }
+
+ /** @see ClassHolder#addMethodReference */
+ public int addMethodReference(String className, String simpleName, String descriptor, boolean isInterface) {
+
+ int tag = isInterface ? VMDescriptor.CONSTANT_InterfaceMethodref :
+ VMDescriptor.CONSTANT_Methodref;
+
+ return addReference(tag, className, simpleName, descriptor);
+ }
+
+ private int addReference(int tag, String className, String simpleName, String descriptor) {
+
+ int classIndex = addClassReference(className);
+ int nameTypeIndex = addNameAndType(simpleName, descriptor);
+
+ return addIndexReference(tag, classIndex, nameTypeIndex);
+ }
+
+ private int addReference(int tag, ClassMember member) {
+
+ int nameTypeIndex = addIndexReference(VMDescriptor.CONSTANT_NameAndType,
+ member.name_index, member.descriptor_index);
+
+ return addIndexReference(tag, this_class, nameTypeIndex);
+ }
+
+ /** @see ClassHolder#addConstant */
+ public int addConstant(String value) {
+
+ return addString(value);
+ }
+
+ /** @see ClassHolder#addUtf8 */
+ public int addUtf8(String value) {
+
+ return addUtf8Entry(value).getIndex();
+ }
+
+
+ /** @see ClassHolder#addInteger */
+ public int addConstant(int value) {
+ return addDirectEntry(new CONSTANT_Integer_info(value));
+ }
+
+ /** @see ClassHolder#addFloat */
+ public int addConstant(float value) {
+ return addDirectEntry(new CONSTANT_Float_info(value));
+ }
+
+ /** @see ClassHolder#addLong */
+ public int addConstant(long value) {
+ return addDirectEntry(new CONSTANT_Long_info(value));
+ }
+
+ /** @see ClassHolder#addDouble */
+ public int addConstant(double value) {
+ return addDirectEntry(new CONSTANT_Double_info(value));
+ }
+
+
+ /** @see ClassMember
+ */
+ public int getConstantPoolIndex() { return this_class; }
+
+ public void addAttribute(String attributeName, ClassFormatOutput info) {
+
+ if (attribute_info == null)
+ attribute_info = new Attributes(1);
+
+
+ CONSTANT_Utf8_info autf = addUtf8Entry(attributeName);
+
+ int index = autf.getIndex();
+
+ attribute_info.addEntry(new AttributeEntry(index, info));
+ }
+
+
+ public String getSuperClassName() {
+ if (super_class == 0)
+ return null;
+ else
+ return className(super_class).replace('/', '.');
+ }
+
+
+/*
+ public ClassMember getMemberReference(String fullyQualifiedClassName, String simpleName, String descriptor) {
+
+ int classIndex;
+
+ if (fullyQualifiedClassName == null)
+ classIndex = this_class;
+ else
+ classIndex = constantPool.findClass(fullyQualifiedClassName);
+
+ if (classIndex < 0)
+ return null;
+
+ int nameAndTypeIndex = constantPool.findNameAndType(simpleName, descriptor);
+ if (nameAndTypeIndex < 0)
+ return null;
+
+ return constantPool.findReference(classIndex, nameAndTypeIndex);
+ }
+*/
+ /*
+ ** Public methods from ClassRead
+ */
+
+
+
+ /*
+ ** Implementation specific methods.
+ */
+
+ /*
+ ** Methods related to Constant Pool Table
+ */
+ /**
+ Generic add entry to constant pool. Includes the logic
+ for an entry to occupy more than one slot (e.g. long).
+
+ @return The number of slots occupied by the entry.
+.
+ */
+ protected int addEntry(Object key, ConstantPoolEntry item) {
+
+ item.setIndex(cptEntries.size());
+ if (key != null)
+ cptHashTable.put(key, item);
+ cptEntries.addElement(item);
+
+ cptEstimatedSize += item.classFileSize();
+
+ if (item.doubleSlot()) {
+ cptEntries.addElement(null);
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ Add an entry, but only if it doesn't exist.
+
+ @return the constant pool index of the added
+ or existing item.
+ */
+ private int addDirectEntry(ConstantPoolEntry item) {
+ ConstantPoolEntry existingItem = findMatchingEntry(item);
+ if (existingItem != null) {
+ item = existingItem;
+ //foundCount++;
+ }
+ else {
+ addEntry(item.getKey(), item);
+ }
+ return item.getIndex();
+ }
+
+ /**
+ Add an index reference.
+ */
+ private int addIndexReference(int tag, int i1, int i2) {
+
+ // search for the item using the pre-allocated object
+ searchIndex.set(tag, i1, i2);
+
+ ConstantPoolEntry item = findMatchingEntry(searchIndex);
+
+ if (item == null) {
+ item = new CONSTANT_Index_info(tag, i1, i2);
+ addEntry(item.getKey(), item);
+ }
+
+ return item.getIndex();
+ }
+
+ /**
+ Add a class entry to the pool.
+ */
+ public int addClassReference(String fullyQualifiedName) {
+ if (ClassHolder.isExternalClassName(fullyQualifiedName)) {
+ fullyQualifiedName = ClassHolder.convertToInternalClassName(fullyQualifiedName);
+ // System.out.println("addClassReference " + fullyQualifiedName);
+ }
+
+ int name_index = addUtf8Entry(fullyQualifiedName).getIndex();
+
+ return addIndexReference(VMDescriptor.CONSTANT_Class, name_index, 0);
+ }
+
+ /**
+ Add a name and type entry
+ */
+ private int addNameAndType(String name, String descriptor) {
+ int nameIndex = addUtf8Entry(name).getIndex();
+
+ int descriptorIndex = addUtf8Entry(descriptor).getIndex();
+
+ return addIndexReference(VMDescriptor.CONSTANT_NameAndType, nameIndex, descriptorIndex);
+ }
+
+ /**
+ Add a UTF8 into the pool and return the index to it.
+ */
+ private CONSTANT_Utf8_info addUtf8Entry(String value) {
+
+ CONSTANT_Utf8_info item = (CONSTANT_Utf8_info) findMatchingEntry(value);
+
+ if (item == null) {
+
+ item = new CONSTANT_Utf8_info(value);
+ addEntry(value, item);
+ }
+ return item;
+ }
+ /**
+ Add an extra UTF8 into the pool
+ */
+ private CONSTANT_Utf8_info addExtraUtf8(String value) {
+
+ CONSTANT_Utf8_info item = new CONSTANT_Utf8_info(value);
+ addEntry(null, item);
+
+ return item;
+ }
+
+ /**
+ Add a string entry
+ */
+ private int addString(String value) {
+ CONSTANT_Utf8_info sutf = addUtf8Entry(value);
+ int valueIndex = sutf.setAsString();
+ if (valueIndex == 0) {
+ // string is already being used as code
+ valueIndex = addExtraUtf8(value).getIndex();
+ sutf.setAlternative(valueIndex);
+ }
+
+ return addIndexReference(VMDescriptor.CONSTANT_String, valueIndex, 0);
+ }
+
+ /**
+ Add a string entry
+ */
+ private int addCodeUtf8(String value) {
+ CONSTANT_Utf8_info sutf = addUtf8Entry(value);
+ int index = sutf.setAsCode();
+ if (index == 0) {
+ // code string is already being used as string
+ CONSTANT_Utf8_info eutf = addExtraUtf8(value);
+ eutf.setAsCode(); // ensure the replace will happen
+ index = eutf.getIndex();
+ sutf.setAlternative(index);
+ }
+
+ return index;
+ }
+ protected void cptPut(ClassFormatOutput out) throws IOException {
+
+ for (Enumeration e = cptEntries.elements(); e.hasMoreElements(); ) {
+ ConstantPoolEntry item = (ConstantPoolEntry) e.nextElement();
+ if (item == null) {
+ continue;
+ }
+
+ item.put(out);
+ }
+ }
+
+ /*
+ ** Methods to convert indexes to constant pool entries and vice-versa.
+ */
+
+ ConstantPoolEntry getEntry(int index) {
+ return (ConstantPoolEntry) cptEntries.elementAt(index);
+ }
+
+ /**
+ Return the class name for an index to a CONSTANT_Class_info.
+ */
+
+ protected String className(int classIndex) {
+ CONSTANT_Index_info ci = (CONSTANT_Index_info) getEntry(classIndex);
+
+ return nameIndexToString(ci.getI1()).replace('/', '.');
+
+ }
+
+ /*
+ ** Methods to find specific types of constant pool entries.
+ In these methods we try to avoid using the ConstantPoolEntry.matchValue()
+ as that requires creating a new object for the search. The matchValue()
+ call is really intended for when objects are being added to the constant pool.
+ */
+
+ /**
+ Return the index of a UTF entry or -1 if it doesn't exist.
+ */
+ int findUtf8(String value) {
+
+ ConstantPoolEntry item = findMatchingEntry(value);
+ if (item == null)
+ return -1;
+
+ return item.getIndex();
+ }
+
+ /**
+ Find a class descriptor (section 4.4.1) and return its
+ index, returns -1 if not found.
+ */
+ public int findClass(String fullyQualifiedName) {
+ String internalName = ClassHolder.convertToInternalClassName(fullyQualifiedName);
+ int utf_index = findUtf8(internalName);
+ if (utf_index < 0)
+ return -1;
+
+ return findIndexIndex(VMDescriptor.CONSTANT_Class,
+ utf_index, 0);
+ }
+
+
+ /**
+ Find a name and type descriptor (section 4.4.6) and
+ return ita index. returns -1 if not found.
+ */
+ public int findNameAndType(String name, String descriptor) {
+
+ int name_index = findUtf8(name);
+ if (name_index < 0)
+ return -1;
+ int descriptor_index = findUtf8(descriptor);
+ if (descriptor_index < 0)
+ return -1;
+
+ return findIndexIndex(VMDescriptor.CONSTANT_NameAndType,
+ name_index, descriptor_index);
+ }
+/*
+ public ClassMember findReference(int classIndex, int nameAndTypeIndex) {
+
+ CONSTANT_Index_info item = findIndexEntry(VMDescriptor.CONSTANT_Methodref,
+ classIndex, nameAndTypeIndex);
+
+ if (item == null) {
+
+ item = findIndexEntry(VMDescriptor.CONSTANT_InterfaceMethodref,
+ classIndex, nameAndTypeIndex);
+
+ if (item == null) {
+ item = findIndexEntry(VMDescriptor.CONSTANT_Fieldref,
+ classIndex, nameAndTypeIndex);
+
+ if (item == null)
+ return null;
+
+ }
+ }
+
+ return new ReferenceMember(this, item);
+ }
+*/
+ protected CONSTANT_Index_info findIndexEntry(int tag, int i1, int i2) {
+ // search for the item using the pre-allocated object
+ searchIndex.set(tag, i1, i2);
+
+ return (CONSTANT_Index_info) findMatchingEntry(searchIndex);
+ }
+
+ protected int findIndexIndex(int tag, int i1, int i2) {
+ CONSTANT_Index_info item = findIndexEntry(tag, i1, i2);
+ if (item == null)
+ return -1;
+
+ return item.getIndex();
+ }
+
+ protected ConstantPoolEntry findMatchingEntry(Object key) {
+ return (ConstantPoolEntry) cptHashTable.get(key);
+ }
+
+ /** get a string (UTF) given a name_index into the constant pool
+ */
+ String nameIndexToString(int index) {
+
+ return getEntry(index).toString();
+ }
+
+ /** get the class name of a Class given the index of its CONSTANT_Class_info
+ entry in the Constant Pool.
+ */
+
+ protected String getClassName(int index) {
+
+ if (index == 0)
+ return ""; // must be the super class of java.lang.Object, ie. nothing.
+
+ return nameIndexToString(getEntry(index).getI1());
+ }
+
+ /*
+ * Determine whether the class descriptor string is
+ * in external format or not. Assumes that to be in external
+ * format means it must have a '.' or end in an ']'.
+ *
+ * @param className the name of the class to check
+ *
+ * @return true/false
+ */
+ public static boolean isExternalClassName(String className)
+ {
+ int len;
+ if (className.indexOf('.') != -1)
+ {
+ return true;
+ }
+ else if ((len = className.length()) == 0)
+ {
+ return false;
+ }
+ return (className.charAt(len - 1) == ']');
+ }
+
+ /*
+ * Convert a class name to the internal VM class name format.
+ See sections 4.3.2, 4.4.1 of the vm spec.
+ * The normal leading 'L' and trailing ';' are left
+ * off of objects. This is intended primarily for
+ * the class manager.
+ * <p>
+ * An example of a conversion would be java.lang.Double[]
+ * to "[Ljava/lang/Double;".
+ <BR>
+ java.lang.Double would be converted to "java/lang/Double"
+
+ <BR>
+ Note that for array types the result of convertToInternalClassName()
+ and convertToInternalDescriptor() are identical.
+
+ *
+ * @param the external name (cannot be null)
+ *
+ * @return the internal string
+ */
+ public static String convertToInternalClassName(String externalName)
+ {
+ return convertToInternal(externalName, false);
+ }
+
+ /*
+ * Convert a class name to internal JVM descriptor format.
+ See sections 4.3.2 of the vm spec.
+ * <p>
+ * An example of a conversion would be "java.lang.Double[]"
+ * to "[Ljava/lang/Double;".
+ *
+ <BR>
+ java.lang.Double would be converted to "Ljava/lang/Double;"
+
+ <BR>
+ Note that for array types the result of convertToInternalClassName()
+ and convertToInternalDescriptor() are identical.
+
+ * @param the external name (cannot be null)
+ *
+ * @return the internal string
+ */
+ public static String convertToInternalDescriptor(String externalName)
+ {
+ return convertToInternal(externalName, true);
+ }
+
+ /*
+ ** Workhorse method. Convert to internal format.
+
+ @param descriptor True if converting to descriptor format, false if
+ converting to class name format.
+ **
+ ** Lifted from BCClass.java.
+ **
+ ** Returns the result string.
+ */
+ private static String convertToInternal(String externalName, boolean descriptor)
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(externalName != null, "unexpected null");
+ }
+
+ int len = externalName.length();
+
+ String internalName;
+ String retVal = null;
+ int origLen = len;
+ int arity = 0;
+
+ // first walk through all array-ness
+ if (externalName.charAt(len-1) == ']')
+ {
+ while (len > 0
+ && externalName.charAt(len-1) == ']'
+ && externalName.charAt(len-2) == '[')
+ {
+ len -= 2;
+ arity++;
+ }
+ }
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(len > 0);
+ }
+
+ internalName = (origLen == len)?
+ externalName
+ : externalName.substring(0,len);
+
+ // then check for primitive types ...
+ // in length by expected frequency order
+
+ switch (len) {
+ case 7 :
+ if ("boolean".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_BOOLEAN, arity);
+ }
+ break;
+ case 4 :
+ if ("void".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_VOID, arity);
+ }
+ else if ("long".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_LONG, arity);
+ }
+ else if ("byte".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_BYTE, arity);
+ }
+ else if ("char".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_CHAR, arity);
+ }
+ break;
+ case 3 :
+ if ("int".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_INT, arity);
+ }
+ break;
+ case 6 :
+ if ("double".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_DOUBLE, arity);
+ }
+ break;
+ case 5 :
+ if ("short".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_SHORT, arity);
+ }
+ else if ("float".equals(internalName)) {
+ retVal = makeDesc(VMDescriptor.C_FLOAT, arity);
+ }
+ break;
+ }
+
+ // then it must be a Java class
+ if (retVal == null)
+ retVal = makeDesc(internalName, arity, descriptor);
+
+ return retVal;
+ }
+
+ /**
+ A helper to build a type description based on a built-in type
+ and an array arity.
+ */
+ static private String makeDesc (char builtin, int arity) {
+ if (arity == 0)
+ switch (builtin) {
+ case VMDescriptor.C_BYTE : return VMDescriptor.BYTE;
+ case VMDescriptor.C_CHAR : return VMDescriptor.CHAR;
+ case VMDescriptor.C_DOUBLE : return VMDescriptor.DOUBLE;
+ case VMDescriptor.C_FLOAT : return VMDescriptor.FLOAT;
+ case VMDescriptor.C_INT : return VMDescriptor.INT;
+ case VMDescriptor.C_LONG : return VMDescriptor.LONG;
+ case VMDescriptor.C_SHORT : return VMDescriptor.SHORT;
+ case VMDescriptor.C_BOOLEAN : return VMDescriptor.BOOLEAN;
+ case VMDescriptor.C_VOID : return VMDescriptor.VOID;
+ default:
+ if (SanityManager.DEBUG)
+ SanityManager.THROWASSERT("No type match");
+ return null;
+ }
+ else {
+ StringBuffer desc = new StringBuffer(arity+3);
+
+ for (int i=0;i<arity;i++)
+ desc.append(VMDescriptor.C_ARRAY);
+
+ desc.append(ClassHolder.makeDesc(builtin, 0));
+
+ return desc.toString();
+ }
+ }
+
+ /**
+ A helper to build a type description based on a Java class
+ and an array arity.
+
+ If descriptor is true create a descriptor according to
+ section 4.3.2 of the vm spec. If false create a class name
+ according to sections 4.3.2 and 4.4.1 of the vm spec.
+
+ */
+ static private String makeDesc (String className, int arity, boolean descriptor) {
+
+ if (!descriptor && (arity == 0)) {
+ return className.replace('.','/');
+ }
+
+ StringBuffer desc = new StringBuffer(arity+2+className.length());
+
+ for (int i=0;i<arity;i++)
+ desc.append(VMDescriptor.C_ARRAY);
+
+ desc.append(VMDescriptor.C_CLASS);
+
+ desc.append(className.replace('.','/'));
+
+ desc.append(VMDescriptor.C_ENDCLASS);
+
+ return desc.toString();
+ }
+
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInput.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInput.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInput.java Fri Sep 24 10:33:20 2004
@@ -1,43 +1,43 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import java.io.InputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-
-
-/** A wrapper around DataInputStream to provide input functions in terms
- of the types defined on pages 83.
- */
-
-class ClassInput extends DataInputStream {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
- ClassInput(InputStream in) {
- super(in);
- }
-
- int getU2() throws IOException {
- return readUnsignedShort();
- }
- int getU4() throws IOException {
- return readInt();
- }
- byte[] getU1Array(int count) throws IOException {
- byte[] b = new byte[count];
- readFully(b);
- return b;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import java.io.InputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+
+/** A wrapper around DataInputStream to provide input functions in terms
+ of the types defined on pages 83.
+ */
+
+class ClassInput extends DataInputStream {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+ ClassInput(InputStream in) {
+ super(in);
+ }
+
+ int getU2() throws IOException {
+ return readUnsignedShort();
+ }
+ int getU4() throws IOException {
+ return readInt();
+ }
+ byte[] getU1Array(int count) throws IOException {
+ byte[] b = new byte[count];
+ readFully(b);
+ return b;
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInvestigator.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInvestigator.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassInvestigator.java Fri Sep 24 10:33:20 2004
@@ -1,582 +1,582 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2001, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-
-import java.io.InputStream;
-import java.util.Enumeration;
-
-import java.io.IOException;
-import java.util.Vector;
-
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-import java.util.HashSet;
-
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Enumeration;
-import java.util.Collections;
-
-
-/**
-*/
-
-public class ClassInvestigator extends ClassHolder {
- /**
- IBM Copyright © notice.
- */
-
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2001_2004;
-
- public static ClassInvestigator load(InputStream is)
- throws IOException {
-
- ClassInput classInput = new ClassInput(is);
-
- // Check the header
- checkHeader(classInput);
-
- // Read in the Constant Pool
- int constantPoolCount = classInput.getU2();
-
- ClassInvestigator ci = new ClassInvestigator(constantPoolCount);
- // Yes, index starts at 1, The '0'th constant pool entry
- // is reserved for the JVM and is not present in the class file.
- for (int i = 1; i < constantPoolCount; ) {
- ConstantPoolEntry item = ClassInvestigator.getConstant(classInput);
- i += ci.addEntry(item.getKey(), item);
- }
-
- // Read in access_flags and class indexes
- ci.access_flags = classInput.getU2();
- ci.this_class = classInput.getU2();
- ci.super_class = classInput.getU2();
-
- // interfaces is a simple int array
- int interfaceCount = classInput.getU2();
- if (interfaceCount != 0) {
- ci.interfaces = new int[interfaceCount];
- for (int i = 0; i < interfaceCount; i++)
- ci.interfaces[i] = classInput.getU2();
- }
-
- int fieldCount = classInput.getU2();
- if (fieldCount != 0) {
- ci.field_info = new MemberTable(fieldCount);
- for (int i = 0; i < fieldCount; i++)
- {
- ci.field_info.addEntry(readClassMember(ci, classInput));
- }
- }
-
- int methodCount = classInput.getU2();
- if (methodCount != 0) {
- ci.method_info = new MemberTable(methodCount);
- for (int i = 0; i < methodCount; i++)
- {
- ci.method_info.addEntry(readClassMember(ci, classInput));
- }
- }
-
- int attributeCount = classInput.getU2();
- if (attributeCount != 0) {
- ci.attribute_info = new Attributes(attributeCount);
-
- for (int i = 0; i < attributeCount; i++)
- ci.attribute_info.addEntry(new AttributeEntry(classInput));
- }
- return ci;
-
- }
-
- private static ClassMember readClassMember(ClassInvestigator ci, ClassInput in)
- throws IOException {
-
- ClassMember member = new ClassMember(ci, in.getU2(), in.getU2(), in.getU2());
-
- int attributeCount = in.getU2();
- if (attributeCount != 0) {
- member.attribute_info = new Attributes(attributeCount);
- for (int i = 0; i < attributeCount; i++)
- member.attribute_info.addEntry(new AttributeEntry(in));
- }
-
- return member;
- }
-
- /*
- ** Constructors.
- */
-
- private ClassInvestigator(int constantPoolCount) {
- super(constantPoolCount);
- }
-
- /*
- ** Methods to investigate this class
- */
-
-
- public Enumeration implementedInterfaces()
- {
- int interfaceCount = interfaces == null ? 0 : interfaces.length;
- Vector implemented = new Vector(interfaceCount);
-
- for (int i = 0; i < interfaceCount; i++)
- {
- implemented.addElement(className(interfaces[i]));
- }
- return implemented.elements();
- }
- public Enumeration getFields() {
- if (field_info == null)
- return Collections.enumeration(Collections.EMPTY_LIST);
-
- return field_info.entries.elements();
- }
-
- public Enumeration getMethods() {
- if (method_info == null)
- return Collections.enumeration(Collections.EMPTY_LIST);
- return method_info.entries.elements();
- }
-
- public Enumeration referencedClasses() {
- return getClasses(getMethods(), getFields() );
- }
-
- /**
- Return an Enumeration of all referenced classes
- */
-
- private Enumeration getClasses(Enumeration methods, Enumeration fields)
- {
- return new ClassEnumeration(this, cptEntries.elements(), methods, fields);
- }
-
- public Enumeration getStrings() {
- HashSet strings = new HashSet(30, 0.8f);
-
- int size = cptEntries.size();
- for (int i = 1; i < size; i++) {
- ConstantPoolEntry cpe = getEntry(i);
-
- if ((cpe == null) || (cpe.getTag() != VMDescriptor.CONSTANT_String))
- continue;
-
- CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
-
- strings.add(nameIndexToString(cii.getI1()));
- }
-
- return java.util.Collections.enumeration(strings);
- }
-
- public ClassMember getMember(String simpleName, String descriptor) {
-
- if (descriptor.startsWith("(")) {
- if (method_info == null)
- return null;
- return method_info.find(simpleName, descriptor);
- }
- else {
- if (field_info == null)
- return null;
- return field_info.find(simpleName, descriptor);
- }
- }
-
- /**
- Return an Enumeration of all Member References
- */
-/*
- Enumeration getMemberReferences() {
- return new ReferenceEnumeration(this, elements());
- }
-*/
-
- /*
- ** Methods to modify the class.
- */
- // remove all atttributes that are not essential
- public void removeAttributes() throws IOException {
-
- // Class level attributes
- if (attribute_info != null) {
- for (int i = attribute_info.size() - 1; i >= 0 ; i--) {
-
- AttributeEntry ae = (AttributeEntry) attribute_info.elementAt(i);
- String name = nameIndexToString(ae.getNameIndex());
- if (name.equals("SourceFile"))
- attribute_info.removeElementAt(i);
- else if (name.equals("InnerClasses"))
- ; // leave in
- else
- System.err.println("WARNING - Unknown Class File attribute " + name);
- }
-
- if (attribute_info.size() == 0)
- attribute_info = null;
- }
- attribute_info = null;
-
- // fields
- for (Enumeration e = getFields(); e.hasMoreElements(); ) {
- ClassMember member = (ClassMember) e.nextElement();
-
- Attributes attrs = member.attribute_info;
-
- if (attrs != null) {
-
- for (int i = attrs.size() - 1; i >= 0 ; i--) {
-
- AttributeEntry ae = (AttributeEntry) attrs.elementAt(i);
- String name = nameIndexToString(ae.getNameIndex());
- if (name.equals("ConstantValue"))
- ; // leave in
- else if (name.equals("Synthetic"))
- ; // leave in
- else
- System.err.println("WARNING - Unknown Field attribute " + name);
- }
-
- if (attrs.size() == 0)
- member.attribute_info = null;
- }
-
- }
-
- // methods
- for (Enumeration e = getMethods(); e.hasMoreElements(); ) {
- ClassMember member = (ClassMember) e.nextElement();
-
- Attributes attrs = member.attribute_info;
-
- if (attrs != null) {
-
- for (int i = attrs.size() - 1; i >= 0 ; i--) {
-
- AttributeEntry ae = (AttributeEntry) attrs.elementAt(i);
- String name = nameIndexToString(ae.getNameIndex());
- if (name.equals("Code"))
- processCodeAttribute(member, ae);
- else if (name.equals("Exceptions"))
- ; // leave in
- else if (name.equals("Deprecated"))
- ; // leave in
- else if (name.equals("Synthetic"))
- ; // leave in
- else
- System.err.println("WARNING - Unknown method attribute " + name);
- }
-
- if (attrs.size() == 0)
- member.attribute_info = null;
- }
-
- }
- }
-
- private void processCodeAttribute(ClassMember member, AttributeEntry ae) throws IOException {
-
- ClassInput ci = new ClassInput(new java.io.ByteArrayInputStream(ae.infoIn));
-
-
- ci.skipBytes(4); // puts us at code_length
- int len = ci.getU4();
- ci.skipBytes(len); // puts us at exception_table_length
- int count = ci.getU2();
- if (count != 0)
- ci.skipBytes(8 * count);
-
- int nonAttrLength = 4 + 4 + len + 2 + (8 * count);
-
- // now at attributes
-
- count = ci.getU2();
- if (count == 0)
- return;
-
- int newCount = count;
- for (int i = 0; i < count; i++) {
-
- int nameIndex = ci.getU2();
- String name = nameIndexToString(nameIndex);
- if (name.equals("LineNumberTable") || name.equals("LocalVariableTable"))
- newCount--;
- else
- System.err.println("ERROR - Unknown code attribute " + name);
-
- len = ci.getU4();
- ci.skipBytes(len);
- }
-
- if (newCount != 0) {
- System.err.println("ERROR - expecting all code attributes to be removed");
- System.exit(1);
- }
-
- // this is only coded for all attributes within a Code attribute being removed.
-
- byte[] newInfo = new byte[nonAttrLength + 2];
- System.arraycopy(ae.infoIn, 0, newInfo, 0, nonAttrLength);
- // last two bytes are left at 0 which means 0 attributes
- ae.infoIn = newInfo;
- }
-
- public void renameClassElements(Hashtable classNameMap, Hashtable memberNameMap) {
-
- // this & super class
- renameString(classNameMap, (CONSTANT_Index_info) getEntry(this_class));
- renameString(classNameMap, (CONSTANT_Index_info) getEntry(super_class));
-
- // implemented interfaces
- // handled by Class entries below
-
- // classes & Strings
- // descriptors
- int size = cptEntries.size();
- for (int i = 1; i < size; i++) {
- ConstantPoolEntry cpe = getEntry(i);
-
- if (cpe == null)
- continue;
-
- switch (cpe.getTag()) {
- case VMDescriptor.CONSTANT_String:
- case VMDescriptor.CONSTANT_Class:
- {
- CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
- renameString(classNameMap, cii);
- break;
- }
- case VMDescriptor.CONSTANT_NameAndType:
- {
- CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
- String newDescriptor = newDescriptor(classNameMap, nameIndexToString(cii.getI2()));
- if (newDescriptor != null) {
- doRenameString(cii.getI2(), newDescriptor);
- }
- break;
- }
-
- default:
- continue;
- }
-
- }
-
- //System.out.println("Starting Fields");
-
- // now the methods & fields, only descriptors at this time
- renameMembers(getFields(), classNameMap, memberNameMap);
-
- renameMembers(getMethods(), classNameMap, memberNameMap);
- }
-
- private void renameMembers(Enumeration e, Hashtable classNameMap, Hashtable memberNameMap) {
-
- for (; e.hasMoreElements(); ) {
- ClassMember member = (ClassMember) e.nextElement();
-
- String oldMemberName = nameIndexToString(member.name_index);
- String newMemberName = (String) memberNameMap.get(oldMemberName);
- if (newMemberName != null)
- doRenameString(member.name_index, newMemberName);
-
- String newDescriptor = newDescriptor(classNameMap, nameIndexToString(member.descriptor_index));
- if (newDescriptor != null) {
- doRenameString(member.descriptor_index, newDescriptor);
- }
- }
-
- }
-
- private void renameString(Hashtable classNameMap, CONSTANT_Index_info cii) {
-
- int index = cii.getI1();
-
- String name = nameIndexToString(index);
- String newName = (String) classNameMap.get(name);
- if (newName != null) {
-
- doRenameString(index, newName);
-
- return;
- }
-
- // have to look for arrays
- if (cii.getTag() == VMDescriptor.CONSTANT_Class) {
-
- if (name.charAt(0) == '[') {
- int classOffset = name.indexOf('L') + 1;
-
- String baseClassName = name.substring(classOffset, name.length() - 1);
-
-
- newName = (String) classNameMap.get(baseClassName);
-
- if (newName != null) {
-
- String newArrayClassName = name.substring(0, classOffset) + newName + ";";
-
- doRenameString(index, newArrayClassName);
-
- }
-
- }
- }
- }
-
- private void doRenameString(int index, String newName) {
- ConstantPoolEntry cpe = getEntry(index);
- if (cpe.getTag() != VMDescriptor.CONSTANT_Utf8)
- throw new RuntimeException("unexpected type " + cpe);
-
- CONSTANT_Utf8_info newCpe = new CONSTANT_Utf8_info(newName);
-
- cptHashTable.remove(cpe.getKey());
- cptHashTable.put(cpe.getKey(), cpe);
-
- newCpe.index = index;
-
- cptEntries.setElementAt(newCpe, index);
- }
-
- /*
- **
- */
- static private void checkHeader(ClassInput in) throws IOException {
- int magic = in.getU4();
- int minor_version = in.getU2();
- int major_version = in.getU2();
-
-
- if (magic != VMDescriptor.JAVA_CLASS_FORMAT_MAGIC)
- throw new ClassFormatError();
- }
- private static ConstantPoolEntry getConstant(ClassInput in)
- throws IOException {
-
- ConstantPoolEntry item;
- int tag;
- tag = in.readUnsignedByte();
-
- switch (tag) {
- case VMDescriptor.CONSTANT_Class:
- case VMDescriptor.CONSTANT_String:
- item = new CONSTANT_Index_info(tag, in.getU2(), 0);
- break;
-
- case VMDescriptor.CONSTANT_NameAndType:
- case VMDescriptor.CONSTANT_Fieldref:
- case VMDescriptor.CONSTANT_Methodref:
- case VMDescriptor.CONSTANT_InterfaceMethodref:
- item = new CONSTANT_Index_info(tag, in.getU2(), in.getU2());
- break;
-
- case VMDescriptor.CONSTANT_Integer:
- item = new CONSTANT_Integer_info(in.getU4());
- break;
-
- case VMDescriptor.CONSTANT_Float:
- item = new CONSTANT_Float_info(in.readFloat());
- break;
-
- case VMDescriptor.CONSTANT_Long:
- item = new CONSTANT_Long_info(in.readLong());
- break;
-
- case VMDescriptor.CONSTANT_Double:
- item = new CONSTANT_Double_info(in.readDouble());
- break;
-
- case VMDescriptor.CONSTANT_Utf8:
- item = new CONSTANT_Utf8_info(in.readUTF());
- break;
- default:
- throw new ClassFormatError();
- }
-
- return item;
- }
- public static String newDescriptor(Hashtable classNameMap, String descriptor) {
-
- String newDescriptor = null;
-
- int dlen = descriptor.length();
- for (int offset = 0; offset < dlen; ) {
- char c = descriptor.charAt(offset);
- switch (c) {
- case VMDescriptor.C_VOID :
- case VMDescriptor.C_BOOLEAN:
- case VMDescriptor.C_BYTE:
- case VMDescriptor.C_CHAR:
- case VMDescriptor.C_SHORT:
- case VMDescriptor.C_INT:
- case VMDescriptor.C_LONG:
- case VMDescriptor.C_FLOAT:
- case VMDescriptor.C_DOUBLE:
- case VMDescriptor.C_ARRAY:
- case VMDescriptor.C_METHOD:
- case VMDescriptor.C_ENDMETHOD:
- default:
- offset++;
- continue;
-
- case VMDescriptor.C_CLASS:
- {
- int startOffset = offset;
- while (descriptor.charAt(offset++) != VMDescriptor.C_ENDCLASS)
- ;
- int endOffset = offset;
-
- // name includes L and ;
- String name = descriptor.substring(startOffset, endOffset);
- String newName = (String) classNameMap.get(name);
- if (newName != null) {
- if (newDescriptor == null)
- newDescriptor = descriptor;
-
- // we just replace the first occurance of it,
- // the loop will hit any next occurance.
- int startPos = newDescriptor.indexOf(name);
-
- String tmp;
- if (startPos == 0)
- tmp = newName;
- else
- tmp = newDescriptor.substring(0, startPos) +
- newName;
-
- int endPos = startPos + name.length();
-
- if (endPos < newDescriptor.length()) {
-
- tmp += newDescriptor.substring(endPos , newDescriptor.length());
- }
-
-
- newDescriptor = tmp;
- }
- }
- }
-
-
- }
- //if (newDescriptor != null) {
- // System.out.println("O - " + descriptor);
- // System.out.println("N - " + newDescriptor);
- //}
- return newDescriptor;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2001, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+
+import java.io.InputStream;
+import java.util.Enumeration;
+
+import java.io.IOException;
+import java.util.Vector;
+
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+import java.util.HashSet;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Collections;
+
+
+/**
+*/
+
+public class ClassInvestigator extends ClassHolder {
+ /**
+ IBM Copyright © notice.
+ */
+
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2001_2004;
+
+ public static ClassInvestigator load(InputStream is)
+ throws IOException {
+
+ ClassInput classInput = new ClassInput(is);
+
+ // Check the header
+ checkHeader(classInput);
+
+ // Read in the Constant Pool
+ int constantPoolCount = classInput.getU2();
+
+ ClassInvestigator ci = new ClassInvestigator(constantPoolCount);
+ // Yes, index starts at 1, The '0'th constant pool entry
+ // is reserved for the JVM and is not present in the class file.
+ for (int i = 1; i < constantPoolCount; ) {
+ ConstantPoolEntry item = ClassInvestigator.getConstant(classInput);
+ i += ci.addEntry(item.getKey(), item);
+ }
+
+ // Read in access_flags and class indexes
+ ci.access_flags = classInput.getU2();
+ ci.this_class = classInput.getU2();
+ ci.super_class = classInput.getU2();
+
+ // interfaces is a simple int array
+ int interfaceCount = classInput.getU2();
+ if (interfaceCount != 0) {
+ ci.interfaces = new int[interfaceCount];
+ for (int i = 0; i < interfaceCount; i++)
+ ci.interfaces[i] = classInput.getU2();
+ }
+
+ int fieldCount = classInput.getU2();
+ if (fieldCount != 0) {
+ ci.field_info = new MemberTable(fieldCount);
+ for (int i = 0; i < fieldCount; i++)
+ {
+ ci.field_info.addEntry(readClassMember(ci, classInput));
+ }
+ }
+
+ int methodCount = classInput.getU2();
+ if (methodCount != 0) {
+ ci.method_info = new MemberTable(methodCount);
+ for (int i = 0; i < methodCount; i++)
+ {
+ ci.method_info.addEntry(readClassMember(ci, classInput));
+ }
+ }
+
+ int attributeCount = classInput.getU2();
+ if (attributeCount != 0) {
+ ci.attribute_info = new Attributes(attributeCount);
+
+ for (int i = 0; i < attributeCount; i++)
+ ci.attribute_info.addEntry(new AttributeEntry(classInput));
+ }
+ return ci;
+
+ }
+
+ private static ClassMember readClassMember(ClassInvestigator ci, ClassInput in)
+ throws IOException {
+
+ ClassMember member = new ClassMember(ci, in.getU2(), in.getU2(), in.getU2());
+
+ int attributeCount = in.getU2();
+ if (attributeCount != 0) {
+ member.attribute_info = new Attributes(attributeCount);
+ for (int i = 0; i < attributeCount; i++)
+ member.attribute_info.addEntry(new AttributeEntry(in));
+ }
+
+ return member;
+ }
+
+ /*
+ ** Constructors.
+ */
+
+ private ClassInvestigator(int constantPoolCount) {
+ super(constantPoolCount);
+ }
+
+ /*
+ ** Methods to investigate this class
+ */
+
+
+ public Enumeration implementedInterfaces()
+ {
+ int interfaceCount = interfaces == null ? 0 : interfaces.length;
+ Vector implemented = new Vector(interfaceCount);
+
+ for (int i = 0; i < interfaceCount; i++)
+ {
+ implemented.addElement(className(interfaces[i]));
+ }
+ return implemented.elements();
+ }
+ public Enumeration getFields() {
+ if (field_info == null)
+ return Collections.enumeration(Collections.EMPTY_LIST);
+
+ return field_info.entries.elements();
+ }
+
+ public Enumeration getMethods() {
+ if (method_info == null)
+ return Collections.enumeration(Collections.EMPTY_LIST);
+ return method_info.entries.elements();
+ }
+
+ public Enumeration referencedClasses() {
+ return getClasses(getMethods(), getFields() );
+ }
+
+ /**
+ Return an Enumeration of all referenced classes
+ */
+
+ private Enumeration getClasses(Enumeration methods, Enumeration fields)
+ {
+ return new ClassEnumeration(this, cptEntries.elements(), methods, fields);
+ }
+
+ public Enumeration getStrings() {
+ HashSet strings = new HashSet(30, 0.8f);
+
+ int size = cptEntries.size();
+ for (int i = 1; i < size; i++) {
+ ConstantPoolEntry cpe = getEntry(i);
+
+ if ((cpe == null) || (cpe.getTag() != VMDescriptor.CONSTANT_String))
+ continue;
+
+ CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
+
+ strings.add(nameIndexToString(cii.getI1()));
+ }
+
+ return java.util.Collections.enumeration(strings);
+ }
+
+ public ClassMember getMember(String simpleName, String descriptor) {
+
+ if (descriptor.startsWith("(")) {
+ if (method_info == null)
+ return null;
+ return method_info.find(simpleName, descriptor);
+ }
+ else {
+ if (field_info == null)
+ return null;
+ return field_info.find(simpleName, descriptor);
+ }
+ }
+
+ /**
+ Return an Enumeration of all Member References
+ */
+/*
+ Enumeration getMemberReferences() {
+ return new ReferenceEnumeration(this, elements());
+ }
+*/
+
+ /*
+ ** Methods to modify the class.
+ */
+ // remove all atttributes that are not essential
+ public void removeAttributes() throws IOException {
+
+ // Class level attributes
+ if (attribute_info != null) {
+ for (int i = attribute_info.size() - 1; i >= 0 ; i--) {
+
+ AttributeEntry ae = (AttributeEntry) attribute_info.elementAt(i);
+ String name = nameIndexToString(ae.getNameIndex());
+ if (name.equals("SourceFile"))
+ attribute_info.removeElementAt(i);
+ else if (name.equals("InnerClasses"))
+ ; // leave in
+ else
+ System.err.println("WARNING - Unknown Class File attribute " + name);
+ }
+
+ if (attribute_info.size() == 0)
+ attribute_info = null;
+ }
+ attribute_info = null;
+
+ // fields
+ for (Enumeration e = getFields(); e.hasMoreElements(); ) {
+ ClassMember member = (ClassMember) e.nextElement();
+
+ Attributes attrs = member.attribute_info;
+
+ if (attrs != null) {
+
+ for (int i = attrs.size() - 1; i >= 0 ; i--) {
+
+ AttributeEntry ae = (AttributeEntry) attrs.elementAt(i);
+ String name = nameIndexToString(ae.getNameIndex());
+ if (name.equals("ConstantValue"))
+ ; // leave in
+ else if (name.equals("Synthetic"))
+ ; // leave in
+ else
+ System.err.println("WARNING - Unknown Field attribute " + name);
+ }
+
+ if (attrs.size() == 0)
+ member.attribute_info = null;
+ }
+
+ }
+
+ // methods
+ for (Enumeration e = getMethods(); e.hasMoreElements(); ) {
+ ClassMember member = (ClassMember) e.nextElement();
+
+ Attributes attrs = member.attribute_info;
+
+ if (attrs != null) {
+
+ for (int i = attrs.size() - 1; i >= 0 ; i--) {
+
+ AttributeEntry ae = (AttributeEntry) attrs.elementAt(i);
+ String name = nameIndexToString(ae.getNameIndex());
+ if (name.equals("Code"))
+ processCodeAttribute(member, ae);
+ else if (name.equals("Exceptions"))
+ ; // leave in
+ else if (name.equals("Deprecated"))
+ ; // leave in
+ else if (name.equals("Synthetic"))
+ ; // leave in
+ else
+ System.err.println("WARNING - Unknown method attribute " + name);
+ }
+
+ if (attrs.size() == 0)
+ member.attribute_info = null;
+ }
+
+ }
+ }
+
+ private void processCodeAttribute(ClassMember member, AttributeEntry ae) throws IOException {
+
+ ClassInput ci = new ClassInput(new java.io.ByteArrayInputStream(ae.infoIn));
+
+
+ ci.skipBytes(4); // puts us at code_length
+ int len = ci.getU4();
+ ci.skipBytes(len); // puts us at exception_table_length
+ int count = ci.getU2();
+ if (count != 0)
+ ci.skipBytes(8 * count);
+
+ int nonAttrLength = 4 + 4 + len + 2 + (8 * count);
+
+ // now at attributes
+
+ count = ci.getU2();
+ if (count == 0)
+ return;
+
+ int newCount = count;
+ for (int i = 0; i < count; i++) {
+
+ int nameIndex = ci.getU2();
+ String name = nameIndexToString(nameIndex);
+ if (name.equals("LineNumberTable") || name.equals("LocalVariableTable"))
+ newCount--;
+ else
+ System.err.println("ERROR - Unknown code attribute " + name);
+
+ len = ci.getU4();
+ ci.skipBytes(len);
+ }
+
+ if (newCount != 0) {
+ System.err.println("ERROR - expecting all code attributes to be removed");
+ System.exit(1);
+ }
+
+ // this is only coded for all attributes within a Code attribute being removed.
+
+ byte[] newInfo = new byte[nonAttrLength + 2];
+ System.arraycopy(ae.infoIn, 0, newInfo, 0, nonAttrLength);
+ // last two bytes are left at 0 which means 0 attributes
+ ae.infoIn = newInfo;
+ }
+
+ public void renameClassElements(Hashtable classNameMap, Hashtable memberNameMap) {
+
+ // this & super class
+ renameString(classNameMap, (CONSTANT_Index_info) getEntry(this_class));
+ renameString(classNameMap, (CONSTANT_Index_info) getEntry(super_class));
+
+ // implemented interfaces
+ // handled by Class entries below
+
+ // classes & Strings
+ // descriptors
+ int size = cptEntries.size();
+ for (int i = 1; i < size; i++) {
+ ConstantPoolEntry cpe = getEntry(i);
+
+ if (cpe == null)
+ continue;
+
+ switch (cpe.getTag()) {
+ case VMDescriptor.CONSTANT_String:
+ case VMDescriptor.CONSTANT_Class:
+ {
+ CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
+ renameString(classNameMap, cii);
+ break;
+ }
+ case VMDescriptor.CONSTANT_NameAndType:
+ {
+ CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
+ String newDescriptor = newDescriptor(classNameMap, nameIndexToString(cii.getI2()));
+ if (newDescriptor != null) {
+ doRenameString(cii.getI2(), newDescriptor);
+ }
+ break;
+ }
+
+ default:
+ continue;
+ }
+
+ }
+
+ //System.out.println("Starting Fields");
+
+ // now the methods & fields, only descriptors at this time
+ renameMembers(getFields(), classNameMap, memberNameMap);
+
+ renameMembers(getMethods(), classNameMap, memberNameMap);
+ }
+
+ private void renameMembers(Enumeration e, Hashtable classNameMap, Hashtable memberNameMap) {
+
+ for (; e.hasMoreElements(); ) {
+ ClassMember member = (ClassMember) e.nextElement();
+
+ String oldMemberName = nameIndexToString(member.name_index);
+ String newMemberName = (String) memberNameMap.get(oldMemberName);
+ if (newMemberName != null)
+ doRenameString(member.name_index, newMemberName);
+
+ String newDescriptor = newDescriptor(classNameMap, nameIndexToString(member.descriptor_index));
+ if (newDescriptor != null) {
+ doRenameString(member.descriptor_index, newDescriptor);
+ }
+ }
+
+ }
+
+ private void renameString(Hashtable classNameMap, CONSTANT_Index_info cii) {
+
+ int index = cii.getI1();
+
+ String name = nameIndexToString(index);
+ String newName = (String) classNameMap.get(name);
+ if (newName != null) {
+
+ doRenameString(index, newName);
+
+ return;
+ }
+
+ // have to look for arrays
+ if (cii.getTag() == VMDescriptor.CONSTANT_Class) {
+
+ if (name.charAt(0) == '[') {
+ int classOffset = name.indexOf('L') + 1;
+
+ String baseClassName = name.substring(classOffset, name.length() - 1);
+
+
+ newName = (String) classNameMap.get(baseClassName);
+
+ if (newName != null) {
+
+ String newArrayClassName = name.substring(0, classOffset) + newName + ";";
+
+ doRenameString(index, newArrayClassName);
+
+ }
+
+ }
+ }
+ }
+
+ private void doRenameString(int index, String newName) {
+ ConstantPoolEntry cpe = getEntry(index);
+ if (cpe.getTag() != VMDescriptor.CONSTANT_Utf8)
+ throw new RuntimeException("unexpected type " + cpe);
+
+ CONSTANT_Utf8_info newCpe = new CONSTANT_Utf8_info(newName);
+
+ cptHashTable.remove(cpe.getKey());
+ cptHashTable.put(cpe.getKey(), cpe);
+
+ newCpe.index = index;
+
+ cptEntries.setElementAt(newCpe, index);
+ }
+
+ /*
+ **
+ */
+ static private void checkHeader(ClassInput in) throws IOException {
+ int magic = in.getU4();
+ int minor_version = in.getU2();
+ int major_version = in.getU2();
+
+
+ if (magic != VMDescriptor.JAVA_CLASS_FORMAT_MAGIC)
+ throw new ClassFormatError();
+ }
+ private static ConstantPoolEntry getConstant(ClassInput in)
+ throws IOException {
+
+ ConstantPoolEntry item;
+ int tag;
+ tag = in.readUnsignedByte();
+
+ switch (tag) {
+ case VMDescriptor.CONSTANT_Class:
+ case VMDescriptor.CONSTANT_String:
+ item = new CONSTANT_Index_info(tag, in.getU2(), 0);
+ break;
+
+ case VMDescriptor.CONSTANT_NameAndType:
+ case VMDescriptor.CONSTANT_Fieldref:
+ case VMDescriptor.CONSTANT_Methodref:
+ case VMDescriptor.CONSTANT_InterfaceMethodref:
+ item = new CONSTANT_Index_info(tag, in.getU2(), in.getU2());
+ break;
+
+ case VMDescriptor.CONSTANT_Integer:
+ item = new CONSTANT_Integer_info(in.getU4());
+ break;
+
+ case VMDescriptor.CONSTANT_Float:
+ item = new CONSTANT_Float_info(in.readFloat());
+ break;
+
+ case VMDescriptor.CONSTANT_Long:
+ item = new CONSTANT_Long_info(in.readLong());
+ break;
+
+ case VMDescriptor.CONSTANT_Double:
+ item = new CONSTANT_Double_info(in.readDouble());
+ break;
+
+ case VMDescriptor.CONSTANT_Utf8:
+ item = new CONSTANT_Utf8_info(in.readUTF());
+ break;
+ default:
+ throw new ClassFormatError();
+ }
+
+ return item;
+ }
+ public static String newDescriptor(Hashtable classNameMap, String descriptor) {
+
+ String newDescriptor = null;
+
+ int dlen = descriptor.length();
+ for (int offset = 0; offset < dlen; ) {
+ char c = descriptor.charAt(offset);
+ switch (c) {
+ case VMDescriptor.C_VOID :
+ case VMDescriptor.C_BOOLEAN:
+ case VMDescriptor.C_BYTE:
+ case VMDescriptor.C_CHAR:
+ case VMDescriptor.C_SHORT:
+ case VMDescriptor.C_INT:
+ case VMDescriptor.C_LONG:
+ case VMDescriptor.C_FLOAT:
+ case VMDescriptor.C_DOUBLE:
+ case VMDescriptor.C_ARRAY:
+ case VMDescriptor.C_METHOD:
+ case VMDescriptor.C_ENDMETHOD:
+ default:
+ offset++;
+ continue;
+
+ case VMDescriptor.C_CLASS:
+ {
+ int startOffset = offset;
+ while (descriptor.charAt(offset++) != VMDescriptor.C_ENDCLASS)
+ ;
+ int endOffset = offset;
+
+ // name includes L and ;
+ String name = descriptor.substring(startOffset, endOffset);
+ String newName = (String) classNameMap.get(name);
+ if (newName != null) {
+ if (newDescriptor == null)
+ newDescriptor = descriptor;
+
+ // we just replace the first occurance of it,
+ // the loop will hit any next occurance.
+ int startPos = newDescriptor.indexOf(name);
+
+ String tmp;
+ if (startPos == 0)
+ tmp = newName;
+ else
+ tmp = newDescriptor.substring(0, startPos) +
+ newName;
+
+ int endPos = startPos + name.length();
+
+ if (endPos < newDescriptor.length()) {
+
+ tmp += newDescriptor.substring(endPos , newDescriptor.length());
+ }
+
+
+ newDescriptor = tmp;
+ }
+ }
+ }
+
+
+ }
+ //if (newDescriptor != null) {
+ // System.out.println("O - " + descriptor);
+ // System.out.println("N - " + newDescriptor);
+ //}
+ return newDescriptor;
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassMember.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassMember.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ClassMember.java Fri Sep 24 10:33:20 2004
@@ -1,85 +1,85 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import java.lang.reflect.Modifier;
-
-import java.io.IOException;
-
-
-
-public class ClassMember {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- protected ClassHolder cpt;
- protected int access_flags;
- protected int name_index;
- protected int descriptor_index;
- protected Attributes attribute_info; // can be null
-
- ClassMember(ClassHolder cpt, int modifier, int name, int descriptor) {
- this.cpt = cpt;
- name_index = name;
- descriptor_index = descriptor;
- access_flags = modifier;
- }
-
- /*
- ** Public methods from ClassMember
- */
-
- public int getModifier() {
- return access_flags;
- }
-
- public String getDescriptor() {
- return cpt.nameIndexToString(descriptor_index);
- }
-
- public String getName() {
- return cpt.nameIndexToString(name_index);
- }
-
- public void addAttribute(String attributeName, ClassFormatOutput info) {
-
- if (attribute_info == null)
- attribute_info = new Attributes(1);
-
- attribute_info.addEntry(new AttributeEntry(cpt.addUtf8(attributeName), info));
- }
-
-
- /*
- ** ----
- */
-
- void put(ClassFormatOutput out) throws IOException {
- out.putU2(access_flags);
- out.putU2(name_index);
- out.putU2(descriptor_index);
-
- if (attribute_info != null) {
- out.putU2(attribute_info.size());
- attribute_info.put(out);
- } else {
- out.putU2(0);
- }
- }
-
- int classFileSize() {
- int size = 2 + 2 + 2 + 2;
- if (attribute_info != null)
- size += attribute_info.classFileSize();
- return size;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import java.lang.reflect.Modifier;
+
+import java.io.IOException;
+
+
+
+public class ClassMember {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ protected ClassHolder cpt;
+ protected int access_flags;
+ protected int name_index;
+ protected int descriptor_index;
+ protected Attributes attribute_info; // can be null
+
+ ClassMember(ClassHolder cpt, int modifier, int name, int descriptor) {
+ this.cpt = cpt;
+ name_index = name;
+ descriptor_index = descriptor;
+ access_flags = modifier;
+ }
+
+ /*
+ ** Public methods from ClassMember
+ */
+
+ public int getModifier() {
+ return access_flags;
+ }
+
+ public String getDescriptor() {
+ return cpt.nameIndexToString(descriptor_index);
+ }
+
+ public String getName() {
+ return cpt.nameIndexToString(name_index);
+ }
+
+ public void addAttribute(String attributeName, ClassFormatOutput info) {
+
+ if (attribute_info == null)
+ attribute_info = new Attributes(1);
+
+ attribute_info.addEntry(new AttributeEntry(cpt.addUtf8(attributeName), info));
+ }
+
+
+ /*
+ ** ----
+ */
+
+ void put(ClassFormatOutput out) throws IOException {
+ out.putU2(access_flags);
+ out.putU2(name_index);
+ out.putU2(descriptor_index);
+
+ if (attribute_info != null) {
+ out.putU2(attribute_info.size());
+ attribute_info.put(out);
+ } else {
+ out.putU2(0);
+ }
+ }
+
+ int classFileSize() {
+ int size = 2 + 2 + 2 + 2;
+ if (attribute_info != null)
+ size += attribute_info.classFileSize();
+ return size;
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ConstantPoolEntry.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ConstantPoolEntry.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/classfile/ConstantPoolEntry.java Fri Sep 24 10:33:20 2004
@@ -1,109 +1,109 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.classfile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.classfile;
-
-import org.apache.derby.iapi.services.classfile.VMDescriptor;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import java.io.IOException;
-
-/** Constant Pool class - pages 92-99 */
-public abstract class ConstantPoolEntry /*implements PoolEntry*/
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
- protected int tag; // u1 (page 83)
- protected boolean doubleSlot; // Some entries take up two slots! (see footnote page 98)
-
- /* Index within Vector */
- protected int index;
-
- protected ConstantPoolEntry(int tag) {
- this.tag = tag;
- }
-
- int getIndex() {
- if (SanityManager.DEBUG) {
- if (index <= 0)
- {
- SanityManager.THROWASSERT("index is expected to be > 0, is " + index);
- }
- }
- return index;
- }
-
- void setIndex(int index) {
- this.index = index;
- }
-
- boolean doubleSlot() {
- return doubleSlot;
- }
-
- /**
- Return the key used to key this object in a hashtable
- */
- Object getKey() {
- return this;
- }
-
- /**
- Return an estimate of the size of the constant pool entry.
- */
- abstract int classFileSize();
-
- void put(ClassFormatOutput out) throws IOException {
- out.putU1(tag);
- }
-
- /*
- ** Public API methods
- */
-
- /**
- Return the tag or type of the entry. Will be equal to one of the
- constants above, e.g. CONSTANT_Class.
- */
- final int getTag() {
- return tag;
- }
-
- /**
- Get the first index in a index type pool entry.
- This call is valid when getTag() returns one of
- <UL>
- <LI> CONSTANT_Class
- <LI> CONSTANT_Fieldref
- <LI> CONSTANT_Methodref
- <LI> CONSTANT_InterfaceMethodref
- <LI> CONSTANT_String
- <LI> CONSTANT_NameAndType
- </UL>
- */
- int getI1() { return 0; }
-
- /**
- Get the second index in a index type pool entry.
- This call is valid when getTag() returns one of
- <UL>
- <LI> CONSTANT_Fieldref
- <LI> CONSTANT_Methodref
- <LI> CONSTANT_InterfaceMethodref
- <LI> CONSTANT_NameAndType
- </UL>
- */
- int getI2() { return 0; };
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.classfile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.classfile;
+
+import org.apache.derby.iapi.services.classfile.VMDescriptor;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import java.io.IOException;
+
+/** Constant Pool class - pages 92-99 */
+public abstract class ConstantPoolEntry /*implements PoolEntry*/
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+ protected int tag; // u1 (page 83)
+ protected boolean doubleSlot; // Some entries take up two slots! (see footnote page 98)
+
+ /* Index within Vector */
+ protected int index;
+
+ protected ConstantPoolEntry(int tag) {
+ this.tag = tag;
+ }
+
+ int getIndex() {
+ if (SanityManager.DEBUG) {
+ if (index <= 0)
+ {
+ SanityManager.THROWASSERT("index is expected to be > 0, is " + index);
+ }
+ }
+ return index;
+ }
+
+ void setIndex(int index) {
+ this.index = index;
+ }
+
+ boolean doubleSlot() {
+ return doubleSlot;
+ }
+
+ /**
+ Return the key used to key this object in a hashtable
+ */
+ Object getKey() {
+ return this;
+ }
+
+ /**
+ Return an estimate of the size of the constant pool entry.
+ */
+ abstract int classFileSize();
+
+ void put(ClassFormatOutput out) throws IOException {
+ out.putU1(tag);
+ }
+
+ /*
+ ** Public API methods
+ */
+
+ /**
+ Return the tag or type of the entry. Will be equal to one of the
+ constants above, e.g. CONSTANT_Class.
+ */
+ final int getTag() {
+ return tag;
+ }
+
+ /**
+ Get the first index in a index type pool entry.
+ This call is valid when getTag() returns one of
+ <UL>
+ <LI> CONSTANT_Class
+ <LI> CONSTANT_Fieldref
+ <LI> CONSTANT_Methodref
+ <LI> CONSTANT_InterfaceMethodref
+ <LI> CONSTANT_String
+ <LI> CONSTANT_NameAndType
+ </UL>
+ */
+ int getI1() { return 0; }
+
+ /**
+ Get the second index in a index type pool entry.
+ This call is valid when getTag() returns one of
+ <UL>
+ <LI> CONSTANT_Fieldref
+ <LI> CONSTANT_Methodref
+ <LI> CONSTANT_InterfaceMethodref
+ <LI> CONSTANT_NameAndType
+ </UL>
+ */
+ int getI2() { return 0; };
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/HeaderPrintWriter.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/HeaderPrintWriter.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/HeaderPrintWriter.java Fri Sep 24 10:33:20 2004
@@ -1,78 +1,78 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.stream
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.stream;
-
-import java.io.PrintWriter;
-
-/**
- * A HeaderPrintWriter is like a PrintWriter with support for
- * including a header in the output. It is expected users
- * will use HeaderPrintWriters to prepend headings to trace
- * and log messages.
- *
- */
-public interface HeaderPrintWriter
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- * Puts out some setup info for
- * the current write and the write(s) that will be put out next.
- * It ends with a \n\r.
- * <p>
- * All other writes to the stream use the
- * PrintStream interface.
- */
- public void printlnWithHeader(String message);
-
- /**
- * Return the header for the stream.
- */
- public PrintWriterGetHeader getHeader();
-
- /**
- * Gets a PrintWriter object for writing to this HeaderPrintWriter.
- * Users may use the HeaderPrintWriter to access methods not included
- * in this interface or to invoke methods or constructors which require
- * a PrintWriter.
- *
- * Interleaving calls to a printWriter and its associated HeaderPrintWriter
- * is not supported.
- *
- */
- public PrintWriter getPrintWriter();
-
- /*
- * The routines that mimic java.io.PrintWriter...
- */
- /**
- * @see java.io.PrintWriter#print
- */
- public void print(String message);
-
- /**
- * @see java.io.PrintWriter#println
- */
- public void println(String message);
-
- /**
- * @see java.io.PrintWriter#println
- */
- public void println(Object message);
-
- /**
- * @see java.io.PrintWriter#flush
- */
- public void flush();
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.stream
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.stream;
+
+import java.io.PrintWriter;
+
+/**
+ * A HeaderPrintWriter is like a PrintWriter with support for
+ * including a header in the output. It is expected users
+ * will use HeaderPrintWriters to prepend headings to trace
+ * and log messages.
+ *
+ */
+public interface HeaderPrintWriter
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ * Puts out some setup info for
+ * the current write and the write(s) that will be put out next.
+ * It ends with a \n\r.
+ * <p>
+ * All other writes to the stream use the
+ * PrintStream interface.
+ */
+ public void printlnWithHeader(String message);
+
+ /**
+ * Return the header for the stream.
+ */
+ public PrintWriterGetHeader getHeader();
+
+ /**
+ * Gets a PrintWriter object for writing to this HeaderPrintWriter.
+ * Users may use the HeaderPrintWriter to access methods not included
+ * in this interface or to invoke methods or constructors which require
+ * a PrintWriter.
+ *
+ * Interleaving calls to a printWriter and its associated HeaderPrintWriter
+ * is not supported.
+ *
+ */
+ public PrintWriter getPrintWriter();
+
+ /*
+ * The routines that mimic java.io.PrintWriter...
+ */
+ /**
+ * @see java.io.PrintWriter#print
+ */
+ public void print(String message);
+
+ /**
+ * @see java.io.PrintWriter#println
+ */
+ public void println(String message);
+
+ /**
+ * @see java.io.PrintWriter#println
+ */
+ public void println(Object message);
+
+ /**
+ * @see java.io.PrintWriter#flush
+ */
+ public void flush();
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/InfoStreams.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/InfoStreams.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/InfoStreams.java Fri Sep 24 10:33:20 2004
@@ -1,40 +1,40 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.stream
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.stream;
-
-/**
- *
- * The Basic Services provide InfoStreams for reporting
- * information.
- * <p>
- * When creating a message for a stream,
- * you can create an initial entry with header information
- * and then append to it as many times as desired.
- * <p>
- *
- * @see HeaderPrintWriter
- * @author ames
- */
-public interface InfoStreams {
-
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- /**
- Return the default stream. If the default stream could not be set up as requested then
- it points indirectly to System.err.
- *
- * @return the default stream.
- */
- HeaderPrintWriter stream();
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.stream
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.stream;
+
+/**
+ *
+ * The Basic Services provide InfoStreams for reporting
+ * information.
+ * <p>
+ * When creating a message for a stream,
+ * you can create an initial entry with header information
+ * and then append to it as many times as desired.
+ * <p>
+ *
+ * @see HeaderPrintWriter
+ * @author ames
+ */
+public interface InfoStreams {
+
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ /**
+ Return the default stream. If the default stream could not be set up as requested then
+ it points indirectly to System.err.
+ *
+ * @return the default stream.
+ */
+ HeaderPrintWriter stream();
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/PrintWriterGetHeader.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/PrintWriterGetHeader.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/stream/PrintWriterGetHeader.java Fri Sep 24 10:33:20 2004
@@ -1,37 +1,37 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.stream
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.stream;
-
-/**
- * Get a header to prepend to a line of output.
- * A HeaderPrintWriter requires an object which implements
- * this interface to construct headers for output lines.
- *
- * @see org.apache.derby.iapi.services.stream.HeaderPrintWriter
- */
-
-public interface PrintWriterGetHeader
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- * getHeader
- *
- * @return The header for an output line.
- *
- * @see org.apache.derby.iapi.services.stream.HeaderPrintWriter
- **/
-
- public String getHeader();
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.stream
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.stream;
+
+/**
+ * Get a header to prepend to a line of output.
+ * A HeaderPrintWriter requires an object which implements
+ * this interface to construct headers for output lines.
+ *
+ * @see org.apache.derby.iapi.services.stream.HeaderPrintWriter
+ */
+
+public interface PrintWriterGetHeader
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ * getHeader
+ *
+ * @return The header for an output line.
+ *
+ * @see org.apache.derby.iapi.services.stream.HeaderPrintWriter
+ **/
+
+ public String getHeader();
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/uuid/UUIDFactory.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/uuid/UUIDFactory.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/services/uuid/UUIDFactory.java Fri Sep 24 10:33:20 2004
@@ -1,69 +1,69 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.services.uuid
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.services.uuid;
-
-import org.apache.derby.catalog.UUID;
-
-/*
- Internal comment (not for user documentation):
- Although this is an abstract interface, I believe that the
- underlying implementation of UUID will have to be DCE UUID.
- This is because the string versions of UUIDs get stored in
- the source code. In other words, no matter what implementation
- is used for UUIDs, strings that look like this
- <blockquote><pre>
- E4900B90-DA0E-11d0-BAFE-0060973F0942
- </blockquote></pre>
- will always have to be turned into universally unique objects
- by the recreateUUID method
- */
-/**
-
- Generates and recreates unique identifiers.
-
- An example of such an identifier is:
- <blockquote><pre>
- E4900B90-DA0E-11d0-BAFE-0060973F0942
- </blockquote></pre>
- These resemble DCE UUIDs, but use a different implementation.
- <P>
- The string format is designed to be the same as the string
- format produced by Microsoft's UUIDGEN program, although at
- present the bit fields are probably not the same.
-
- **/
-public interface UUIDFactory
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- /**
- Create a new UUID. The resulting object is guaranteed
- to be unique "across space and time".
- @return The UUID.
- **/
- public UUID createUUID();
-
- /**
- Recreate a UUID from a string produced by UUID.toString.
- @return The UUID.
- **/
- public UUID recreateUUID(String uuidstring);
-
- /**
- Recreate a UUID from a byte array produced by UUID.toByteArray.
- @return The UUID.
- @see UUID#toByteArray
- **/
- public UUID recreateUUID(byte[] b);
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.services.uuid
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.services.uuid;
+
+import org.apache.derby.catalog.UUID;
+
+/*
+ Internal comment (not for user documentation):
+ Although this is an abstract interface, I believe that the
+ underlying implementation of UUID will have to be DCE UUID.
+ This is because the string versions of UUIDs get stored in
+ the source code. In other words, no matter what implementation
+ is used for UUIDs, strings that look like this
+ <blockquote><pre>
+ E4900B90-DA0E-11d0-BAFE-0060973F0942
+ </blockquote></pre>
+ will always have to be turned into universally unique objects
+ by the recreateUUID method
+ */
+/**
+
+ Generates and recreates unique identifiers.
+
+ An example of such an identifier is:
+ <blockquote><pre>
+ E4900B90-DA0E-11d0-BAFE-0060973F0942
+ </blockquote></pre>
+ These resemble DCE UUIDs, but use a different implementation.
+ <P>
+ The string format is designed to be the same as the string
+ format produced by Microsoft's UUIDGEN program, although at
+ present the bit fields are probably not the same.
+
+ **/
+public interface UUIDFactory
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ /**
+ Create a new UUID. The resulting object is guaranteed
+ to be unique "across space and time".
+ @return The UUID.
+ **/
+ public UUID createUUID();
+
+ /**
+ Recreate a UUID from a string produced by UUID.toString.
+ @return The UUID.
+ **/
+ public UUID recreateUUID(String uuidstring);
+
+ /**
+ Recreate a UUID from a byte array produced by UUID.toByteArray.
+ @return The UUID.
+ @see UUID#toByteArray
+ **/
+ public UUID recreateUUID(byte[] b);
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java Fri Sep 24 10:33:20 2004
@@ -1,617 +1,617 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-
-import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
-import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
-
-import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
-import org.apache.derby.iapi.sql.execute.ExecRow;
-import org.apache.derby.iapi.sql.execute.ExecutionFactory;
-import org.apache.derby.iapi.sql.execute.NoPutResultSet;
-import org.apache.derby.iapi.sql.execute.ConstantAction;
-import org.apache.derby.iapi.sql.execute.CursorResultSet;
-import org.apache.derby.iapi.sql.execute.TemporaryRowHolder;
-
-import org.apache.derby.iapi.store.access.ConglomerateController;
-import org.apache.derby.iapi.store.access.ScanController;
-import org.apache.derby.iapi.store.access.TransactionController;
-
-import org.apache.derby.iapi.types.DataValueFactory;
-
-import org.apache.derby.iapi.types.RowLocation;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-import java.sql.SQLWarning;
-import java.util.Enumeration;
-import java.util.Vector;
-import java.util.Hashtable;
-
-
-/**
- * An activation contains all the local state information necessary
- * to execute a re-entrant PreparedStatement. The way it will actually work
- * is that a PreparedStatement will have an executable plan, which will be
- * a generated class. All of the local state will be variables in the class.
- * Creating a new instance of the executable plan will create the local state
- * variables. This means that an executable plan must implement this interface,
- * and that the PreparedStatement.getActivation() method will do a
- * "new" operation on the executable plan.
- * <p>
- * The fixed implementations of Activation in the Execution impl
- * package are used as skeletons for the classes generated for statements
- * when they are compiled.
- * <p>
- * There are no fixed implementations of Activation for statements;
- * a statement has an activation generated for it when it is compiled.
- *
- * @author Jeff Lichtman
- */
-
-public interface Activation
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- * Resets the activation to the "pre-execution" state -
- * that is, the state where it can be used to begin a new execution.
- * Frees local buffers, stops scans, resets counters to zero, sets
- * current date and time to an unitialized state, etc.
- *
- * @return Nothing
- * @exception StandardException thrown on failure
- */
- void reset() throws StandardException;
-
- /**
- * JDBC requires that all select statements be converted into cursors,
- * and that the cursor name be settable for each execution of a select
- * statement. The Language Module will support this, so that the JDBC
- * driver will not have to parse JSQL text. This method will have no
- * effect when called on non-select statements.
- * <p>
- * There will be a JSQL statement to disable the "cursorization" of
- * all select statements. For non-cursorized select statements, this
- * method will have no effect.
- * <p>
- * This has no effect if the activation has been closed.
- * <p>
- * @param cursorName The cursor name to use.
- */
- void setCursorName(String cursorName);
-
- /**
- * Temporary tables can be declared with ON COMMIT DELETE ROWS. But if the table has a held curosr open at
- * commit time, data should not be deleted from the table. This method, (gets called at commit time) checks if this
- * activation held cursor and if so, does that cursor reference the passed temp table name.
- *
- * @return true if this activation has held cursor and if it references the passed temp table name
- */
- public boolean checkIfThisActivationHasHoldCursor(String tableName);
-
- /**
- * Gets the ParameterValueSet for this execution of the statement.
- *
- * @return The ParameterValueSet for this execution of the
- * statement. Returns NULL if there are no parameters.
- */
- ParameterValueSet getParameterValueSet();
-
- /**
- * Sets the parameter values for this execution of the statement.
- * <p>
- * Has no effect if the activation has been closed.
- *
- * <p>
- * NOTE: The setParameters() method is currently unimplemented.
- * A statement with parameters will generate its own ParameterValueSet,
- * which can be gotten with the getParameterValueSet() method (above).
- * The idea behind setParameters() is to improve performance when
- * operating across a network by allowing all the parameters to be set
- * in one call, as opposed to one call per parameter.
- *
- * @param parameterValues The values of the parameters.
- *
- * @return Nothing
- */
- void setParameters(ParameterValueSet parameterValues, DataTypeDescriptor[] parameterTypes) throws StandardException;
-
- /**
- * When the prepared statement is executed, it passes
- * execution on to the activation execution was requested for.
- *
- * @return the ResultSet for further manipulation, if any.
- *
- * @exception StandardException Thrown on failure
- */
- ResultSet execute() throws StandardException;
-
- /**
- Closing an activation statement marks it as unusable. Any other
- requests made on it will fail. An activation should be
- marked closed when it is expected to not be used any longer,
- i.e. when the connection for it is closed, or it has suffered some
- sort of severe error. This will also close its result set and
- release any resources it holds e.g. for parameters.
- <P>
- Any class that implements this must be prepared to be executed
- from garbage collection, ie. there is no matching context stack.
-
- @exception StandardException Thrown on failure
- */
- void close() throws StandardException;
-
- /**
- Find out if the activation is closed or not.
-
- @return true if the Activation has been closed.
- */
- boolean isClosed();
-
- /**
- Set this Activation for a single execution.
- E.g. a java.sql.Statement execution.
- */
- void setSingleExecution();
-
- /**
- Returns true if this Activation is only going to be used for
- one execution.
- */
- boolean isSingleExecution();
-
- /**
- Returns the chained list of warnings. Returns null
- if there are no warnings.
- */
- SQLWarning getWarnings();
-
- /**
- Add a warning to the activation
- */
- void addWarning(SQLWarning w);
-
- /**
- Clear the activation's warnings.
- */
- void clearWarnings();
-
- /**
- * Get the language connection context associated with this activation
- */
- public LanguageConnectionContext getLanguageConnectionContext();
-
- /**
- * Get the Execution TransactionController associated with this
- * activation/lcc.
- */
- TransactionController getTransactionController();
-
- /**
- * Returns the current result set for this activation, i.e.
- * the one returned by the last execute() call. If there has
- * been no execute call or the activation has been reset or closed,
- * a null is returned.
- *
- * @return the current ResultSet of this activation.
- */
- ResultSet getResultSet();
-
- /**
- * Sets the ResultSet to be returned by getResultSet() to null.
- */
- void clearResultSet();
-
- /**
- * Generated plans have a current row field for ease in defining
- * the methods and finding them dynamically. The interface is
- * used to set the row before a dynamic method that uses it is
- * invoked.
- * <p>
- * When all processing on the currentRow has been completed,
- * callers should call activation.clearCurrentRow(resultSetNumber)
- * to ensure that no unnecessary references are retained to rows.
- * This will allow the rows no longer in use to be collected by
- * the garbage collecter.
- *
- * @param currentRow The row to be operated upon.
- * @param resultSetNumber The resultSetNumber for the current ResultSet
- *
- * @return Nothing
- *
- */
- void setCurrentRow(ExecRow currentRow, int resultSetNumber);
-
- /**
- * Generated plans have a current row field for ease in defining
- * the methods and finding them dynamically. The interface is
- * used to set the row before a dynamic method that uses it is
- * invoked.
- * <p>
- * When all processing on the currentRow has been completed,
- * callers should call activation.clearCurrentRow(resultSetNumber)
- * to ensure that no unnecessary references are retained to rows.
- * This will allow the rows no longer in use to be collected by
- * the garbage collecter.
- *
- * @param resultSetNumber The resultSetNumber for the current ResultSet
- *
- * @return Nothing
- */
- /* RESOLVE - this method belongs on an internal, not external, interface */
- void clearCurrentRow(int resultSetNumber);
-
- /**
- * Get the prepared statement that this activation is for.
- *
- * @return the prepared statement this activation is for.
- *
- */
- ExecPreparedStatement getPreparedStatement();
-
- /**
- Check the validity of the current executing statement. Needs to be
- called after a statement has obtained the relevant table locks on
- the
- */
- public void checkStatementValidity() throws StandardException;
-
- /**
- * Get the result description for this activation, if it has one.
- *
- * @return result description for this activation, if it has one;
- * otherwise, null.
- */
- ResultDescription getResultDescription();
-
- /**
- * Get the DataValueFactory
- *
- * @return DataValueFactory
- */
- DataValueFactory getDataValueFactory();
-
- /**
- * Get the ExecutionFactory
- *
- * @return ExecutionFactory
- */
- ExecutionFactory getExecutionFactory();
-
- /**
- Get the saved RowLocation.
-
- @param itemNumber The saved item number.
-
- @return A RowLocation template for the conglomerate
- */
- public RowLocation getRowLocationTemplate(int itemNumber);
-
- /**
- Get the number of subqueries in the entire query.
- @return int The number of subqueries in the entire query.
- */
- public int getNumSubqueries();
-
- /**
- * Return the cursor name of this activation. This will differ
- * from its ResultSet's cursor name if it has been
- * altered with setCursorName. Thus this always returns the cursor
- * name of the next execution of this activation. The cursor name
- * of the current execution must be obtained from the ResultSet.
- * or this.getResultSet.getCursorName() [with null checking].
- * <p>
- * Statements that do not support cursors will return a null.
- * <p>
- * @return The cursor name.
- */
- public String getCursorName();
-
- /**
- * Return the holdability of this activation.
- * <p>
- * @return The holdability of this activation.
- */
- public boolean getResultSetHoldability();
-
- /**
- * Set current resultset holdability.
- *
- * @param resultSetHoldability The new resultset holdability.
- *
- * @return Nothing.
- */
- public void setResultSetHoldability(boolean resultSetHoldability);
-
- /**
- * Set the auto-generated keys resultset mode to true for this activation.
- *
- * The specific columns for auto-generated keys resultset can be requested by
- * passing column positions array
- *
- * The specific columns for auto-generated keys resultset can be requested by
- * passing column names array
- *
- * Both the parameters would be null if user didn't request specific keys.
- * Otherwise, the user could request specific columns by passing column positions
- * or names array but not both.
- *
- * @param columnIndexes Request specific columns in auto-generated keys
- * resultset by passing column positions. null means no specific columns
- * requested by position
- *
- * @param columnNames Request specific columns in auto-generated keys
- * resultset by passing column names. null means no specific columns
- * requested by position
- *
- * @return Nothing.
- */
- public void setAutoGeneratedKeysResultsetInfo(int[] columnIndexes, String[] columnNames);
-
- /**
- * Returns true if auto-generated keys resultset request was made for this
- * avtivation.
- * <p>
- * @return auto-generated keys resultset mode for this activation.
- */
- public boolean getAutoGeneratedKeysResultsetMode();
-
- /**
- * Returns the column positions array of columns requested in auto-generated
- * keys resultset for this avtivation. Returns null if no specific column
- * requested by positions
- * <p>
- * @return column positions array of columns requested.
- */
- public int[] getAutoGeneratedKeysColumnIndexes();
-
- /**
- * Returns the column names array of columns requested in auto-generated
- * keys resultset for this avtivation. Returns null if no specific column
- * requested by names
- * <p>
- * @return column names array of columns requested.
- */
- public String[] getAutoGeneratedKeysColumnNames();
-
- /**
- * Mark the activation as unused.
- */
- public void markUnused();
-
- /**
- * Is the activation in use?
- *
- * @return true/false
- */
- public boolean isInUse();
-
- /**
- * Tell this activation that the given ResultSet was found to have
- * the given number of rows. This is used during execution to determine
- * whether a table has grown or shrunk. If a table's size changes
- * significantly, the activation may invalidate its PreparedStatement
- * to force recompilation.
- *
- * Note that the association of row counts with ResultSets is kept
- * in the activation class, not in the activation itself. This
- * means that this method must be synchronized.
- *
- * This method is not required to check the number of rows on each
- * call. Because of synchronization, this check is likely to be
- * expensive, so it may only check every hundred calls or so.
- *
- * @exception StandardException Thrown on error
- */
- public void informOfRowCount(NoPutResultSet resultSet, long rowCount)
- throws StandardException;
-
- /**
- * Get the ConglomerateController, if any, that has already
- * been opened for the heap when scaning for an update or delete.
- * (Saves opening the ConglomerateController twice.)
- *
- * @return The ConglomerateController, if available, to use for the update.
- */
- public ConglomerateController getHeapConglomerateController();
-
- /**
- * Set the ConglomerateController to be used for an update or delete.
- * (Saves opening the ConglomerateController twice.)
- *
- * @param updateHeapCC The ConglomerateController to reuse for the update or delete.
- *
- * @return Nothing.
- */
- public void setHeapConglomerateController(ConglomerateController updateHeapCC);
-
- /**
- * Clear the ConglomerateController to be used for an update or delete.
- * (Saves opening the ConglomerateController twice.)
- *
- * @return Nothing.
- */
- public void clearHeapConglomerateController();
-
- /**
- * Get the ScanController, if any, that has already
- * been opened for the index when scaning for an update or delete.
- * (Saves opening the ScanController twice.)
- *
- * @return The ScanController, if available, to use for the update.
- */
- public ScanController getIndexScanController();
-
- /**
- * Set the ScanController to be used for an update or delete,
- * when scanning an index that will also be updated
- * (Saves opening the ScanController twice.)
- *
- * @param indexSC The ScanController to reuse for the update or delete.
- *
- * @return Nothing.
- */
- public void setIndexScanController(ScanController indexSC);
-
- /**
- * Get the conglomerate number of the index, if any, that has already
- * been opened for scaning for an update or delete.
- * (Saves opening the ScanController twice.)
- *
- * @return The conglomerate number, if available, to use for the update.
- */
- public long getIndexConglomerateNumber();
-
- /**
- * Set the conglomerate number of the index to be used for an update or delete,
- * when scanning an index that will also be updated
- * (Saves opening the ScanController twice.)
- *
- * @param indexConglomerateNumber The conglomerate number of the index to reuse for the update or delete.
- *
- * @return Nothing.
- */
- public void setIndexConglomerateNumber(long indexConglomerateNumber);
-
- /**
- * Clear the info for the index to be re-used for update/delete.
- * (ScanController and conglomerate number.)
- *
- * @return Nothing.
- */
- public void clearIndexScanInfo();
-
- /**
- * Mark the Activation as being for create table.
- * (NOTE: We can do certain optimizations for
- * create table that we can't do for other DDL.)
- *
- * @return Nothing.
- */
- public void setForCreateTable();
-
- /**
- * Get whether or not this activation is for
- * create table.
- * (NOTE: We can do certain optimizations for
- * create table that we can't do for other DDL.)
- *
- * @return Whether or not this activation is for
- * create table.
- */
- public boolean getForCreateTable();
-
- /**
- * Save the TableDescriptor for the target of
- * DDL so that it can be passed between the
- * various ConstantActions during execution.
- *
- * @return Nothing.
- */
- public void setDDLTableDescriptor(TableDescriptor td);
-
- /**
- * Get the TableDescriptor for the target of
- * DDL.
- *
- * @return The TableDescriptor for the target of
- * DDL.
- */
- public TableDescriptor getDDLTableDescriptor();
-
- /**
- * Set the maximum # of rows. (# of rows that can
- * be returned by a ResultSet. 0 means no limit.)
- *
- * @param maxRows Maximum # of rows. (0 means no limit.)
- *
- * @return Nothing.
- */
- public void setMaxRows(int maxRows);
-
- /**
- * Get the maximum # of rows. (# of rows that can
- * be returned by a ResultSet. 0 means no limit.)
- *
- * @return Maximum # of rows. (0 means no limit.)
- */
- public int getMaxRows();
-
- /**
- * Is this Activation for a cursor?
- *
- * @return Whether or not this Activation is for a cursor.
- */
- public boolean isCursorActivation();
-
- /**
- * Save the ResultSet for the target
- * of an update/delete to a VTI.
- *
- * @return Nothing.
- */
- public void setTargetVTI(java.sql.ResultSet targetVTI);
-
- /**
- * Get the ResultSet for the target
- * of an update/delete to a VTI.
- *
- * @return The ResultSet for the target
- * of an update/delete to a VTI.
- */
- public java.sql.ResultSet getTargetVTI();
-
- public ConstantAction getConstantAction();
-
- //store a reference to the parent table result sets
- public void setParentResultSet(TemporaryRowHolder rs, String resultSetId);
-
- /**
- * get the reference to parent table ResultSets, that will be needed by the
- * referential action dependent table scans.
- */
- public Vector getParentResultSet(String resultSetId);
-
- //clear the parent resultset hash table;
- public void clearParentResultSets();
-
- public Hashtable getParentResultSets();
-
- /**
- * beetle 3865: updateable cursor using index. A way of communication
- * between cursor activation and update activation.
- */
- public void setForUpdateIndexScan(CursorResultSet forUpdateResultSet);
-
- public CursorResultSet getForUpdateIndexScan();
-
- /**
- Return the set of dynamical created result sets, for procedures.
- Base implementation returns null, a generated class for a procedure overwrites
- this with a real implementation.
- @return null if no dynamic results exists. Otherwise an array of ResultSet
- arrays, each of length one containing null or a reference to a ResultSet.
- */
- public java.sql.ResultSet[][] getDynamicResults();
-
- /**
- Return the maximum number of dynamical created result sets from the procedure definition.
- Base implementation returns 0, a generated class for a procedure overwrites
- this with a real implementation.
- */
- public int getMaxDynamicResults();
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+
+import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+
+import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
+import org.apache.derby.iapi.sql.execute.ExecRow;
+import org.apache.derby.iapi.sql.execute.ExecutionFactory;
+import org.apache.derby.iapi.sql.execute.NoPutResultSet;
+import org.apache.derby.iapi.sql.execute.ConstantAction;
+import org.apache.derby.iapi.sql.execute.CursorResultSet;
+import org.apache.derby.iapi.sql.execute.TemporaryRowHolder;
+
+import org.apache.derby.iapi.store.access.ConglomerateController;
+import org.apache.derby.iapi.store.access.ScanController;
+import org.apache.derby.iapi.store.access.TransactionController;
+
+import org.apache.derby.iapi.types.DataValueFactory;
+
+import org.apache.derby.iapi.types.RowLocation;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import java.sql.SQLWarning;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Hashtable;
+
+
+/**
+ * An activation contains all the local state information necessary
+ * to execute a re-entrant PreparedStatement. The way it will actually work
+ * is that a PreparedStatement will have an executable plan, which will be
+ * a generated class. All of the local state will be variables in the class.
+ * Creating a new instance of the executable plan will create the local state
+ * variables. This means that an executable plan must implement this interface,
+ * and that the PreparedStatement.getActivation() method will do a
+ * "new" operation on the executable plan.
+ * <p>
+ * The fixed implementations of Activation in the Execution impl
+ * package are used as skeletons for the classes generated for statements
+ * when they are compiled.
+ * <p>
+ * There are no fixed implementations of Activation for statements;
+ * a statement has an activation generated for it when it is compiled.
+ *
+ * @author Jeff Lichtman
+ */
+
+public interface Activation
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ * Resets the activation to the "pre-execution" state -
+ * that is, the state where it can be used to begin a new execution.
+ * Frees local buffers, stops scans, resets counters to zero, sets
+ * current date and time to an unitialized state, etc.
+ *
+ * @return Nothing
+ * @exception StandardException thrown on failure
+ */
+ void reset() throws StandardException;
+
+ /**
+ * JDBC requires that all select statements be converted into cursors,
+ * and that the cursor name be settable for each execution of a select
+ * statement. The Language Module will support this, so that the JDBC
+ * driver will not have to parse JSQL text. This method will have no
+ * effect when called on non-select statements.
+ * <p>
+ * There will be a JSQL statement to disable the "cursorization" of
+ * all select statements. For non-cursorized select statements, this
+ * method will have no effect.
+ * <p>
+ * This has no effect if the activation has been closed.
+ * <p>
+ * @param cursorName The cursor name to use.
+ */
+ void setCursorName(String cursorName);
+
+ /**
+ * Temporary tables can be declared with ON COMMIT DELETE ROWS. But if the table has a held curosr open at
+ * commit time, data should not be deleted from the table. This method, (gets called at commit time) checks if this
+ * activation held cursor and if so, does that cursor reference the passed temp table name.
+ *
+ * @return true if this activation has held cursor and if it references the passed temp table name
+ */
+ public boolean checkIfThisActivationHasHoldCursor(String tableName);
+
+ /**
+ * Gets the ParameterValueSet for this execution of the statement.
+ *
+ * @return The ParameterValueSet for this execution of the
+ * statement. Returns NULL if there are no parameters.
+ */
+ ParameterValueSet getParameterValueSet();
+
+ /**
+ * Sets the parameter values for this execution of the statement.
+ * <p>
+ * Has no effect if the activation has been closed.
+ *
+ * <p>
+ * NOTE: The setParameters() method is currently unimplemented.
+ * A statement with parameters will generate its own ParameterValueSet,
+ * which can be gotten with the getParameterValueSet() method (above).
+ * The idea behind setParameters() is to improve performance when
+ * operating across a network by allowing all the parameters to be set
+ * in one call, as opposed to one call per parameter.
+ *
+ * @param parameterValues The values of the parameters.
+ *
+ * @return Nothing
+ */
+ void setParameters(ParameterValueSet parameterValues, DataTypeDescriptor[] parameterTypes) throws StandardException;
+
+ /**
+ * When the prepared statement is executed, it passes
+ * execution on to the activation execution was requested for.
+ *
+ * @return the ResultSet for further manipulation, if any.
+ *
+ * @exception StandardException Thrown on failure
+ */
+ ResultSet execute() throws StandardException;
+
+ /**
+ Closing an activation statement marks it as unusable. Any other
+ requests made on it will fail. An activation should be
+ marked closed when it is expected to not be used any longer,
+ i.e. when the connection for it is closed, or it has suffered some
+ sort of severe error. This will also close its result set and
+ release any resources it holds e.g. for parameters.
+ <P>
+ Any class that implements this must be prepared to be executed
+ from garbage collection, ie. there is no matching context stack.
+
+ @exception StandardException Thrown on failure
+ */
+ void close() throws StandardException;
+
+ /**
+ Find out if the activation is closed or not.
+
+ @return true if the Activation has been closed.
+ */
+ boolean isClosed();
+
+ /**
+ Set this Activation for a single execution.
+ E.g. a java.sql.Statement execution.
+ */
+ void setSingleExecution();
+
+ /**
+ Returns true if this Activation is only going to be used for
+ one execution.
+ */
+ boolean isSingleExecution();
+
+ /**
+ Returns the chained list of warnings. Returns null
+ if there are no warnings.
+ */
+ SQLWarning getWarnings();
+
+ /**
+ Add a warning to the activation
+ */
+ void addWarning(SQLWarning w);
+
+ /**
+ Clear the activation's warnings.
+ */
+ void clearWarnings();
+
+ /**
+ * Get the language connection context associated with this activation
+ */
+ public LanguageConnectionContext getLanguageConnectionContext();
+
+ /**
+ * Get the Execution TransactionController associated with this
+ * activation/lcc.
+ */
+ TransactionController getTransactionController();
+
+ /**
+ * Returns the current result set for this activation, i.e.
+ * the one returned by the last execute() call. If there has
+ * been no execute call or the activation has been reset or closed,
+ * a null is returned.
+ *
+ * @return the current ResultSet of this activation.
+ */
+ ResultSet getResultSet();
+
+ /**
+ * Sets the ResultSet to be returned by getResultSet() to null.
+ */
+ void clearResultSet();
+
+ /**
+ * Generated plans have a current row field for ease in defining
+ * the methods and finding them dynamically. The interface is
+ * used to set the row before a dynamic method that uses it is
+ * invoked.
+ * <p>
+ * When all processing on the currentRow has been completed,
+ * callers should call activation.clearCurrentRow(resultSetNumber)
+ * to ensure that no unnecessary references are retained to rows.
+ * This will allow the rows no longer in use to be collected by
+ * the garbage collecter.
+ *
+ * @param currentRow The row to be operated upon.
+ * @param resultSetNumber The resultSetNumber for the current ResultSet
+ *
+ * @return Nothing
+ *
+ */
+ void setCurrentRow(ExecRow currentRow, int resultSetNumber);
+
+ /**
+ * Generated plans have a current row field for ease in defining
+ * the methods and finding them dynamically. The interface is
+ * used to set the row before a dynamic method that uses it is
+ * invoked.
+ * <p>
+ * When all processing on the currentRow has been completed,
+ * callers should call activation.clearCurrentRow(resultSetNumber)
+ * to ensure that no unnecessary references are retained to rows.
+ * This will allow the rows no longer in use to be collected by
+ * the garbage collecter.
+ *
+ * @param resultSetNumber The resultSetNumber for the current ResultSet
+ *
+ * @return Nothing
+ */
+ /* RESOLVE - this method belongs on an internal, not external, interface */
+ void clearCurrentRow(int resultSetNumber);
+
+ /**
+ * Get the prepared statement that this activation is for.
+ *
+ * @return the prepared statement this activation is for.
+ *
+ */
+ ExecPreparedStatement getPreparedStatement();
+
+ /**
+ Check the validity of the current executing statement. Needs to be
+ called after a statement has obtained the relevant table locks on
+ the
+ */
+ public void checkStatementValidity() throws StandardException;
+
+ /**
+ * Get the result description for this activation, if it has one.
+ *
+ * @return result description for this activation, if it has one;
+ * otherwise, null.
+ */
+ ResultDescription getResultDescription();
+
+ /**
+ * Get the DataValueFactory
+ *
+ * @return DataValueFactory
+ */
+ DataValueFactory getDataValueFactory();
+
+ /**
+ * Get the ExecutionFactory
+ *
+ * @return ExecutionFactory
+ */
+ ExecutionFactory getExecutionFactory();
+
+ /**
+ Get the saved RowLocation.
+
+ @param itemNumber The saved item number.
+
+ @return A RowLocation template for the conglomerate
+ */
+ public RowLocation getRowLocationTemplate(int itemNumber);
+
+ /**
+ Get the number of subqueries in the entire query.
+ @return int The number of subqueries in the entire query.
+ */
+ public int getNumSubqueries();
+
+ /**
+ * Return the cursor name of this activation. This will differ
+ * from its ResultSet's cursor name if it has been
+ * altered with setCursorName. Thus this always returns the cursor
+ * name of the next execution of this activation. The cursor name
+ * of the current execution must be obtained from the ResultSet.
+ * or this.getResultSet.getCursorName() [with null checking].
+ * <p>
+ * Statements that do not support cursors will return a null.
+ * <p>
+ * @return The cursor name.
+ */
+ public String getCursorName();
+
+ /**
+ * Return the holdability of this activation.
+ * <p>
+ * @return The holdability of this activation.
+ */
+ public boolean getResultSetHoldability();
+
+ /**
+ * Set current resultset holdability.
+ *
+ * @param resultSetHoldability The new resultset holdability.
+ *
+ * @return Nothing.
+ */
+ public void setResultSetHoldability(boolean resultSetHoldability);
+
+ /**
+ * Set the auto-generated keys resultset mode to true for this activation.
+ *
+ * The specific columns for auto-generated keys resultset can be requested by
+ * passing column positions array
+ *
+ * The specific columns for auto-generated keys resultset can be requested by
+ * passing column names array
+ *
+ * Both the parameters would be null if user didn't request specific keys.
+ * Otherwise, the user could request specific columns by passing column positions
+ * or names array but not both.
+ *
+ * @param columnIndexes Request specific columns in auto-generated keys
+ * resultset by passing column positions. null means no specific columns
+ * requested by position
+ *
+ * @param columnNames Request specific columns in auto-generated keys
+ * resultset by passing column names. null means no specific columns
+ * requested by position
+ *
+ * @return Nothing.
+ */
+ public void setAutoGeneratedKeysResultsetInfo(int[] columnIndexes, String[] columnNames);
+
+ /**
+ * Returns true if auto-generated keys resultset request was made for this
+ * avtivation.
+ * <p>
+ * @return auto-generated keys resultset mode for this activation.
+ */
+ public boolean getAutoGeneratedKeysResultsetMode();
+
+ /**
+ * Returns the column positions array of columns requested in auto-generated
+ * keys resultset for this avtivation. Returns null if no specific column
+ * requested by positions
+ * <p>
+ * @return column positions array of columns requested.
+ */
+ public int[] getAutoGeneratedKeysColumnIndexes();
+
+ /**
+ * Returns the column names array of columns requested in auto-generated
+ * keys resultset for this avtivation. Returns null if no specific column
+ * requested by names
+ * <p>
+ * @return column names array of columns requested.
+ */
+ public String[] getAutoGeneratedKeysColumnNames();
+
+ /**
+ * Mark the activation as unused.
+ */
+ public void markUnused();
+
+ /**
+ * Is the activation in use?
+ *
+ * @return true/false
+ */
+ public boolean isInUse();
+
+ /**
+ * Tell this activation that the given ResultSet was found to have
+ * the given number of rows. This is used during execution to determine
+ * whether a table has grown or shrunk. If a table's size changes
+ * significantly, the activation may invalidate its PreparedStatement
+ * to force recompilation.
+ *
+ * Note that the association of row counts with ResultSets is kept
+ * in the activation class, not in the activation itself. This
+ * means that this method must be synchronized.
+ *
+ * This method is not required to check the number of rows on each
+ * call. Because of synchronization, this check is likely to be
+ * expensive, so it may only check every hundred calls or so.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void informOfRowCount(NoPutResultSet resultSet, long rowCount)
+ throws StandardException;
+
+ /**
+ * Get the ConglomerateController, if any, that has already
+ * been opened for the heap when scaning for an update or delete.
+ * (Saves opening the ConglomerateController twice.)
+ *
+ * @return The ConglomerateController, if available, to use for the update.
+ */
+ public ConglomerateController getHeapConglomerateController();
+
+ /**
+ * Set the ConglomerateController to be used for an update or delete.
+ * (Saves opening the ConglomerateController twice.)
+ *
+ * @param updateHeapCC The ConglomerateController to reuse for the update or delete.
+ *
+ * @return Nothing.
+ */
+ public void setHeapConglomerateController(ConglomerateController updateHeapCC);
+
+ /**
+ * Clear the ConglomerateController to be used for an update or delete.
+ * (Saves opening the ConglomerateController twice.)
+ *
+ * @return Nothing.
+ */
+ public void clearHeapConglomerateController();
+
+ /**
+ * Get the ScanController, if any, that has already
+ * been opened for the index when scaning for an update or delete.
+ * (Saves opening the ScanController twice.)
+ *
+ * @return The ScanController, if available, to use for the update.
+ */
+ public ScanController getIndexScanController();
+
+ /**
+ * Set the ScanController to be used for an update or delete,
+ * when scanning an index that will also be updated
+ * (Saves opening the ScanController twice.)
+ *
+ * @param indexSC The ScanController to reuse for the update or delete.
+ *
+ * @return Nothing.
+ */
+ public void setIndexScanController(ScanController indexSC);
+
+ /**
+ * Get the conglomerate number of the index, if any, that has already
+ * been opened for scaning for an update or delete.
+ * (Saves opening the ScanController twice.)
+ *
+ * @return The conglomerate number, if available, to use for the update.
+ */
+ public long getIndexConglomerateNumber();
+
+ /**
+ * Set the conglomerate number of the index to be used for an update or delete,
+ * when scanning an index that will also be updated
+ * (Saves opening the ScanController twice.)
+ *
+ * @param indexConglomerateNumber The conglomerate number of the index to reuse for the update or delete.
+ *
+ * @return Nothing.
+ */
+ public void setIndexConglomerateNumber(long indexConglomerateNumber);
+
+ /**
+ * Clear the info for the index to be re-used for update/delete.
+ * (ScanController and conglomerate number.)
+ *
+ * @return Nothing.
+ */
+ public void clearIndexScanInfo();
+
+ /**
+ * Mark the Activation as being for create table.
+ * (NOTE: We can do certain optimizations for
+ * create table that we can't do for other DDL.)
+ *
+ * @return Nothing.
+ */
+ public void setForCreateTable();
+
+ /**
+ * Get whether or not this activation is for
+ * create table.
+ * (NOTE: We can do certain optimizations for
+ * create table that we can't do for other DDL.)
+ *
+ * @return Whether or not this activation is for
+ * create table.
+ */
+ public boolean getForCreateTable();
+
+ /**
+ * Save the TableDescriptor for the target of
+ * DDL so that it can be passed between the
+ * various ConstantActions during execution.
+ *
+ * @return Nothing.
+ */
+ public void setDDLTableDescriptor(TableDescriptor td);
+
+ /**
+ * Get the TableDescriptor for the target of
+ * DDL.
+ *
+ * @return The TableDescriptor for the target of
+ * DDL.
+ */
+ public TableDescriptor getDDLTableDescriptor();
+
+ /**
+ * Set the maximum # of rows. (# of rows that can
+ * be returned by a ResultSet. 0 means no limit.)
+ *
+ * @param maxRows Maximum # of rows. (0 means no limit.)
+ *
+ * @return Nothing.
+ */
+ public void setMaxRows(int maxRows);
+
+ /**
+ * Get the maximum # of rows. (# of rows that can
+ * be returned by a ResultSet. 0 means no limit.)
+ *
+ * @return Maximum # of rows. (0 means no limit.)
+ */
+ public int getMaxRows();
+
+ /**
+ * Is this Activation for a cursor?
+ *
+ * @return Whether or not this Activation is for a cursor.
+ */
+ public boolean isCursorActivation();
+
+ /**
+ * Save the ResultSet for the target
+ * of an update/delete to a VTI.
+ *
+ * @return Nothing.
+ */
+ public void setTargetVTI(java.sql.ResultSet targetVTI);
+
+ /**
+ * Get the ResultSet for the target
+ * of an update/delete to a VTI.
+ *
+ * @return The ResultSet for the target
+ * of an update/delete to a VTI.
+ */
+ public java.sql.ResultSet getTargetVTI();
+
+ public ConstantAction getConstantAction();
+
+ //store a reference to the parent table result sets
+ public void setParentResultSet(TemporaryRowHolder rs, String resultSetId);
+
+ /**
+ * get the reference to parent table ResultSets, that will be needed by the
+ * referential action dependent table scans.
+ */
+ public Vector getParentResultSet(String resultSetId);
+
+ //clear the parent resultset hash table;
+ public void clearParentResultSets();
+
+ public Hashtable getParentResultSets();
+
+ /**
+ * beetle 3865: updateable cursor using index. A way of communication
+ * between cursor activation and update activation.
+ */
+ public void setForUpdateIndexScan(CursorResultSet forUpdateResultSet);
+
+ public CursorResultSet getForUpdateIndexScan();
+
+ /**
+ Return the set of dynamical created result sets, for procedures.
+ Base implementation returns null, a generated class for a procedure overwrites
+ this with a real implementation.
+ @return null if no dynamic results exists. Otherwise an array of ResultSet
+ arrays, each of length one containing null or a reference to a ResultSet.
+ */
+ public java.sql.ResultSet[][] getDynamicResults();
+
+ /**
+ Return the maximum number of dynamical created result sets from the procedure definition.
+ Base implementation returns 0, a generated class for a procedure overwrites
+ this with a real implementation.
+ */
+ public int getMaxDynamicResults();
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageFactory.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageFactory.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageFactory.java Fri Sep 24 10:33:20 2004
@@ -1,80 +1,80 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.services.loader.ClassInspector;
-
-/**
- * Factory interface for the Language.Interface protocol.
- * This is used via the Database API by users, and is presented
- * as a System Module (not a service module). That could change,
- * but for now this is valid for any database.
- *
- * @author Jeff Lichtman
- */
-public interface LanguageFactory
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- Used to locate this factory by the Monitor basic service.
- There needs to be a language factory per database.
- */
- String MODULE = "org.apache.derby.iapi.sql.LanguageFactory";
-
- /**
- * Get a ParameterValueSet
- *
- * @param numParms The number of parameters in the
- * ParameterValueSet
- * @param hasReturnParam true if this parameter set
- * has a return parameter. The return parameter
- * is always the 1st parameter in the list. It
- * is due to a callableStatement like this: <i>
- * ? = CALL myMethod()</i>
- *
- * @return A new ParameterValueSet with the given number of parms
- */
- ParameterValueSet newParameterValueSet(ClassInspector ci, int numParms, boolean hasReturnParam);
-
- /**
- * Get a new result description from the input result
- * description. Picks only the columns in the column
- * array from the inputResultDescription.
- *
- * @param inputResultDescription the input rd
- * @param theCols non null array of ints
- *
- * @return ResultDescription the rd
- */
- public ResultDescription getResultDescription
- (
- ResultDescription inputResultDescription,
- int[] theCols
- );
-
- /**
- * Get a new result description
- *
- * @param cols an array of col descriptors
- * @param type the statement type
- *
- * @return ResultDescription the rd
- */
- public ResultDescription getResultDescription
- (
- ResultColumnDescriptor[] cols,
- String type
- );
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.loader.ClassInspector;
+
+/**
+ * Factory interface for the Language.Interface protocol.
+ * This is used via the Database API by users, and is presented
+ * as a System Module (not a service module). That could change,
+ * but for now this is valid for any database.
+ *
+ * @author Jeff Lichtman
+ */
+public interface LanguageFactory
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ Used to locate this factory by the Monitor basic service.
+ There needs to be a language factory per database.
+ */
+ String MODULE = "org.apache.derby.iapi.sql.LanguageFactory";
+
+ /**
+ * Get a ParameterValueSet
+ *
+ * @param numParms The number of parameters in the
+ * ParameterValueSet
+ * @param hasReturnParam true if this parameter set
+ * has a return parameter. The return parameter
+ * is always the 1st parameter in the list. It
+ * is due to a callableStatement like this: <i>
+ * ? = CALL myMethod()</i>
+ *
+ * @return A new ParameterValueSet with the given number of parms
+ */
+ ParameterValueSet newParameterValueSet(ClassInspector ci, int numParms, boolean hasReturnParam);
+
+ /**
+ * Get a new result description from the input result
+ * description. Picks only the columns in the column
+ * array from the inputResultDescription.
+ *
+ * @param inputResultDescription the input rd
+ * @param theCols non null array of ints
+ *
+ * @return ResultDescription the rd
+ */
+ public ResultDescription getResultDescription
+ (
+ ResultDescription inputResultDescription,
+ int[] theCols
+ );
+
+ /**
+ * Get a new result description
+ *
+ * @param cols an array of col descriptors
+ * @param type the statement type
+ *
+ * @return ResultDescription the rd
+ */
+ public ResultDescription getResultDescription
+ (
+ ResultColumnDescriptor[] cols,
+ String type
+ );
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageProperties.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageProperties.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/LanguageProperties.java Fri Sep 24 10:33:20 2004
@@ -1,42 +1,42 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-/**
- * This is a holder of language properties that are
- * exposed users. Consolodate all properties here.
- */
-public interface LanguageProperties
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- /*
- ** BulkFetch
- **
- ** The default size needs some explaining. As
- ** of 7/14/98, the most efficient way for access
- ** to return rows from a table is basically by
- ** reading/qualifying/returning all the rows in
- ** one page. If you are read in many many rows
- ** at a time the performance gain is only marginally
- ** better. Anyway, since even a small number of
- ** rows per read helps, and since there is no good
- ** way to get access to retrieve the rows page
- ** by page, we use 16 totally arbitrarily. Ultimately,
- ** this should be dynamically sized -- in which
- ** case we wouldn't need this default.
- */
- static final String BULK_FETCH_PROP = "derby.language.bulkFetchDefault";
- static final String BULK_FETCH_DEFAULT = "16";
- static final int BULK_FETCH_DEFAULT_INT = 16;
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+/**
+ * This is a holder of language properties that are
+ * exposed users. Consolodate all properties here.
+ */
+public interface LanguageProperties
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ /*
+ ** BulkFetch
+ **
+ ** The default size needs some explaining. As
+ ** of 7/14/98, the most efficient way for access
+ ** to return rows from a table is basically by
+ ** reading/qualifying/returning all the rows in
+ ** one page. If you are read in many many rows
+ ** at a time the performance gain is only marginally
+ ** better. Anyway, since even a small number of
+ ** rows per read helps, and since there is no good
+ ** way to get access to retrieve the rows page
+ ** by page, we use 16 totally arbitrarily. Ultimately,
+ ** this should be dynamically sized -- in which
+ ** case we wouldn't need this default.
+ */
+ static final String BULK_FETCH_PROP = "derby.language.bulkFetchDefault";
+ static final String BULK_FETCH_DEFAULT = "16";
+ static final int BULK_FETCH_DEFAULT_INT = 16;
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ParameterValueSet.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ParameterValueSet.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ParameterValueSet.java Fri Sep 24 10:33:20 2004
@@ -1,270 +1,270 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import java.sql.Date;
-import java.sql.Time;
-import java.sql.Timestamp;
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.types.DataValueDescriptor;
-
-/**
- * A ParameterValueSet is a set of parameter values that can be assembled by a
- * JDBC driver and passed to a PreparedStatement all at once. The fact that
- * they are all passed at once can reduce the communication overhead between
- * client and server.
- *
- * @author Jeff Lichtman
- */
-public interface ParameterValueSet
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
-
- /**
- Set the mode of the parameter, called when setting up static method calls and stored procedures.
- Otherwise the parameter type will default to an IN parameter.
- */
- void setParameterMode(int position, int mode);
-
- /**
- * Set a parameter position to a DataValueDescriptor.
- *
- * NOTE: This method assumes the caller will not pass a position that's
- * out of range. The implementation may have an assertion that the position
- * is in range.
- *
- * @param sdv The DataValueDescriptor to set
- * @param position The parameter position to set it at
- * @param jdbcTypeId The corresponding JDBC types from java.sql.Types
- * @param className The declared class name for the type.
- */
-
- void setStorableDataValue(DataValueDescriptor sdv, int position, int jdbcTypeId, String className);
-
-
- //////////////////////////////////////////////////////////////////
- //
- // CALLABLE STATEMENT
- //
- //////////////////////////////////////////////////////////////////
-
- /**
- * Mark the parameter as an output parameter.
- *
- * @param parameterIndex The ordinal position of a parameter to set
- * to the given value.
- * @param sqlType A type from java.sql.Types
- * @param scale the scale to use. -1 means ignore scale
- *
- * @exception StandardException on error
- */
- void registerOutParameter(int parameterIndex, int sqlType, int scale)
- throws StandardException;
-
-
- /**
- * Get the value of a parameter as a Java object.
- *
- * <p>This method returns a Java object whose type coresponds to the SQL
- * type that was registered for this parameter using registerOutParameter.
- *
- * <p>Note that this method may be used to read
- * datatabase-specific, abstract data types. This is done by
- * specifying a targetSqlType of java.sql.types.OTHER, which
- * allows the driver to return a database-specific Java type.
- *
- * @param parameterIndex The first parameter is 1, the second is 2, ...
- * @return A java.lang.Object holding the OUT parameter value.
- * @exception StandardException if a database-access error occurs.
- * @see java.sql.Types
- */
- Object getObject(int parameterIndex) throws StandardException;
-
- //////////////////////////////////////////////////////////////////
- //
- // MISC STATEMENT
- //
- //////////////////////////////////////////////////////////////////
-
- /**
- * Sets all parameters to an uninitialized state. An exception will be
- * thrown if the caller tries to execute a PreparedStatement when one
- * or more parameters is uninitialized (i.e. has not had
- * setParameterValue() called on it.
- *
- * @return Nothing
- */
- void clearParameters();
-
- /**
- * Returns the number of parameters in this set.
- *
- * @return The number of parameters in this set.
- */
- public int getParameterCount();
-
- /**
- * Returns the parameter at the given position.
- *
- * @return The parameter at the given position.
- * @exception StandardException Thrown on error
- */
- public DataValueDescriptor getParameter( int position ) throws StandardException;
-
-
- /**
- * Returns the parameter at the given position in order to set it.
- Setting via an unknown object type must use setParameterAsObject()
- to ensure correct typing.
-
- *
- * @return The parameter at the given position.
- * @exception StandardException Thrown on error
- */
- public DataValueDescriptor getParameterForSet( int position ) throws StandardException;
-
- /**
- Set the value of this parameter to the passed in Object.
-
- @return The parameter at the given position.
- @exception StandardException Thrown on error
- */
- void setParameterAsObject(int parameterIndex, Object value) throws StandardException;
-
-
- public DataValueDescriptor getParameterForGet( int position ) throws StandardException;
-
- /**
- * Tells whether all the parameters are set and ready for execution.
- OUT and Cloudscape static method INOUT parameters are not required to be set.
- *
- * @return true if all parameters are set, false if at least one
- * parameter is not set.
- */
- boolean allAreSet();
-
- /**
- * Clone the ParameterValueSet and its contents.
- *
- * @return ParameterValueSet A clone of the ParameterValueSet and its contents.
- */
- ParameterValueSet getClone();
-
- /**
- * Validate the parameters. This is done for situations where
- * we cannot validate everything in the setXXX() calls. In
- * particular, before we do an execute() on a CallableStatement,
- * we need to go through the parameters and make sure that
- * all parameters are set up properly. The motivator for this
- * is that setXXX() can be called either before or after
- * registerOutputParamter(), we cannot be sure we have the types
- * correct until we get to execute().
- *
- * @exception StandardException if the parameters aren't valid
- */
- void validate() throws StandardException;
-
- /**
- * Is there a return output parameter in this pvs. A return
- * parameter is from a CALL statement of the following
- * syntax: ? = CALL myMethod(). Note that a return
- * output parameter is NOT the same thing as an output
- * parameter; it is a special type of output parameter.
- *
- * @return true if it has a return parameter
- *
- */
- public boolean hasReturnOutputParameter();
-
- /**
- Check that there are not output parameters defined
- by the parameter set. If there are unknown parameter
- types they are forced to input types. i.e. Cloudscape static method
- calls with parameters that are array.
-
- @return true if a declared Java Procedure INOUT or OUT parameter is in the set, false otherwise.
- */
- public boolean checkNoDeclaredOutputParameters();
-
-
- // bug 4552 - "exec statement using" will return no parameters through parametermetadata
- /**
- * Is this pvs for using clause.
- *
- * @return true if it has a output parameter
- *
- */
- public boolean isUsingParameterValueSet();
-
- // bug 4552 - "exec statement using" will return no parameters through parametermetadata
- /**
- * Setthis pvs for using clause.
- */
- public void setUsingParameterValueSet();
-
- /**
- * Set the parameter values of the pvstarget to equal those
- * set in this PVS.
- * Used to transfer saved SPS parameters to the actual
- * prepared statement parameters once associated parameters
- * have been established. Assumes pvstarget is the same
- * length as this.
- * @param pvstarget ParameterValueSet which will recieve the values
-
- @exception StandardException values not compatible
- **/
- public void transferDataValues(ParameterValueSet pvstarget) throws StandardException;
-
- /**
- Return the mode of the parameter according to JDBC 3.0 ParameterMetaData
-
- *
- * @param parameterIndex the first parameter is 1, the second is 2, ...
- *
- */
- public short getParameterMode(int parameterIndex);
-
-
- /**
- * Set the value of the return parameter as a Java object.
- *
- * @param value the return value
- *
- * @exception StandardException if a database-access error occurs.
- */
- void setReturnValue(Object value) throws StandardException;
-
- /**
- * Return the scale of the given parameter index in this pvs.
- *
- * @param parameterIndex the first parameter is 1, the second is 2, ...
- *
- * @return scale
- */
- public int getScale(int parameterIndex);
-
- /**
- * Return the precision of the given parameter index in this pvs.
- *
- * @param parameterIndex the first parameter is 1, the second is 2, ...
- *
- * @return precision
- */
- public int getPrecision(int parameterIndex);
-
-
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+/**
+ * A ParameterValueSet is a set of parameter values that can be assembled by a
+ * JDBC driver and passed to a PreparedStatement all at once. The fact that
+ * they are all passed at once can reduce the communication overhead between
+ * client and server.
+ *
+ * @author Jeff Lichtman
+ */
+public interface ParameterValueSet
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+
+ /**
+ Set the mode of the parameter, called when setting up static method calls and stored procedures.
+ Otherwise the parameter type will default to an IN parameter.
+ */
+ void setParameterMode(int position, int mode);
+
+ /**
+ * Set a parameter position to a DataValueDescriptor.
+ *
+ * NOTE: This method assumes the caller will not pass a position that's
+ * out of range. The implementation may have an assertion that the position
+ * is in range.
+ *
+ * @param sdv The DataValueDescriptor to set
+ * @param position The parameter position to set it at
+ * @param jdbcTypeId The corresponding JDBC types from java.sql.Types
+ * @param className The declared class name for the type.
+ */
+
+ void setStorableDataValue(DataValueDescriptor sdv, int position, int jdbcTypeId, String className);
+
+
+ //////////////////////////////////////////////////////////////////
+ //
+ // CALLABLE STATEMENT
+ //
+ //////////////////////////////////////////////////////////////////
+
+ /**
+ * Mark the parameter as an output parameter.
+ *
+ * @param parameterIndex The ordinal position of a parameter to set
+ * to the given value.
+ * @param sqlType A type from java.sql.Types
+ * @param scale the scale to use. -1 means ignore scale
+ *
+ * @exception StandardException on error
+ */
+ void registerOutParameter(int parameterIndex, int sqlType, int scale)
+ throws StandardException;
+
+
+ /**
+ * Get the value of a parameter as a Java object.
+ *
+ * <p>This method returns a Java object whose type coresponds to the SQL
+ * type that was registered for this parameter using registerOutParameter.
+ *
+ * <p>Note that this method may be used to read
+ * datatabase-specific, abstract data types. This is done by
+ * specifying a targetSqlType of java.sql.types.OTHER, which
+ * allows the driver to return a database-specific Java type.
+ *
+ * @param parameterIndex The first parameter is 1, the second is 2, ...
+ * @return A java.lang.Object holding the OUT parameter value.
+ * @exception StandardException if a database-access error occurs.
+ * @see java.sql.Types
+ */
+ Object getObject(int parameterIndex) throws StandardException;
+
+ //////////////////////////////////////////////////////////////////
+ //
+ // MISC STATEMENT
+ //
+ //////////////////////////////////////////////////////////////////
+
+ /**
+ * Sets all parameters to an uninitialized state. An exception will be
+ * thrown if the caller tries to execute a PreparedStatement when one
+ * or more parameters is uninitialized (i.e. has not had
+ * setParameterValue() called on it.
+ *
+ * @return Nothing
+ */
+ void clearParameters();
+
+ /**
+ * Returns the number of parameters in this set.
+ *
+ * @return The number of parameters in this set.
+ */
+ public int getParameterCount();
+
+ /**
+ * Returns the parameter at the given position.
+ *
+ * @return The parameter at the given position.
+ * @exception StandardException Thrown on error
+ */
+ public DataValueDescriptor getParameter( int position ) throws StandardException;
+
+
+ /**
+ * Returns the parameter at the given position in order to set it.
+ Setting via an unknown object type must use setParameterAsObject()
+ to ensure correct typing.
+
+ *
+ * @return The parameter at the given position.
+ * @exception StandardException Thrown on error
+ */
+ public DataValueDescriptor getParameterForSet( int position ) throws StandardException;
+
+ /**
+ Set the value of this parameter to the passed in Object.
+
+ @return The parameter at the given position.
+ @exception StandardException Thrown on error
+ */
+ void setParameterAsObject(int parameterIndex, Object value) throws StandardException;
+
+
+ public DataValueDescriptor getParameterForGet( int position ) throws StandardException;
+
+ /**
+ * Tells whether all the parameters are set and ready for execution.
+ OUT and Cloudscape static method INOUT parameters are not required to be set.
+ *
+ * @return true if all parameters are set, false if at least one
+ * parameter is not set.
+ */
+ boolean allAreSet();
+
+ /**
+ * Clone the ParameterValueSet and its contents.
+ *
+ * @return ParameterValueSet A clone of the ParameterValueSet and its contents.
+ */
+ ParameterValueSet getClone();
+
+ /**
+ * Validate the parameters. This is done for situations where
+ * we cannot validate everything in the setXXX() calls. In
+ * particular, before we do an execute() on a CallableStatement,
+ * we need to go through the parameters and make sure that
+ * all parameters are set up properly. The motivator for this
+ * is that setXXX() can be called either before or after
+ * registerOutputParamter(), we cannot be sure we have the types
+ * correct until we get to execute().
+ *
+ * @exception StandardException if the parameters aren't valid
+ */
+ void validate() throws StandardException;
+
+ /**
+ * Is there a return output parameter in this pvs. A return
+ * parameter is from a CALL statement of the following
+ * syntax: ? = CALL myMethod(). Note that a return
+ * output parameter is NOT the same thing as an output
+ * parameter; it is a special type of output parameter.
+ *
+ * @return true if it has a return parameter
+ *
+ */
+ public boolean hasReturnOutputParameter();
+
+ /**
+ Check that there are not output parameters defined
+ by the parameter set. If there are unknown parameter
+ types they are forced to input types. i.e. Cloudscape static method
+ calls with parameters that are array.
+
+ @return true if a declared Java Procedure INOUT or OUT parameter is in the set, false otherwise.
+ */
+ public boolean checkNoDeclaredOutputParameters();
+
+
+ // bug 4552 - "exec statement using" will return no parameters through parametermetadata
+ /**
+ * Is this pvs for using clause.
+ *
+ * @return true if it has a output parameter
+ *
+ */
+ public boolean isUsingParameterValueSet();
+
+ // bug 4552 - "exec statement using" will return no parameters through parametermetadata
+ /**
+ * Setthis pvs for using clause.
+ */
+ public void setUsingParameterValueSet();
+
+ /**
+ * Set the parameter values of the pvstarget to equal those
+ * set in this PVS.
+ * Used to transfer saved SPS parameters to the actual
+ * prepared statement parameters once associated parameters
+ * have been established. Assumes pvstarget is the same
+ * length as this.
+ * @param pvstarget ParameterValueSet which will recieve the values
+
+ @exception StandardException values not compatible
+ **/
+ public void transferDataValues(ParameterValueSet pvstarget) throws StandardException;
+
+ /**
+ Return the mode of the parameter according to JDBC 3.0 ParameterMetaData
+
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ *
+ */
+ public short getParameterMode(int parameterIndex);
+
+
+ /**
+ * Set the value of the return parameter as a Java object.
+ *
+ * @param value the return value
+ *
+ * @exception StandardException if a database-access error occurs.
+ */
+ void setReturnValue(Object value) throws StandardException;
+
+ /**
+ * Return the scale of the given parameter index in this pvs.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ *
+ * @return scale
+ */
+ public int getScale(int parameterIndex);
+
+ /**
+ * Return the precision of the given parameter index in this pvs.
+ *
+ * @param parameterIndex the first parameter is 1, the second is 2, ...
+ *
+ * @return precision
+ */
+ public int getPrecision(int parameterIndex);
+
+
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/PreparedStatement.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/PreparedStatement.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/PreparedStatement.java Fri Sep 24 10:33:20 2004
@@ -1,230 +1,230 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-
-import org.apache.derby.iapi.sql.depend.Dependent;
-import org.apache.derby.iapi.sql.depend.Provider;
-
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import java.sql.Timestamp;
-import java.sql.SQLWarning;
-
-/**
- * The PreparedStatement interface provides methods to execute prepared
- * statements, store them, and get metadata about them.
- *
- * @author Jeff Lichtman
- */
-public interface PreparedStatement
- extends Dependent, Provider
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- /**
- * Checks whether this PreparedStatement is up to date.
- * A PreparedStatement can become out of date if any of several
- * things happen:
- *
- * A schema used by the statement is dropped
- * A table used by the statement is dropped
- * A table used by the statement, or a column in such a table,
- * is altered in one of several ways: a column is dropped,
- * a privilege is dropped, a constraint is added or
- * dropped, an index is dropped.
- * A view used by the statement is dropped.
- *
- * In general, anything that happened since the plan was generated
- * that might cause the plan to fail, or to generate incorrect results,
- * will cause this method to return FALSE.
- *
- * @return TRUE if the PreparedStatement is up to date,
- * FALSE if it is not up to date
- */
- boolean upToDate() throws StandardException;
-
- /**
- * Re-prepare the statement if it is not up to date or,
- * if requested, simply not optimal.
- * If there are open cursors using this prepared statement,
- * then we will not be able to recompile the statement.
- *
- * @param lcc The LanguageConnectionContext.
- *
- * @exception StandardException thrown if unable to perform
- */
- void rePrepare(LanguageConnectionContext lcc)
- throws StandardException;
-
- /**
- * PreparedStatements are re-entrant - that is, more than one
- * execution can be active at a time for a single prepared statement.
- * An Activation contains all the local state information to
- * execute a prepared statement (as opposed to the constant
- * information, such as literal values and code). Each Activation
- * class contains the code specific to the prepared statement
- * represented by an instance of this class (PreparedStatement).
- *
- * @param lcc The LanguageConnectionContext.
- * @return The new activation.
- *
- * @exception StandardException Thrown on failure
- */
- Activation getActivation(LanguageConnectionContext lcc, boolean scrollable) throws StandardException;
-
- /**
- * Execute the PreparedStatement and return results.
- *<p>
- * There is no executeQuery() or
- * executeUpdate(); a method is provided in
- * ResultSet to tell whether to expect rows to be returned.
- *
- * @param activation The activation containing all the local state
- * to execute the plan.
- * @param executeQuery Whether or not called from a Statement.executeQuery()
- * @param executeUpdate Whether or not called from a Statement.executeUpdate()
- * @param rollbackParentContext True if 1) the statement context is
- * NOT a top-level context, AND 2) in the event of a statement-level
- * exception, the parent context needs to be rolled back, too.
- *
- * @return A ResultSet for a statement. A ResultSet represents
- * the results returned from the statement, if any.
- * Will return NULL if the plan for the PreparedStatement
- * has aged out of cache, or the plan is out of date.
- *
- * @exception StandardException Thrown on failure
- */
- ResultSet execute(Activation activation, boolean executeQuery, boolean executeUpdate,
- boolean rollbackParentContext) throws StandardException;
-
- /**
- Simple form of execute(). Creates a new single use activation and executes it,
- but also passes rollbackParentContext parameter (see above).
- */
- ResultSet execute(LanguageConnectionContext lcc, boolean rollbackParentContext)
- throws StandardException;
-
- /**
- * Get the ResultDescription for the statement. The ResultDescription
- * describes what the results look like: what are the rows and columns?
- * <p>
- * This is available here and on the ResultSet so that users can
- * see the shape of the result before they execute.
- *
- * @return A ResultDescription describing the results.
- *
- */
- ResultDescription getResultDescription();
-
- /**
- * Return true if the query node for this statement references SESSION schema tables.
- *
- * @return true if references SESSION schema tables, else false
- */
- boolean referencesSessionSchema();
-
- /**
- * Get an array of DataTypeDescriptors describing the types of the
- * parameters of this PreparedStatement. The Nth element of the array
- * describes the Nth parameter.
- *
- * @return An array of DataTypeDescriptors telling the
- * type, length, precision, scale, etc. of each
- * parameter of this PreparedStatement.
- */
- DataTypeDescriptor[] getParameterTypes();
-
- /**
- * Return the SQL string that this statement is for.
- *
- * @return the SQL string this statement is for.
- */
- String getSource();
-
- /**
- * Return the SPS Name for this statement.
- *
- * @return the SPS Name for this statement
- */
- String getSPSName();
-
- /**
- * Get the total compile time for the associated query in milliseconds.
- * Compile time can be divided into parse, bind, optimize and generate times.
- *
- * @return long The total compile time for the associated query in milliseconds.
- */
- public long getCompileTimeInMillis();
-
- /**
- * Get the parse time for the associated query in milliseconds.
- *
- * @return long The parse time for the associated query in milliseconds.
- */
- public long getParseTimeInMillis();
-
- /**
- * Get the bind time for the associated query in milliseconds.
- *
- * @return long The bind time for the associated query in milliseconds.
- */
- public long getBindTimeInMillis();
-
- /**
- * Get the optimize time for the associated query in milliseconds.
- *
- * @return long The optimize time for the associated query in milliseconds.
- */
- public long getOptimizeTimeInMillis();
-
- /**
- * Get the generate time for the associated query in milliseconds.
- *
- * @return long The generate time for the associated query in milliseconds.
- */
- public long getGenerateTimeInMillis();
-
- /**
- * Get the timestamp for the beginning of compilation
- *
- * @return Timestamp The timestamp for the beginning of compilation.
- */
- public Timestamp getBeginCompileTimestamp();
-
- /**
- * Get the timestamp for the end of compilation
- *
- * @return Timestamp The timestamp for the end of compilation.
- */
- public Timestamp getEndCompileTimestamp();
-
- /**
- * Returns whether or not this Statement requires should
- * behave atomically -- i.e. whether a user is permitted
- * to do a commit/rollback during the execution of this
- * statement.
- *
- * @return boolean Whether or not this Statement is atomic
- */
- boolean isAtomic();
-
- /**
- Return any compile time warnings. Null if no warnings exist.
- */
- public SQLWarning getCompileTimeWarnings();
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+
+import org.apache.derby.iapi.sql.depend.Dependent;
+import org.apache.derby.iapi.sql.depend.Provider;
+
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import java.sql.Timestamp;
+import java.sql.SQLWarning;
+
+/**
+ * The PreparedStatement interface provides methods to execute prepared
+ * statements, store them, and get metadata about them.
+ *
+ * @author Jeff Lichtman
+ */
+public interface PreparedStatement
+ extends Dependent, Provider
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ /**
+ * Checks whether this PreparedStatement is up to date.
+ * A PreparedStatement can become out of date if any of several
+ * things happen:
+ *
+ * A schema used by the statement is dropped
+ * A table used by the statement is dropped
+ * A table used by the statement, or a column in such a table,
+ * is altered in one of several ways: a column is dropped,
+ * a privilege is dropped, a constraint is added or
+ * dropped, an index is dropped.
+ * A view used by the statement is dropped.
+ *
+ * In general, anything that happened since the plan was generated
+ * that might cause the plan to fail, or to generate incorrect results,
+ * will cause this method to return FALSE.
+ *
+ * @return TRUE if the PreparedStatement is up to date,
+ * FALSE if it is not up to date
+ */
+ boolean upToDate() throws StandardException;
+
+ /**
+ * Re-prepare the statement if it is not up to date or,
+ * if requested, simply not optimal.
+ * If there are open cursors using this prepared statement,
+ * then we will not be able to recompile the statement.
+ *
+ * @param lcc The LanguageConnectionContext.
+ *
+ * @exception StandardException thrown if unable to perform
+ */
+ void rePrepare(LanguageConnectionContext lcc)
+ throws StandardException;
+
+ /**
+ * PreparedStatements are re-entrant - that is, more than one
+ * execution can be active at a time for a single prepared statement.
+ * An Activation contains all the local state information to
+ * execute a prepared statement (as opposed to the constant
+ * information, such as literal values and code). Each Activation
+ * class contains the code specific to the prepared statement
+ * represented by an instance of this class (PreparedStatement).
+ *
+ * @param lcc The LanguageConnectionContext.
+ * @return The new activation.
+ *
+ * @exception StandardException Thrown on failure
+ */
+ Activation getActivation(LanguageConnectionContext lcc, boolean scrollable) throws StandardException;
+
+ /**
+ * Execute the PreparedStatement and return results.
+ *<p>
+ * There is no executeQuery() or
+ * executeUpdate(); a method is provided in
+ * ResultSet to tell whether to expect rows to be returned.
+ *
+ * @param activation The activation containing all the local state
+ * to execute the plan.
+ * @param executeQuery Whether or not called from a Statement.executeQuery()
+ * @param executeUpdate Whether or not called from a Statement.executeUpdate()
+ * @param rollbackParentContext True if 1) the statement context is
+ * NOT a top-level context, AND 2) in the event of a statement-level
+ * exception, the parent context needs to be rolled back, too.
+ *
+ * @return A ResultSet for a statement. A ResultSet represents
+ * the results returned from the statement, if any.
+ * Will return NULL if the plan for the PreparedStatement
+ * has aged out of cache, or the plan is out of date.
+ *
+ * @exception StandardException Thrown on failure
+ */
+ ResultSet execute(Activation activation, boolean executeQuery, boolean executeUpdate,
+ boolean rollbackParentContext) throws StandardException;
+
+ /**
+ Simple form of execute(). Creates a new single use activation and executes it,
+ but also passes rollbackParentContext parameter (see above).
+ */
+ ResultSet execute(LanguageConnectionContext lcc, boolean rollbackParentContext)
+ throws StandardException;
+
+ /**
+ * Get the ResultDescription for the statement. The ResultDescription
+ * describes what the results look like: what are the rows and columns?
+ * <p>
+ * This is available here and on the ResultSet so that users can
+ * see the shape of the result before they execute.
+ *
+ * @return A ResultDescription describing the results.
+ *
+ */
+ ResultDescription getResultDescription();
+
+ /**
+ * Return true if the query node for this statement references SESSION schema tables.
+ *
+ * @return true if references SESSION schema tables, else false
+ */
+ boolean referencesSessionSchema();
+
+ /**
+ * Get an array of DataTypeDescriptors describing the types of the
+ * parameters of this PreparedStatement. The Nth element of the array
+ * describes the Nth parameter.
+ *
+ * @return An array of DataTypeDescriptors telling the
+ * type, length, precision, scale, etc. of each
+ * parameter of this PreparedStatement.
+ */
+ DataTypeDescriptor[] getParameterTypes();
+
+ /**
+ * Return the SQL string that this statement is for.
+ *
+ * @return the SQL string this statement is for.
+ */
+ String getSource();
+
+ /**
+ * Return the SPS Name for this statement.
+ *
+ * @return the SPS Name for this statement
+ */
+ String getSPSName();
+
+ /**
+ * Get the total compile time for the associated query in milliseconds.
+ * Compile time can be divided into parse, bind, optimize and generate times.
+ *
+ * @return long The total compile time for the associated query in milliseconds.
+ */
+ public long getCompileTimeInMillis();
+
+ /**
+ * Get the parse time for the associated query in milliseconds.
+ *
+ * @return long The parse time for the associated query in milliseconds.
+ */
+ public long getParseTimeInMillis();
+
+ /**
+ * Get the bind time for the associated query in milliseconds.
+ *
+ * @return long The bind time for the associated query in milliseconds.
+ */
+ public long getBindTimeInMillis();
+
+ /**
+ * Get the optimize time for the associated query in milliseconds.
+ *
+ * @return long The optimize time for the associated query in milliseconds.
+ */
+ public long getOptimizeTimeInMillis();
+
+ /**
+ * Get the generate time for the associated query in milliseconds.
+ *
+ * @return long The generate time for the associated query in milliseconds.
+ */
+ public long getGenerateTimeInMillis();
+
+ /**
+ * Get the timestamp for the beginning of compilation
+ *
+ * @return Timestamp The timestamp for the beginning of compilation.
+ */
+ public Timestamp getBeginCompileTimestamp();
+
+ /**
+ * Get the timestamp for the end of compilation
+ *
+ * @return Timestamp The timestamp for the end of compilation.
+ */
+ public Timestamp getEndCompileTimestamp();
+
+ /**
+ * Returns whether or not this Statement requires should
+ * behave atomically -- i.e. whether a user is permitted
+ * to do a commit/rollback during the execution of this
+ * statement.
+ *
+ * @return boolean Whether or not this Statement is atomic
+ */
+ boolean isAtomic();
+
+ /**
+ Return any compile time warnings. Null if no warnings exist.
+ */
+ public SQLWarning getCompileTimeWarnings();
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultColumnDescriptor.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultColumnDescriptor.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultColumnDescriptor.java Fri Sep 24 10:33:20 2004
@@ -1,88 +1,88 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-/**
- * A ResultColumnDescriptor describes a result column in a ResultSet.
- *
- * @author Jeff Lichtman
- */
-
-public interface ResultColumnDescriptor
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- * Returns a DataTypeDescriptor for the column. This DataTypeDescriptor
- * will not represent an actual value, it will only represent the type
- * that all values in the column will have.
- *
- * @return A DataTypeDescriptor describing the type of the column.
- */
- DataTypeDescriptor getType();
-
- /**
- * Returns the name of the Column.
- *
- * @return A String containing the name of the column.
- */
- String getName();
-
- /**
- * Get the name of the schema the Column is in, if any.
- *
- * @return A String containing the name of the schema the Column
- * is in. If the column is not in a schema (i.e. is a
- * derived column), it returns NULL.
- */
- String getSchemaName();
-
- /**
- * Get the name of the table the Column is in, if any.
- *
- * @return A String containing the name of the table the Column
- * is in. If the column is not in a table (i.e. is a
- * derived column), it returns NULL.
- */
- String getSourceTableName();
-
- /**
- * Get the position of the Column.
- * NOTE - position is 1-based.
- *
- * @return An int containing the position of the Column
- * within the table.
- */
- int getColumnPosition();
-
- /**
- * Tell us if the column is an autoincrement column or not.
- *
- * @return TRUE, if the column is a base column of a table and is an
- * autoincrement column.
- */
- boolean isAutoincrement();
-
- /*
- * NOTE: These interfaces are intended to support JDBC. There are some
- * JDBC methods on java.sql.ResultSetMetaData that have no equivalent
- * here, mainly because they are of questionable use to us. They are:
- * getCatalogName() (will we support catalogs?), getColumnLabel(),
- * isCaseSensitive(), isCurrency(),
- * isDefinitelyWritable(), isReadOnly(), isSearchable(), isSigned(),
- * isWritable()). The JDBC driver implements these itself, using
- * the data type information and knowing data type characteristics.
- */
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+/**
+ * A ResultColumnDescriptor describes a result column in a ResultSet.
+ *
+ * @author Jeff Lichtman
+ */
+
+public interface ResultColumnDescriptor
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ * Returns a DataTypeDescriptor for the column. This DataTypeDescriptor
+ * will not represent an actual value, it will only represent the type
+ * that all values in the column will have.
+ *
+ * @return A DataTypeDescriptor describing the type of the column.
+ */
+ DataTypeDescriptor getType();
+
+ /**
+ * Returns the name of the Column.
+ *
+ * @return A String containing the name of the column.
+ */
+ String getName();
+
+ /**
+ * Get the name of the schema the Column is in, if any.
+ *
+ * @return A String containing the name of the schema the Column
+ * is in. If the column is not in a schema (i.e. is a
+ * derived column), it returns NULL.
+ */
+ String getSchemaName();
+
+ /**
+ * Get the name of the table the Column is in, if any.
+ *
+ * @return A String containing the name of the table the Column
+ * is in. If the column is not in a table (i.e. is a
+ * derived column), it returns NULL.
+ */
+ String getSourceTableName();
+
+ /**
+ * Get the position of the Column.
+ * NOTE - position is 1-based.
+ *
+ * @return An int containing the position of the Column
+ * within the table.
+ */
+ int getColumnPosition();
+
+ /**
+ * Tell us if the column is an autoincrement column or not.
+ *
+ * @return TRUE, if the column is a base column of a table and is an
+ * autoincrement column.
+ */
+ boolean isAutoincrement();
+
+ /*
+ * NOTE: These interfaces are intended to support JDBC. There are some
+ * JDBC methods on java.sql.ResultSetMetaData that have no equivalent
+ * here, mainly because they are of questionable use to us. They are:
+ * getCatalogName() (will we support catalogs?), getColumnLabel(),
+ * isCaseSensitive(), isCurrency(),
+ * isDefinitelyWritable(), isReadOnly(), isSearchable(), isSigned(),
+ * isWritable()). The JDBC driver implements these itself, using
+ * the data type information and knowing data type characteristics.
+ */
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java Fri Sep 24 10:33:20 2004
@@ -1,78 +1,78 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-/**
- * The ResultDescription interface provides methods to get metadata on the
- * results returned by a statement.
- *
- * @author Jeff Lichtman
- */
-
-public interface ResultDescription
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- * Returns an identifier that tells what type of statement has been
- * executed. This can be used to determine what other methods to call
- * to get the results back from a statement. For example, a SELECT
- * statement returns rows and columns, while other statements don't,
- * so you would only call getColumnCount() or getColumnType() for
- * SELECT statements.
- *
- * @return A String identifier telling what type of statement this
- * is.
- */
- String getStatementType();
-
- /**
- * Returns the number of columns in the result set.
- *
- * @return The number of columns in the result set.
- */
- int getColumnCount();
-
- /**
- Return information about all the columns.
- */
- public ResultColumnDescriptor[] getColumnInfo();
-
- /**
- * Returns a ResultColumnDescriptor for the column, given the oridinal
- * position of the column.
- * NOTE - position is 1-based.
- *
- * @param position The oridinal position of a column in the
- * ResultSet.
- *
- * @return A ResultColumnDescriptor describing the
- * column in the ResultSet.
- */
- ResultColumnDescriptor getColumnDescriptor(int position);
-
- /**
- * Get a new result description that has been truncated
- * from input column number. If the input column is
- * 5, then columns 5 to getColumnCount() are removed.
- * The new ResultDescription points to the same
- * ColumnDescriptors (this method performs a shallow
- * copy.
- *
- * @param truncateFrom the starting column to remove,
- * 1-based.
- *
- * @return a new ResultDescription
- */
- public ResultDescription truncateColumns(int truncateFrom);
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+/**
+ * The ResultDescription interface provides methods to get metadata on the
+ * results returned by a statement.
+ *
+ * @author Jeff Lichtman
+ */
+
+public interface ResultDescription
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ * Returns an identifier that tells what type of statement has been
+ * executed. This can be used to determine what other methods to call
+ * to get the results back from a statement. For example, a SELECT
+ * statement returns rows and columns, while other statements don't,
+ * so you would only call getColumnCount() or getColumnType() for
+ * SELECT statements.
+ *
+ * @return A String identifier telling what type of statement this
+ * is.
+ */
+ String getStatementType();
+
+ /**
+ * Returns the number of columns in the result set.
+ *
+ * @return The number of columns in the result set.
+ */
+ int getColumnCount();
+
+ /**
+ Return information about all the columns.
+ */
+ public ResultColumnDescriptor[] getColumnInfo();
+
+ /**
+ * Returns a ResultColumnDescriptor for the column, given the oridinal
+ * position of the column.
+ * NOTE - position is 1-based.
+ *
+ * @param position The oridinal position of a column in the
+ * ResultSet.
+ *
+ * @return A ResultColumnDescriptor describing the
+ * column in the ResultSet.
+ */
+ ResultColumnDescriptor getColumnDescriptor(int position);
+
+ /**
+ * Get a new result description that has been truncated
+ * from input column number. If the input column is
+ * 5, then columns 5 to getColumnCount() are removed.
+ * The new ResultDescription points to the same
+ * ColumnDescriptors (this method performs a shallow
+ * copy.
+ *
+ * @param truncateFrom the starting column to remove,
+ * 1-based.
+ *
+ * @return a new ResultDescription
+ */
+ public ResultDescription truncateColumns(int truncateFrom);
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultSet.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultSet.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultSet.java Fri Sep 24 10:33:20 2004
@@ -1,330 +1,330 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.execute.ExecRow;
-import org.apache.derby.iapi.sql.execute.NoPutResultSet;
-import org.apache.derby.iapi.sql.Row;
-
-import java.sql.Timestamp;
-import java.sql.SQLWarning;
-
-/**
- * The ResultSet interface provides a method to tell whether a statement
- * returns rows, and if so, a method to get the rows. It also provides a
- * method to get metadata about the contents of the rows. It also provide
- * a method to accept rows as input.
- * <p>
- * There is no single implementation of the ResultSet interface. Instead,
- * the various support operations involved in executing statements
- * implement this interface.
- * <p>
- * Although ExecRow is used on the interface, it is not available to
- * users of the API. They should use Row, the exposed super-interface
- * of ExecRow. <<I couldn't find another way to perform this mapping...>>
- * <p>
- * Valid transitions: <ul>
- * <li> open->close</li>
- * <li> close->open</li>
- * <li> close->finished</li>
- * <li> finished->open</li>
- * </ul>
- *
- * @author Jeff Lichtman
- */
-
-public interface ResultSet
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /* Get time only spent in this ResultSet */
- public static final int CURRENT_RESULTSET_ONLY = 0;
- /* Get time spent in this ResultSet and below */
- public static final int ENTIRE_RESULTSET_TREE = 1;
-
- // cursor check positioning
- public static final int ISBEFOREFIRST = 101;
- public static final int ISFIRST = 102;
- public static final int ISLAST = 103;
- public static final int ISAFTERLAST = 104;
-
- /**
- * Returns TRUE if the statement returns rows (i.e. is a SELECT
- * or FETCH statement), FALSE if it returns no rows.
- *
- * @return TRUE if the statement returns rows, FALSE if not.
- */
- boolean returnsRows();
-
- /**
- * Returns the number of rows affected by the statement.
- Only valid of returnsRows() returns false.
- * For other DML statements, it returns the number of rows
- * modified by the statement. For statements that do not affect rows
- * (like DDL statements), it returns zero.
- *
- * @return The number of rows affect by the statement, so far.
- */
- int modifiedRowCount();
-
- /**
- * Returns a ResultDescription object, which describes the results
- * of the statement this ResultSet is in. This will *not* be a
- * description of this particular ResultSet, if this is not the
- * outermost ResultSet.
- *
- * @return A ResultDescription describing the results of the
- * statement.
- */
- ResultDescription getResultDescription();
-
- /**
- * Needs to be called before the result set will do anything.
- * Need to call before getNextRow(), or for a result set
- * that doesn't return rows, this is the call that will
- * cause all the work to be done.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on failure
- */
- void open() throws StandardException;
-
- /**
- * Returns the row at the absolute position from the query,
- * and returns NULL when there is no such position.
- * (Negative position means from the end of the result set.)
- * Moving the cursor to an invalid position leaves the cursor
- * positioned either before the first row (negative position)
- * or after the last row (positive position).
- * NOTE: An exception will be thrown on 0.
- *
- * @param row The position.
- * @return The row at the absolute position, or NULL if no such position.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow getAbsoluteRow(int row) throws StandardException;
-
- /**
- * Returns the row at the relative position from the current
- * cursor position, and returns NULL when there is no such position.
- * (Negative position means toward the beginning of the result set.)
- * Moving the cursor to an invalid position leaves the cursor
- * positioned either before the first row (negative position)
- * or after the last row (positive position).
- * NOTE: 0 is valid.
- * NOTE: An exception is thrown if the cursor is not currently
- * positioned on a row.
- *
- * @param row The position.
- * @return The row at the relative position, or NULL if no such position.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow getRelativeRow(int row) throws StandardException;
-
- /**
- * Sets the current position to before the first row and returns NULL
- * because there is no current row.
- *
- * @return NULL.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow setBeforeFirstRow() throws StandardException;
-
- /**
- * Returns the first row from the query, and returns NULL when there
- * are no rows.
- *
- * @return The first row, or NULL if no rows.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow getFirstRow() throws StandardException;
-
- /**
- * Returns the next row from the query, and returns NULL when there
- * are no more rows.
- *
- * @return The next row, or NULL if no more rows.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow getNextRow() throws StandardException;
-
- /**
- * Returns the previous row from the query, and returns NULL when there
- * are no more previous rows.
- *
- * @return The previous row, or NULL if no more previous rows.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow getPreviousRow() throws StandardException;
-
- /**
- * Returns the last row from the query, and returns NULL when there
- * are no rows.
- *
- * @return The last row, or NULL if no rows.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow getLastRow() throws StandardException;
-
- /**
- * Sets the current position to after the last row and returns NULL
- * because there is no current row.
- *
- * @return NULL.
- *
- * @exception StandardException Thrown on failure
- * @see Row
- */
- ExecRow setAfterLastRow() throws StandardException;
-
- /**
- Determine if the result set is at one of the positions
- according to the constants above (ISBEFOREFIRST etc).
- Only valid and called for scrollable cursors.
- * @return true if at the requested position.
- * @exception StandardException Thrown on error.
- */
- public boolean checkRowPosition(int isType) throws StandardException;
-
- /**
- * Returns the row number of the current row. Row
- * numbers start from 1 and go to 'n'. Corresponds
- * to row numbering used to position current row
- * in the result set (as per JDBC).
-
- Only valid and called for scrollable cursors.
- * @return the row number, or 0 if not on a row
- *
- */
- int getRowNumber();
-
- /**
- * Tells the system that there will be no more calls to getNextRow()
- * (until the next open() call), so it can free up the resources
- * associated with the ResultSet.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error.
- */
- void close() throws StandardException;
-
- /**
- * Tells the system to clean up on an error.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error.
- */
- void cleanUp() throws StandardException;
-
- /**
- Find out if the ResultSet is closed or not.
- Will report true for result sets that do not return rows.
-
- @return true if the ResultSet has been closed.
- */
- boolean isClosed();
-
- /**
- * Tells the system that there will be no more access
- * to any database information via this result set;
- * in particular, no more calls to open().
- * Will close the result set if it is not already closed.
- *
- * @return Nothing
- * @exception StandardException on error
- */
- void finish() throws StandardException;
-
- /**
- * Get the execution time in milliseconds.
- *
- * @return long The execution time in milliseconds.
- */
- public long getExecuteTime();
-
- /**
- * Get the Timestamp for the beginning of execution.
- *
- * @return Timestamp The Timestamp for the beginning of execution.
- */
- public Timestamp getBeginExecutionTimestamp();
-
- /**
- * Get the Timestamp for the end of execution.
- *
- * @return Timestamp The Timestamp for the end of execution.
- */
- public Timestamp getEndExecutionTimestamp();
-
- /**
- * Return the total amount of time spent in this ResultSet
- *
- * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
- * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
- *
- * @return long The total amount of time spent (in milliseconds).
- */
- public long getTimeSpent(int type);
-
- /**
- * Get the subquery ResultSet tracking array from the top ResultSet.
- * (Used for tracking open subqueries when closing down on an error.)
- *
- * @param numSubqueries The size of the array (For allocation on demand.)
- *
- * @return NoPutResultSet[] Array of NoPutResultSets for subqueries.
- */
- public NoPutResultSet[] getSubqueryTrackingArray(int numSubqueries);
-
- /**
- * ResultSet for rowss inserted into the table (contains auto-generated keys columns only)
- *
- * @return NoPutResultSet NoPutResultSets for rows inserted into the table.
- */
- public ResultSet getAutoGeneratedKeysResultset();
-
- /**
- * Returns the name of the cursor, if this is cursor statement of some
- * type (declare, open, fetch, positioned update, positioned delete,
- * close).
- *
- * @return A String with the name of the cursor, if any. Returns
- * NULL if this is not a cursor statement.
- */
- public String getCursorName();
-
- /**
- Return the set of warnings generated during the execution of
- this result set. The warnings are cleared once this call returns.
- */
- public SQLWarning getWarnings();
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.execute.ExecRow;
+import org.apache.derby.iapi.sql.execute.NoPutResultSet;
+import org.apache.derby.iapi.sql.Row;
+
+import java.sql.Timestamp;
+import java.sql.SQLWarning;
+
+/**
+ * The ResultSet interface provides a method to tell whether a statement
+ * returns rows, and if so, a method to get the rows. It also provides a
+ * method to get metadata about the contents of the rows. It also provide
+ * a method to accept rows as input.
+ * <p>
+ * There is no single implementation of the ResultSet interface. Instead,
+ * the various support operations involved in executing statements
+ * implement this interface.
+ * <p>
+ * Although ExecRow is used on the interface, it is not available to
+ * users of the API. They should use Row, the exposed super-interface
+ * of ExecRow. <<I couldn't find another way to perform this mapping...>>
+ * <p>
+ * Valid transitions: <ul>
+ * <li> open->close</li>
+ * <li> close->open</li>
+ * <li> close->finished</li>
+ * <li> finished->open</li>
+ * </ul>
+ *
+ * @author Jeff Lichtman
+ */
+
+public interface ResultSet
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /* Get time only spent in this ResultSet */
+ public static final int CURRENT_RESULTSET_ONLY = 0;
+ /* Get time spent in this ResultSet and below */
+ public static final int ENTIRE_RESULTSET_TREE = 1;
+
+ // cursor check positioning
+ public static final int ISBEFOREFIRST = 101;
+ public static final int ISFIRST = 102;
+ public static final int ISLAST = 103;
+ public static final int ISAFTERLAST = 104;
+
+ /**
+ * Returns TRUE if the statement returns rows (i.e. is a SELECT
+ * or FETCH statement), FALSE if it returns no rows.
+ *
+ * @return TRUE if the statement returns rows, FALSE if not.
+ */
+ boolean returnsRows();
+
+ /**
+ * Returns the number of rows affected by the statement.
+ Only valid of returnsRows() returns false.
+ * For other DML statements, it returns the number of rows
+ * modified by the statement. For statements that do not affect rows
+ * (like DDL statements), it returns zero.
+ *
+ * @return The number of rows affect by the statement, so far.
+ */
+ int modifiedRowCount();
+
+ /**
+ * Returns a ResultDescription object, which describes the results
+ * of the statement this ResultSet is in. This will *not* be a
+ * description of this particular ResultSet, if this is not the
+ * outermost ResultSet.
+ *
+ * @return A ResultDescription describing the results of the
+ * statement.
+ */
+ ResultDescription getResultDescription();
+
+ /**
+ * Needs to be called before the result set will do anything.
+ * Need to call before getNextRow(), or for a result set
+ * that doesn't return rows, this is the call that will
+ * cause all the work to be done.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on failure
+ */
+ void open() throws StandardException;
+
+ /**
+ * Returns the row at the absolute position from the query,
+ * and returns NULL when there is no such position.
+ * (Negative position means from the end of the result set.)
+ * Moving the cursor to an invalid position leaves the cursor
+ * positioned either before the first row (negative position)
+ * or after the last row (positive position).
+ * NOTE: An exception will be thrown on 0.
+ *
+ * @param row The position.
+ * @return The row at the absolute position, or NULL if no such position.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow getAbsoluteRow(int row) throws StandardException;
+
+ /**
+ * Returns the row at the relative position from the current
+ * cursor position, and returns NULL when there is no such position.
+ * (Negative position means toward the beginning of the result set.)
+ * Moving the cursor to an invalid position leaves the cursor
+ * positioned either before the first row (negative position)
+ * or after the last row (positive position).
+ * NOTE: 0 is valid.
+ * NOTE: An exception is thrown if the cursor is not currently
+ * positioned on a row.
+ *
+ * @param row The position.
+ * @return The row at the relative position, or NULL if no such position.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow getRelativeRow(int row) throws StandardException;
+
+ /**
+ * Sets the current position to before the first row and returns NULL
+ * because there is no current row.
+ *
+ * @return NULL.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow setBeforeFirstRow() throws StandardException;
+
+ /**
+ * Returns the first row from the query, and returns NULL when there
+ * are no rows.
+ *
+ * @return The first row, or NULL if no rows.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow getFirstRow() throws StandardException;
+
+ /**
+ * Returns the next row from the query, and returns NULL when there
+ * are no more rows.
+ *
+ * @return The next row, or NULL if no more rows.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow getNextRow() throws StandardException;
+
+ /**
+ * Returns the previous row from the query, and returns NULL when there
+ * are no more previous rows.
+ *
+ * @return The previous row, or NULL if no more previous rows.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow getPreviousRow() throws StandardException;
+
+ /**
+ * Returns the last row from the query, and returns NULL when there
+ * are no rows.
+ *
+ * @return The last row, or NULL if no rows.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow getLastRow() throws StandardException;
+
+ /**
+ * Sets the current position to after the last row and returns NULL
+ * because there is no current row.
+ *
+ * @return NULL.
+ *
+ * @exception StandardException Thrown on failure
+ * @see Row
+ */
+ ExecRow setAfterLastRow() throws StandardException;
+
+ /**
+ Determine if the result set is at one of the positions
+ according to the constants above (ISBEFOREFIRST etc).
+ Only valid and called for scrollable cursors.
+ * @return true if at the requested position.
+ * @exception StandardException Thrown on error.
+ */
+ public boolean checkRowPosition(int isType) throws StandardException;
+
+ /**
+ * Returns the row number of the current row. Row
+ * numbers start from 1 and go to 'n'. Corresponds
+ * to row numbering used to position current row
+ * in the result set (as per JDBC).
+
+ Only valid and called for scrollable cursors.
+ * @return the row number, or 0 if not on a row
+ *
+ */
+ int getRowNumber();
+
+ /**
+ * Tells the system that there will be no more calls to getNextRow()
+ * (until the next open() call), so it can free up the resources
+ * associated with the ResultSet.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error.
+ */
+ void close() throws StandardException;
+
+ /**
+ * Tells the system to clean up on an error.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error.
+ */
+ void cleanUp() throws StandardException;
+
+ /**
+ Find out if the ResultSet is closed or not.
+ Will report true for result sets that do not return rows.
+
+ @return true if the ResultSet has been closed.
+ */
+ boolean isClosed();
+
+ /**
+ * Tells the system that there will be no more access
+ * to any database information via this result set;
+ * in particular, no more calls to open().
+ * Will close the result set if it is not already closed.
+ *
+ * @return Nothing
+ * @exception StandardException on error
+ */
+ void finish() throws StandardException;
+
+ /**
+ * Get the execution time in milliseconds.
+ *
+ * @return long The execution time in milliseconds.
+ */
+ public long getExecuteTime();
+
+ /**
+ * Get the Timestamp for the beginning of execution.
+ *
+ * @return Timestamp The Timestamp for the beginning of execution.
+ */
+ public Timestamp getBeginExecutionTimestamp();
+
+ /**
+ * Get the Timestamp for the end of execution.
+ *
+ * @return Timestamp The Timestamp for the end of execution.
+ */
+ public Timestamp getEndExecutionTimestamp();
+
+ /**
+ * Return the total amount of time spent in this ResultSet
+ *
+ * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
+ * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
+ *
+ * @return long The total amount of time spent (in milliseconds).
+ */
+ public long getTimeSpent(int type);
+
+ /**
+ * Get the subquery ResultSet tracking array from the top ResultSet.
+ * (Used for tracking open subqueries when closing down on an error.)
+ *
+ * @param numSubqueries The size of the array (For allocation on demand.)
+ *
+ * @return NoPutResultSet[] Array of NoPutResultSets for subqueries.
+ */
+ public NoPutResultSet[] getSubqueryTrackingArray(int numSubqueries);
+
+ /**
+ * ResultSet for rowss inserted into the table (contains auto-generated keys columns only)
+ *
+ * @return NoPutResultSet NoPutResultSets for rows inserted into the table.
+ */
+ public ResultSet getAutoGeneratedKeysResultset();
+
+ /**
+ * Returns the name of the cursor, if this is cursor statement of some
+ * type (declare, open, fetch, positioned update, positioned delete,
+ * close).
+ *
+ * @return A String with the name of the cursor, if any. Returns
+ * NULL if this is not a cursor statement.
+ */
+ public String getCursorName();
+
+ /**
+ Return the set of warnings generated during the execution of
+ this result set. The warnings are cleared once this call returns.
+ */
+ public SQLWarning getWarnings();
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Row.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Row.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Row.java Fri Sep 24 10:33:20 2004
@@ -1,58 +1,58 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.types.DataValueDescriptor;
-
-import org.apache.derby.iapi.error.StandardException;
-
-/**
- * The Row interface provides methods to get information about the columns
- * in a result row.
- * It uses simple, position (1-based) access to get to columns.
- * Searching for columns by name should be done from the ResultSet
- * interface, where metadata about the rows and columns is available.
- * <p>
- *
- * @see ResultSet
- *
- * @author Jeff Lichtman
- * @see org.apache.derby.iapi.sql.execute.ExecRow
- */
-
-public interface Row
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- public int nColumns();
-
- /**
- * Get a DataValueDescriptor in a Row by ordinal position (1-based).
- *
- * @param position The ordinal position of the column.
- *
- * @exception StandardException Thrown on failure.
- * @return The DataValueDescriptor, null if no such column exists
- */
- DataValueDescriptor getColumn (int position) throws StandardException;
-
- /**
- * Set a DataValueDescriptor in a Row by ordinal position (1-based).
- *
- * @param position The ordinal position of the column.
- *
- * @return The DataValueDescriptor, null if no such column exists
- */
- void setColumn (int position, DataValueDescriptor value);
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+import org.apache.derby.iapi.error.StandardException;
+
+/**
+ * The Row interface provides methods to get information about the columns
+ * in a result row.
+ * It uses simple, position (1-based) access to get to columns.
+ * Searching for columns by name should be done from the ResultSet
+ * interface, where metadata about the rows and columns is available.
+ * <p>
+ *
+ * @see ResultSet
+ *
+ * @author Jeff Lichtman
+ * @see org.apache.derby.iapi.sql.execute.ExecRow
+ */
+
+public interface Row
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ public int nColumns();
+
+ /**
+ * Get a DataValueDescriptor in a Row by ordinal position (1-based).
+ *
+ * @param position The ordinal position of the column.
+ *
+ * @exception StandardException Thrown on failure.
+ * @return The DataValueDescriptor, null if no such column exists
+ */
+ DataValueDescriptor getColumn (int position) throws StandardException;
+
+ /**
+ * Set a DataValueDescriptor in a Row by ordinal position (1-based).
+ *
+ * @param position The ordinal position of the column.
+ *
+ * @return The DataValueDescriptor, null if no such column exists
+ */
+ void setColumn (int position, DataValueDescriptor value);
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Statement.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Statement.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Statement.java Fri Sep 24 10:33:20 2004
@@ -1,88 +1,88 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-
-/**
- * The Statement interface provides a way of giving a statement to the
- * language module, preparing the statement, and executing it. It also
- * provides some support for stored statements. Simple, non-stored,
- * non-parameterized statements can be executed with the execute() method.
- * Parameterized statements must use prepare(). To get the stored query
- * plan for a statement, use get().
- * <p>
- * This interface will have different implementations for the execution-only
- * and compile-and-execute versions of the product. In the execution-only
- * version, some of the methods will do nothing but raise exceptions to
- * indicate that they are not implemented.
- * <p>
- * There is a Statement factory in the Connection interface in the Database
- * module, which uses the one provided in LanguageFactory.
- *
- * @author Jeff Lichtman
- */
-public interface Statement
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- /**
- * Generates an execution plan without executing it.
- *
- * @return A PreparedStatement that allows execution of the execution
- * plan.
- * @exception StandardException Thrown if this is an
- * execution-only version of the module (the prepare() method
- * relies on compilation).
- */
- PreparedStatement prepare(LanguageConnectionContext lcc) throws StandardException;
-
- /**
- * Generates an execution plan given a set of named parameters.
- * For generating a storable prepared statement (which
- * has some extensions over a standard prepared statement).
- *
- * @param compSchema the compilation schema to use
- * @param paramDefaults Default parameter values to use for
- * optimization
- * @param spsSchema schema of the stored prepared statement
- *
- * @return A Storable PreparedStatement that allows execution of the execution
- * plan.
- * @exception StandardException Thrown if this is an
- * execution-only version of the module (the prepare() method
- * relies on compilation).
- */
- public PreparedStatement prepareStorable
- (
- LanguageConnectionContext lcc,
- PreparedStatement ps,
- Object[] paramDefaults,
- SchemaDescriptor spsSchema,
- boolean internalSQL
- )
- throws StandardException;
-
- /**
- * Return the SQL string that this statement is for.
- *
- * @return the SQL string this statement is for.
- */
- String getSource();
-
- public boolean getUnicode();
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+
+/**
+ * The Statement interface provides a way of giving a statement to the
+ * language module, preparing the statement, and executing it. It also
+ * provides some support for stored statements. Simple, non-stored,
+ * non-parameterized statements can be executed with the execute() method.
+ * Parameterized statements must use prepare(). To get the stored query
+ * plan for a statement, use get().
+ * <p>
+ * This interface will have different implementations for the execution-only
+ * and compile-and-execute versions of the product. In the execution-only
+ * version, some of the methods will do nothing but raise exceptions to
+ * indicate that they are not implemented.
+ * <p>
+ * There is a Statement factory in the Connection interface in the Database
+ * module, which uses the one provided in LanguageFactory.
+ *
+ * @author Jeff Lichtman
+ */
+public interface Statement
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ /**
+ * Generates an execution plan without executing it.
+ *
+ * @return A PreparedStatement that allows execution of the execution
+ * plan.
+ * @exception StandardException Thrown if this is an
+ * execution-only version of the module (the prepare() method
+ * relies on compilation).
+ */
+ PreparedStatement prepare(LanguageConnectionContext lcc) throws StandardException;
+
+ /**
+ * Generates an execution plan given a set of named parameters.
+ * For generating a storable prepared statement (which
+ * has some extensions over a standard prepared statement).
+ *
+ * @param compSchema the compilation schema to use
+ * @param paramDefaults Default parameter values to use for
+ * optimization
+ * @param spsSchema schema of the stored prepared statement
+ *
+ * @return A Storable PreparedStatement that allows execution of the execution
+ * plan.
+ * @exception StandardException Thrown if this is an
+ * execution-only version of the module (the prepare() method
+ * relies on compilation).
+ */
+ public PreparedStatement prepareStorable
+ (
+ LanguageConnectionContext lcc,
+ PreparedStatement ps,
+ Object[] paramDefaults,
+ SchemaDescriptor spsSchema,
+ boolean internalSQL
+ )
+ throws StandardException;
+
+ /**
+ * Return the SQL string that this statement is for.
+ *
+ * @return the SQL string this statement is for.
+ */
+ String getSource();
+
+ public boolean getUnicode();
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementType.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementType.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementType.java Fri Sep 24 10:33:20 2004
@@ -1,54 +1,54 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-/**
- * Different types of statements
- *
- * @author jamie
- */
-public interface StatementType
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- public static final int UNKNOWN = 0;
- public static final int INSERT = 1;
- public static final int BULK_INSERT_REPLACE = 2;
- public static final int UPDATE = 3;
- public static final int DELETE = 4;
- public static final int ENABLED = 5;
- public static final int DISABLED = 6;
-
- public static final int DROP_CASCADE = 0;
- public static final int DROP_RESTRICT = 1;
- public static final int DROP_DEFAULT = 2;
-
- public static final int RENAME_TABLE = 1;
- public static final int RENAME_COLUMN = 2;
- public static final int RENAME_INDEX = 3;
-
- public static final int RA_CASCADE = 0;
- public static final int RA_RESTRICT = 1;
- public static final int RA_NOACTION = 2; //default value
- public static final int RA_SETNULL = 3;
- public static final int RA_SETDEFAULT = 4;
-
- public static final int SET_SCHEMA_USER = 1;
- public static final int SET_SCHEMA_DYNAMIC = 2;
-
-}
-
-
-
-
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+/**
+ * Different types of statements
+ *
+ * @author jamie
+ */
+public interface StatementType
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ public static final int UNKNOWN = 0;
+ public static final int INSERT = 1;
+ public static final int BULK_INSERT_REPLACE = 2;
+ public static final int UPDATE = 3;
+ public static final int DELETE = 4;
+ public static final int ENABLED = 5;
+ public static final int DISABLED = 6;
+
+ public static final int DROP_CASCADE = 0;
+ public static final int DROP_RESTRICT = 1;
+ public static final int DROP_DEFAULT = 2;
+
+ public static final int RENAME_TABLE = 1;
+ public static final int RENAME_COLUMN = 2;
+ public static final int RENAME_INDEX = 3;
+
+ public static final int RA_CASCADE = 0;
+ public static final int RA_RESTRICT = 1;
+ public static final int RA_NOACTION = 2; //default value
+ public static final int RA_SETNULL = 3;
+ public static final int RA_SETDEFAULT = 4;
+
+ public static final int SET_SCHEMA_USER = 1;
+ public static final int SET_SCHEMA_DYNAMIC = 2;
+
+}
+
+
+
+
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementUtil.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementUtil.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StatementUtil.java Fri Sep 24 10:33:20 2004
@@ -1,63 +1,63 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.services.i18n.MessageService;
-import org.apache.derby.iapi.reference.SQLState;
-
-/**
- * Utilities for dealing with statements.
- *
- * @author jeff
- */
-public class StatementUtil
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- private StatementUtil(){}; // Do not instantiate
-
- public static String typeName(int typeNumber)
- {
- String retval;
-
- switch (typeNumber)
- {
- case StatementType.INSERT:
- case StatementType.BULK_INSERT_REPLACE:
- case StatementType.UPDATE:
- case StatementType.DELETE:
- case StatementType.ENABLED:
- case StatementType.DISABLED:
- retval = TypeNames[typeNumber];
- break;
-
- default:
- retval = MessageService.getTextMessage(SQLState.LANG_UNKNOWN);
- break;
- }
-
- return retval;
- }
-
- private static final String[] TypeNames =
- {
- "",
- "INSERT",
- "INSERT",
- "UPDATE",
- "DELETE",
- "ENABLED",
- "DISABLED"
- };
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.i18n.MessageService;
+import org.apache.derby.iapi.reference.SQLState;
+
+/**
+ * Utilities for dealing with statements.
+ *
+ * @author jeff
+ */
+public class StatementUtil
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ private StatementUtil(){}; // Do not instantiate
+
+ public static String typeName(int typeNumber)
+ {
+ String retval;
+
+ switch (typeNumber)
+ {
+ case StatementType.INSERT:
+ case StatementType.BULK_INSERT_REPLACE:
+ case StatementType.UPDATE:
+ case StatementType.DELETE:
+ case StatementType.ENABLED:
+ case StatementType.DISABLED:
+ retval = TypeNames[typeNumber];
+ break;
+
+ default:
+ retval = MessageService.getTextMessage(SQLState.LANG_UNKNOWN);
+ break;
+ }
+
+ return retval;
+ }
+
+ private static final String[] TypeNames =
+ {
+ "",
+ "INSERT",
+ "INSERT",
+ "UPDATE",
+ "DELETE",
+ "ENABLED",
+ "DISABLED"
+ };
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StorablePreparedStatement.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StorablePreparedStatement.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/StorablePreparedStatement.java Fri Sep 24 10:33:20 2004
@@ -1,38 +1,38 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql
- (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql;
-
-import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
-import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.services.loader.GeneratedClass;
-
-/**
- * The Statement interface is an extension of exec prepared statement
- * that has some stored prepared specifics.
- *
- * @author jamie
- */
-public interface StorablePreparedStatement extends ExecPreparedStatement
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
-
- /**
- * Load up the class from the saved bytes.
- *
- *
- * @exception StandardException on error
- */
- public void loadGeneratedClass()
- throws StandardException;
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql
+ (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql;
+
+import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.loader.GeneratedClass;
+
+/**
+ * The Statement interface is an extension of exec prepared statement
+ * that has some stored prepared specifics.
+ *
+ * @author jamie
+ */
+public interface StorablePreparedStatement extends ExecPreparedStatement
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
+
+ /**
+ * Load up the class from the saved bytes.
+ *
+ *
+ * @exception StandardException on error
+ */
+ public void loadGeneratedClass()
+ throws StandardException;
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/AccessPath.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/AccessPath.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/AccessPath.java Fri Sep 24 10:33:20 2004
@@ -1,136 +1,136 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.iapi.sql.compile
- (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.iapi.sql.compile;
-
-import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
-import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.error.StandardException;
-
-/**
- * AccessPath represents a proposed access path for an Optimizable.
- * An Optimizable may have more than one proposed AccessPath.
- */
-
-public interface AccessPath {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
- /**
- * Set the conglomerate descriptor for this access path.
- *
- * @param cd A ConglomerateDescriptor
- *
- * @return Nothing.
- */
- void setConglomerateDescriptor(ConglomerateDescriptor cd);
-
- /**
- * Get whatever was last set as the conglomerate descriptor.
- * Returns null if nothing was set since the last call to startOptimizing()
- */
- ConglomerateDescriptor getConglomerateDescriptor();
-
- /**
- * Set the given cost estimate in this AccessPath. Generally, this will
- * be the CostEstimate for the plan currently under consideration.
- */
- public void setCostEstimate(CostEstimate costEstimate);
-
- /**
- * Get the cost estimate for this AccessPath. This is the last one
- * set by setCostEstimate.
- */
- public CostEstimate getCostEstimate();
-
- /**
- * Set whether or not to consider a covering index scan on the optimizable.
- *
- * @return Nothing.
- */
- public void setCoveringIndexScan(boolean coveringIndexScan);
-
- /**
- * Return whether or not the optimizer is considering a covering index
- * scan on this AccessPath.
- *
- * @return boolean Whether or not the optimizer chose a covering
- * index scan.
- */
- public boolean getCoveringIndexScan();
-
- /**
- * Set whether or not to consider a non-matching index scan on this
- * AccessPath.
- *
- * @return Nothing.
- */
- public void setNonMatchingIndexScan(boolean nonMatchingIndexScan);
-
- /**
- * Return whether or not the optimizer is considering a non-matching
- * index scan on this AccessPath. We expect to call this during
- * generation, after access path selection is complete.
- *
- * @return boolean Whether or not the optimizer is considering
- * a non-matching index scan.
- */
- public boolean getNonMatchingIndexScan();
-
- /**
- * Remember the given join strategy
- *
- * @param joinStrategy The best join strategy
- */
- public void setJoinStrategy(JoinStrategy joinStrategy);
-
- /**
- * Get the join strategy, as set by setJoinStrategy().
- */
- public JoinStrategy getJoinStrategy();
-
- /**
- * Set the lock mode
- */
- public void setLockMode(int lockMode);
-
- /**
- * Get the lock mode, as last set in setLockMode().
- */
- public int getLockMode();
-
- /**
- * Copy all information from the given AccessPath to this one.
- */
- public void copy(AccessPath copyFrom);
-
- /**
- * Get the optimizer associated with this access path.
- *
- * @return The optimizer associated with this access path.
- */
- public Optimizer getOptimizer();
-
- /**
- * Sets the "name" of the access path. if the access path represents an
- * index then set the name to the name of the index. if it is an index
- * created for a constraint, use the constraint name. This is called only
- * for base tables.
- *
- * @param td TableDescriptor of the base table.
- * @param dd Datadictionary.
- *
- * @exception StandardException on error.
- */
- public void initializeAccessPathName(DataDictionary dd, TableDescriptor td)
- throws StandardException;
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.iapi.sql.compile
+ (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.iapi.sql.compile;
+
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.error.StandardException;
+
+/**
+ * AccessPath represents a proposed access path for an Optimizable.
+ * An Optimizable may have more than one proposed AccessPath.
+ */
+
+public interface AccessPath {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
+ /**
+ * Set the conglomerate descriptor for this access path.
+ *
+ * @param cd A ConglomerateDescriptor
+ *
+ * @return Nothing.
+ */
+ void setConglomerateDescriptor(ConglomerateDescriptor cd);
+
+ /**
+ * Get whatever was last set as the conglomerate descriptor.
+ * Returns null if nothing was set since the last call to startOptimizing()
+ */
+ ConglomerateDescriptor getConglomerateDescriptor();
+
+ /**
+ * Set the given cost estimate in this AccessPath. Generally, this will
+ * be the CostEstimate for the plan currently under consideration.
+ */
+ public void setCostEstimate(CostEstimate costEstimate);
+
+ /**
+ * Get the cost estimate for this AccessPath. This is the last one
+ * set by setCostEstimate.
+ */
+ public CostEstimate getCostEstimate();
+
+ /**
+ * Set whether or not to consider a covering index scan on the optimizable.
+ *
+ * @return Nothing.
+ */
+ public void setCoveringIndexScan(boolean coveringIndexScan);
+
+ /**
+ * Return whether or not the optimizer is considering a covering index
+ * scan on this AccessPath.
+ *
+ * @return boolean Whether or not the optimizer chose a covering
+ * index scan.
+ */
+ public boolean getCoveringIndexScan();
+
+ /**
+ * Set whether or not to consider a non-matching index scan on this
+ * AccessPath.
+ *
+ * @return Nothing.
+ */
+ public void setNonMatchingIndexScan(boolean nonMatchingIndexScan);
+
+ /**
+ * Return whether or not the optimizer is considering a non-matching
+ * index scan on this AccessPath. We expect to call this during
+ * generation, after access path selection is complete.
+ *
+ * @return boolean Whether or not the optimizer is considering
+ * a non-matching index scan.
+ */
+ public boolean getNonMatchingIndexScan();
+
+ /**
+ * Remember the given join strategy
+ *
+ * @param joinStrategy The best join strategy
+ */
+ public void setJoinStrategy(JoinStrategy joinStrategy);
+
+ /**
+ * Get the join strategy, as set by setJoinStrategy().
+ */
+ public JoinStrategy getJoinStrategy();
+
+ /**
+ * Set the lock mode
+ */
+ public void setLockMode(int lockMode);
+
+ /**
+ * Get the lock mode, as last set in setLockMode().
+ */
+ public int getLockMode();
+
+ /**
+ * Copy all information from the given AccessPath to this one.
+ */
+ public void copy(AccessPath copyFrom);
+
+ /**
+ * Get the optimizer associated with this access path.
+ *
+ * @return The optimizer associated with this access path.
+ */
+ public Optimizer getOptimizer();
+
+ /**
+ * Sets the "name" of the access path. if the access path represents an
+ * index then set the name to the name of the index. if it is an index
+ * created for a constraint, use the constraint name. This is called only
+ * for base tables.
+ *
+ * @param td TableDescriptor of the base table.
+ * @param dd Datadictionary.
+ *
+ * @exception StandardException on error.
+ */
+ public void initializeAccessPathName(DataDictionary dd, TableDescriptor td)
+ throws StandardException;
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SQLToJavaValueNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SQLToJavaValueNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SQLToJavaValueNode.java Fri Sep 24 10:33:20 2004
@@ -1,519 +1,519 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-import org.apache.derby.iapi.services.compiler.LocalField;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.types.JSQLType;
-
-import org.apache.derby.iapi.types.DataValueDescriptor;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-
-import org.apache.derby.iapi.sql.Activation;
-
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.iapi.sql.compile.Visitable;
-import org.apache.derby.iapi.sql.compile.Visitor;
-
-import org.apache.derby.iapi.reference.ClassName;
-
-import org.apache.derby.iapi.util.JBitSet;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import java.lang.reflect.Modifier;
-
-import java.util.Vector;
-
-/**
- * This node type converts a value in the SQL domain to a value in the Java
- * domain.
- */
-
-public class SQLToJavaValueNode extends JavaValueNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- ValueNode value;
-
- LocalField returnsNullOnNullState;
-
- /**
- * Constructor for a SQLToJavaValueNode
- *
- * @param value A ValueNode representing a SQL value to convert to
- * the Java domain.
- */
-
- public void init(Object value)
- {
- this.value = (ValueNode) value;
- }
-
- /**
- * Prints the sub-nodes of this object. See QueryTreeNode.java for
- * how tree printing is supposed to work.
- *
- * @param depth The depth of this node in the tree
- *
- * @return Nothing
- */
-
- public void printSubNodes(int depth)
- {
- if (SanityManager.DEBUG)
- {
- int parm;
-
- super.printSubNodes(depth);
- if (value != null)
- {
- printLabel(depth, "value: ");
- value.treePrint(depth + 1);
- }
- }
- }
-
- /**
- * Returns the name of the java class type that this node coerces to.
- *
- * @return name of java class type
- *
- */
- public String getJavaTypeName()
- {
- JSQLType myType = getJSQLType();
-
- if ( myType == null ) { return ""; }
- else { return mapToTypeID( myType ).getCorrespondingJavaTypeName(); }
- }
-
- /**
- * Returns the name of the java primitive type that this node coerces to.
- *
- * @return name of java primitive type
- *
- * @exception StandardException Thrown on error
- */
- public String getPrimitiveTypeName()
- throws StandardException
- {
- JSQLType myType = getJSQLType();
-
- if ( myType == null )
- {
- return "";
- }
- else
- {
- return
- getTypeCompiler(mapToTypeID( myType )).
- getCorrespondingPrimitiveTypeName();
- }
- }
-
- /**
- * Get the JSQLType that corresponds to this node. Could be a SQLTYPE,
- * a Java primitive, or a Java class.
- *
- * Overrides method in JavaValueNode.
- *
- * @return the corresponding JSQLType
- *
- */
- public JSQLType getJSQLType
- (
- )
- {
- if ( jsqlType == null )
- {
- if ( value.isParameterNode() )
- {
- jsqlType = ((ParameterNode) value).getJSQLType();
- }
- else
- {
- DataTypeDescriptor dtd = value.getTypeServices();
- if (dtd != null)
- jsqlType = new JSQLType( dtd );
- }
- }
-
- return jsqlType;
- }
-
-
- /**
- * Set the clause that this node appears in.
- *
- * @param clause The clause that this node appears in.
- *
- * @return Nothing.
- */
- public void setClause(int clause)
- {
- super.setClause(clause);
- value.setClause(clause);
- }
-
- /**
- * Bind this expression. This means binding the sub-expressions,
- * as well as figuring out what the return type is for this expression.
- *
- * @param fromList The FROM list for the query this
- * expression is in, for binding columns.
- * @param subqueryList The subquery list being built as we find
- * SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return this
- *
- * @exception StandardException Thrown on error
- */
-
- public JavaValueNode bindExpression(
- FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- /* Bind the expression under us */
- value = value.bindExpression(fromList, subqueryList,
- aggregateVector);
-
- return this;
- }
-
- /**
- * Remap all ColumnReferences in this tree to be clones of the
- * underlying expression.
- *
- * @return JavaValueNode The remapped expression tree.
- *
- * @exception StandardException Thrown on error
- */
- public JavaValueNode remapColumnReferencesToExpressions()
- throws StandardException
- {
- value = value.remapColumnReferencesToExpressions();
- return this;
- }
-
- /**
- * Categorize this predicate. Initially, this means
- * building a bit map of the referenced tables for each predicate.
- * If the source of this ColumnReference (at the next underlying level)
- * is not a ColumnReference or a VirtualColumnNode then this predicate
- * will not be pushed down.
- *
- * For example, in:
- * select * from (select 1 from s) a (x) where x = 1
- * we will not push down x = 1.
- * NOTE: It would be easy to handle the case of a constant, but if the
- * inner SELECT returns an arbitrary expression, then we would have to copy
- * that tree into the pushed predicate, and that tree could contain
- * subqueries and method calls.
- * RESOLVE - revisit this issue once we have views.
- *
- * @param referencedTabs JBitSet with bit map of referenced FromTables
- * @param simplePredsOnly Whether or not to consider method
- * calls, field references and conditional nodes
- * when building bit map
- *
- * @return boolean Whether or not source.expression is a ColumnReference
- * or a VirtualColumnNode.
- *
- * @exception StandardException Thrown on error
- */
- public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
- throws StandardException
- {
- return value.categorize(referencedTabs, simplePredsOnly);
- }
-
- /**
- * Preprocess an expression tree. We do a number of transformations
- * here (including subqueries, IN lists, LIKE and BETWEEN) plus
- * subquery flattening.
- * NOTE: This is done before the outer ResultSetNode is preprocessed.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown on error
- */
- public void preprocess(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList)
- throws StandardException
- {
- value.preprocess(numTables,
- outerFromList, outerSubqueryList,
- outerPredicateList);
- }
-
- /**
- * Return the variant type for the underlying expression.
- * The variant type can be:
- * VARIANT - variant within a scan
- * (method calls and non-static field access)
- * SCAN_INVARIANT - invariant within a scan
- * (column references from outer tables)
- * QUERY_INVARIANT - invariant within the life of a query
- * (constant expressions)
- *
- * @return The variant type for the underlying expression.
- * @exception StandardException thrown on error
- */
- protected int getOrderableVariantType() throws StandardException
- {
- return value.getOrderableVariantType();
- }
-
- ///////////////////////////////////////////////////////////////////////
- //
- // CODE GENERATION METHODS
- //
- ///////////////////////////////////////////////////////////////////////
-
-
- /**
- * Generate code to get the Java value out of a SQL value.
- *
- * Every SQL type has a corresponding Java type. The getObject() method
- * on the SQL type gets the right Java type.
- *
- * The generated code will be:
- *
- * (<Java type name>) ((DataValueDescriptor)
- * <generated value>.getObject())
- *
- * where <Java type name> comes from the getCorrespondingJavaTypeName()
- * method of the value's TypeId.
- *
- * @param acb The ExpressionClassBuilder for the class being built
- * @param mb The method the expression will go into
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateExpression(ExpressionClassBuilder acb,
- MethodBuilder mb)
- throws StandardException
- {
- /* Compile the expression under us */
- generateSQLValue( acb, mb );
-
- /* now cast the SQLValue to a Java value */
- generateJavaValue( acb, mb);
- }
-
- /**
- * Generate the SQLvalue that this node wraps.
- *
- * @param acb The ExpressionClassBuilder for the class being built
- * @param mb The method the expression will go into
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateSQLValue(ExpressionClassBuilder acb,
- MethodBuilder mb)
- throws StandardException
- {
- value.generateExpression(acb, mb);
- }
-
- /**
- * Generate code to cast the SQLValue to a Java value.
- *
- *
- * @param acb The ExpressionClassBuilder for the class being built
- * @param mb The method the expression will go into
- * @param SQLValue An Expression holding the SQLValue.
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateJavaValue
- (
- ExpressionClassBuilder acb,
- MethodBuilder mbex
- )
- throws StandardException
- {
- /* If this is a conversion to a primitive type, then call the
- * appropriate method for getting the primitive value and
- * cast it to the primitive type.
- * NOTE: We first call Activation.nullToPrimitiveTest(),
- * which will throw a StandardException if the value is null
- */
- if ( isPrimitiveType() || mustCastToPrimitive() )
- {
- String primitiveTN = value.getTypeCompiler().getCorrespondingPrimitiveTypeName();
-
- /* Put the code to check if the object is null and to
- * get the primitive value in a method call. This is
- * necessary because we are generating an expression here and
- * cannot have multiple statements.
- * The method call will take SQLValue as a parameter.
- */
- String[] pd = new String[1];
- pd[0] = getSQLValueInterfaceName(); // parameter "param1"
-
- MethodBuilder mb = acb.newGeneratedFun(primitiveTN, Modifier.PRIVATE, pd);
-
- mb.getParameter(0);
-
- if (returnsNullOnNullState != null)
- {
- generateReturnsNullOnNullCheck(mb);
- }
- else
- {
- mb.dup();
- mb.upCast(ClassName.DataValueDescriptor);
- mb.push(primitiveTN);
- mb.callMethod(VMOpcode.INVOKESTATIC, ClassName.BaseActivation, "nullToPrimitiveTest", "void", 2);
- }
-
- // stack is dvd
-
- /* Generate the code to get the primitive value */
- mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor,
- value.getTypeCompiler().getPrimitiveMethodName(), primitiveTN, 0);
-
- mb.methodReturn();
- mb.complete();
-
- /* Generate the call to the new method, with the parameter */
-
- mbex.pushThis();
- mbex.swap(); // caller pushed out parameter
- mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), primitiveTN, 1);
- }
- else
- {
- if (returnsNullOnNullState != null)
- generateReturnsNullOnNullCheck(mbex);
-
- /* Call getObject() to get the right type of Java value */
- mbex.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "getObject",
- "java.lang.Object", 0);
-
- mbex.cast(value.getTypeId().getCorrespondingJavaTypeName());
- }
- }
-
- /**
- Generate the code for the returns Null on Null input check..
- Stack must contain the DataDescriptorValue.
- */
-
- private void generateReturnsNullOnNullCheck(MethodBuilder mb)
- {
- mb.dup();
- mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Storable,
- "isNull", "boolean", 0);
-
- mb.conditionalIf();
- mb.push(true);
- mb.startElseCode();
- mb.getField(returnsNullOnNullState);
- mb.completeConditional();
-
- mb.putField(returnsNullOnNullState);
- mb.endStatement();
- }
-
-
- /**
- * Get the type name of the SQLValue we generate.
- *
- * @return name of interface corresponding to SQLValue
- *
- *
- * @exception StandardException Thrown on error
- */
- public String getSQLValueInterfaceName()
- throws StandardException
- {
- return value.getTypeCompiler().interfaceName();
- }
-
- ///////////////////////////////////////////////////////////////////////
- //
- // OTHER VALUE NODE METHODS
- //
- ///////////////////////////////////////////////////////////////////////
-
-
- /**
- * Get the SQL ValueNode that is being converted to a JavaValueNode
- *
- * @return The underlying SQL ValueNode
- */
- ValueNode getSQLValueNode()
- {
- return value;
- }
-
- /** @see ValueNode#getConstantValueAsObject
- *
- * @exception StandardException Thrown on error
- */
- Object getConstantValueAsObject()
- throws StandardException
- {
- return value.getConstantValueAsObject();
- }
-
- /**
- * Accept a visitor, and call v.visit()
- * on child nodes as necessary.
- *
- * @param v the visitor
- *
- * @exception StandardException on error
- */
- public Visitable accept(Visitor v)
- throws StandardException
- {
- Visitable returnNode = v.visit(this);
-
- if (v.skipChildren(this))
- {
- return returnNode;
- }
-
- if (value != null && !v.stopTraversal())
- {
- value = (ValueNode)value.accept(v);
- }
-
- return returnNode;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+import org.apache.derby.iapi.services.compiler.LocalField;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.types.JSQLType;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import org.apache.derby.iapi.sql.compile.TypeCompiler;
+
+import org.apache.derby.iapi.sql.Activation;
+
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+import org.apache.derby.iapi.sql.compile.Visitable;
+import org.apache.derby.iapi.sql.compile.Visitor;
+
+import org.apache.derby.iapi.reference.ClassName;
+
+import org.apache.derby.iapi.util.JBitSet;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import java.lang.reflect.Modifier;
+
+import java.util.Vector;
+
+/**
+ * This node type converts a value in the SQL domain to a value in the Java
+ * domain.
+ */
+
+public class SQLToJavaValueNode extends JavaValueNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ ValueNode value;
+
+ LocalField returnsNullOnNullState;
+
+ /**
+ * Constructor for a SQLToJavaValueNode
+ *
+ * @param value A ValueNode representing a SQL value to convert to
+ * the Java domain.
+ */
+
+ public void init(Object value)
+ {
+ this.value = (ValueNode) value;
+ }
+
+ /**
+ * Prints the sub-nodes of this object. See QueryTreeNode.java for
+ * how tree printing is supposed to work.
+ *
+ * @param depth The depth of this node in the tree
+ *
+ * @return Nothing
+ */
+
+ public void printSubNodes(int depth)
+ {
+ if (SanityManager.DEBUG)
+ {
+ int parm;
+
+ super.printSubNodes(depth);
+ if (value != null)
+ {
+ printLabel(depth, "value: ");
+ value.treePrint(depth + 1);
+ }
+ }
+ }
+
+ /**
+ * Returns the name of the java class type that this node coerces to.
+ *
+ * @return name of java class type
+ *
+ */
+ public String getJavaTypeName()
+ {
+ JSQLType myType = getJSQLType();
+
+ if ( myType == null ) { return ""; }
+ else { return mapToTypeID( myType ).getCorrespondingJavaTypeName(); }
+ }
+
+ /**
+ * Returns the name of the java primitive type that this node coerces to.
+ *
+ * @return name of java primitive type
+ *
+ * @exception StandardException Thrown on error
+ */
+ public String getPrimitiveTypeName()
+ throws StandardException
+ {
+ JSQLType myType = getJSQLType();
+
+ if ( myType == null )
+ {
+ return "";
+ }
+ else
+ {
+ return
+ getTypeCompiler(mapToTypeID( myType )).
+ getCorrespondingPrimitiveTypeName();
+ }
+ }
+
+ /**
+ * Get the JSQLType that corresponds to this node. Could be a SQLTYPE,
+ * a Java primitive, or a Java class.
+ *
+ * Overrides method in JavaValueNode.
+ *
+ * @return the corresponding JSQLType
+ *
+ */
+ public JSQLType getJSQLType
+ (
+ )
+ {
+ if ( jsqlType == null )
+ {
+ if ( value.isParameterNode() )
+ {
+ jsqlType = ((ParameterNode) value).getJSQLType();
+ }
+ else
+ {
+ DataTypeDescriptor dtd = value.getTypeServices();
+ if (dtd != null)
+ jsqlType = new JSQLType( dtd );
+ }
+ }
+
+ return jsqlType;
+ }
+
+
+ /**
+ * Set the clause that this node appears in.
+ *
+ * @param clause The clause that this node appears in.
+ *
+ * @return Nothing.
+ */
+ public void setClause(int clause)
+ {
+ super.setClause(clause);
+ value.setClause(clause);
+ }
+
+ /**
+ * Bind this expression. This means binding the sub-expressions,
+ * as well as figuring out what the return type is for this expression.
+ *
+ * @param fromList The FROM list for the query this
+ * expression is in, for binding columns.
+ * @param subqueryList The subquery list being built as we find
+ * SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return this
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public JavaValueNode bindExpression(
+ FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ /* Bind the expression under us */
+ value = value.bindExpression(fromList, subqueryList,
+ aggregateVector);
+
+ return this;
+ }
+
+ /**
+ * Remap all ColumnReferences in this tree to be clones of the
+ * underlying expression.
+ *
+ * @return JavaValueNode The remapped expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public JavaValueNode remapColumnReferencesToExpressions()
+ throws StandardException
+ {
+ value = value.remapColumnReferencesToExpressions();
+ return this;
+ }
+
+ /**
+ * Categorize this predicate. Initially, this means
+ * building a bit map of the referenced tables for each predicate.
+ * If the source of this ColumnReference (at the next underlying level)
+ * is not a ColumnReference or a VirtualColumnNode then this predicate
+ * will not be pushed down.
+ *
+ * For example, in:
+ * select * from (select 1 from s) a (x) where x = 1
+ * we will not push down x = 1.
+ * NOTE: It would be easy to handle the case of a constant, but if the
+ * inner SELECT returns an arbitrary expression, then we would have to copy
+ * that tree into the pushed predicate, and that tree could contain
+ * subqueries and method calls.
+ * RESOLVE - revisit this issue once we have views.
+ *
+ * @param referencedTabs JBitSet with bit map of referenced FromTables
+ * @param simplePredsOnly Whether or not to consider method
+ * calls, field references and conditional nodes
+ * when building bit map
+ *
+ * @return boolean Whether or not source.expression is a ColumnReference
+ * or a VirtualColumnNode.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
+ throws StandardException
+ {
+ return value.categorize(referencedTabs, simplePredsOnly);
+ }
+
+ /**
+ * Preprocess an expression tree. We do a number of transformations
+ * here (including subqueries, IN lists, LIKE and BETWEEN) plus
+ * subquery flattening.
+ * NOTE: This is done before the outer ResultSetNode is preprocessed.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void preprocess(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList)
+ throws StandardException
+ {
+ value.preprocess(numTables,
+ outerFromList, outerSubqueryList,
+ outerPredicateList);
+ }
+
+ /**
+ * Return the variant type for the underlying expression.
+ * The variant type can be:
+ * VARIANT - variant within a scan
+ * (method calls and non-static field access)
+ * SCAN_INVARIANT - invariant within a scan
+ * (column references from outer tables)
+ * QUERY_INVARIANT - invariant within the life of a query
+ * (constant expressions)
+ *
+ * @return The variant type for the underlying expression.
+ * @exception StandardException thrown on error
+ */
+ protected int getOrderableVariantType() throws StandardException
+ {
+ return value.getOrderableVariantType();
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // CODE GENERATION METHODS
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Generate code to get the Java value out of a SQL value.
+ *
+ * Every SQL type has a corresponding Java type. The getObject() method
+ * on the SQL type gets the right Java type.
+ *
+ * The generated code will be:
+ *
+ * (<Java type name>) ((DataValueDescriptor)
+ * <generated value>.getObject())
+ *
+ * where <Java type name> comes from the getCorrespondingJavaTypeName()
+ * method of the value's TypeId.
+ *
+ * @param acb The ExpressionClassBuilder for the class being built
+ * @param mb The method the expression will go into
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateExpression(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ throws StandardException
+ {
+ /* Compile the expression under us */
+ generateSQLValue( acb, mb );
+
+ /* now cast the SQLValue to a Java value */
+ generateJavaValue( acb, mb);
+ }
+
+ /**
+ * Generate the SQLvalue that this node wraps.
+ *
+ * @param acb The ExpressionClassBuilder for the class being built
+ * @param mb The method the expression will go into
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateSQLValue(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ throws StandardException
+ {
+ value.generateExpression(acb, mb);
+ }
+
+ /**
+ * Generate code to cast the SQLValue to a Java value.
+ *
+ *
+ * @param acb The ExpressionClassBuilder for the class being built
+ * @param mb The method the expression will go into
+ * @param SQLValue An Expression holding the SQLValue.
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateJavaValue
+ (
+ ExpressionClassBuilder acb,
+ MethodBuilder mbex
+ )
+ throws StandardException
+ {
+ /* If this is a conversion to a primitive type, then call the
+ * appropriate method for getting the primitive value and
+ * cast it to the primitive type.
+ * NOTE: We first call Activation.nullToPrimitiveTest(),
+ * which will throw a StandardException if the value is null
+ */
+ if ( isPrimitiveType() || mustCastToPrimitive() )
+ {
+ String primitiveTN = value.getTypeCompiler().getCorrespondingPrimitiveTypeName();
+
+ /* Put the code to check if the object is null and to
+ * get the primitive value in a method call. This is
+ * necessary because we are generating an expression here and
+ * cannot have multiple statements.
+ * The method call will take SQLValue as a parameter.
+ */
+ String[] pd = new String[1];
+ pd[0] = getSQLValueInterfaceName(); // parameter "param1"
+
+ MethodBuilder mb = acb.newGeneratedFun(primitiveTN, Modifier.PRIVATE, pd);
+
+ mb.getParameter(0);
+
+ if (returnsNullOnNullState != null)
+ {
+ generateReturnsNullOnNullCheck(mb);
+ }
+ else
+ {
+ mb.dup();
+ mb.upCast(ClassName.DataValueDescriptor);
+ mb.push(primitiveTN);
+ mb.callMethod(VMOpcode.INVOKESTATIC, ClassName.BaseActivation, "nullToPrimitiveTest", "void", 2);
+ }
+
+ // stack is dvd
+
+ /* Generate the code to get the primitive value */
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor,
+ value.getTypeCompiler().getPrimitiveMethodName(), primitiveTN, 0);
+
+ mb.methodReturn();
+ mb.complete();
+
+ /* Generate the call to the new method, with the parameter */
+
+ mbex.pushThis();
+ mbex.swap(); // caller pushed out parameter
+ mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), primitiveTN, 1);
+ }
+ else
+ {
+ if (returnsNullOnNullState != null)
+ generateReturnsNullOnNullCheck(mbex);
+
+ /* Call getObject() to get the right type of Java value */
+ mbex.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "getObject",
+ "java.lang.Object", 0);
+
+ mbex.cast(value.getTypeId().getCorrespondingJavaTypeName());
+ }
+ }
+
+ /**
+ Generate the code for the returns Null on Null input check..
+ Stack must contain the DataDescriptorValue.
+ */
+
+ private void generateReturnsNullOnNullCheck(MethodBuilder mb)
+ {
+ mb.dup();
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Storable,
+ "isNull", "boolean", 0);
+
+ mb.conditionalIf();
+ mb.push(true);
+ mb.startElseCode();
+ mb.getField(returnsNullOnNullState);
+ mb.completeConditional();
+
+ mb.putField(returnsNullOnNullState);
+ mb.endStatement();
+ }
+
+
+ /**
+ * Get the type name of the SQLValue we generate.
+ *
+ * @return name of interface corresponding to SQLValue
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+ public String getSQLValueInterfaceName()
+ throws StandardException
+ {
+ return value.getTypeCompiler().interfaceName();
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // OTHER VALUE NODE METHODS
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Get the SQL ValueNode that is being converted to a JavaValueNode
+ *
+ * @return The underlying SQL ValueNode
+ */
+ ValueNode getSQLValueNode()
+ {
+ return value;
+ }
+
+ /** @see ValueNode#getConstantValueAsObject
+ *
+ * @exception StandardException Thrown on error
+ */
+ Object getConstantValueAsObject()
+ throws StandardException
+ {
+ return value.getConstantValueAsObject();
+ }
+
+ /**
+ * Accept a visitor, and call v.visit()
+ * on child nodes as necessary.
+ *
+ * @param v the visitor
+ *
+ * @exception StandardException on error
+ */
+ public Visitable accept(Visitor v)
+ throws StandardException
+ {
+ Visitable returnNode = v.visit(this);
+
+ if (v.skipChildren(this))
+ {
+ return returnNode;
+ }
+
+ if (value != null && !v.stopTraversal())
+ {
+ value = (ValueNode)value.accept(v);
+ }
+
+ return returnNode;
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java Fri Sep 24 10:33:20 2004
@@ -1,265 +1,265 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.context.ContextManager;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-
-import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
-import org.apache.derby.iapi.store.access.ConglomerateController;
-import org.apache.derby.iapi.store.access.TransactionController;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-
-import org.apache.derby.iapi.reference.SQLState;
-import org.apache.derby.iapi.reference.ClassName;
-import org.apache.derby.iapi.services.loader.GeneratedClass;
-
-import org.apache.derby.iapi.util.ByteArray;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import java.lang.reflect.Modifier;
-
-/**
- * A StatementNode represents a single statement in the language. It is
- * the top node for any statement.
- * <p>
- * StatementNode controls the class generation for query tree nodes.
- *
- * @author Jeff Lichtman
- */
-
-/*
-* History:
-* 5/8/97 Rick Hilleags Moved node-name-string to child classes.
-*/
-
-public abstract class StatementNode extends QueryTreeNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- /**
- * By default, assume StatementNodes are atomic.
- * The rare statements that aren't atomic (e.g.
- * CALL method()) override this.
- *
- * @return true if the statement is atomic
- *
- * @exception StandardException Thrown on error
- */
- public boolean isAtomic() throws StandardException
- {
- return true;
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- return "statementType: " + statementToString() + "\n" +
- super.toString();
- }
- else
- {
- return "";
- }
- }
-
- public abstract String statementToString();
-
- /**
- * create the outer shell class builder for the class we will
- * be generating, generate the expression to stuff in it,
- * and turn it into a class.
- */
- static final int NEED_DDL_ACTIVATION = 5;
- static final int NEED_CURSOR_ACTIVATION = 4;
- static final int NEED_PARAM_ACTIVATION = 2;
- static final int NEED_ROW_ACTIVATION = 1;
- static final int NEED_NOTHING_ACTIVATION = 0;
-
- abstract int activationKind();
-
- /* We need to get some kind of table lock (IX here) at the beginning of
- * compilation of DMLModStatementNode and DDLStatementNode, to prevent the
- * interference of insert/update/delete/DDL compilation and DDL execution,
- * see beetle 3976, 4343, and $WS/language/SolutionsToConcurrencyIssues.txt
- */
- protected TableDescriptor lockTableForCompilation(TableDescriptor td)
- throws StandardException
- {
- DataDictionary dd = getDataDictionary();
-
- /* we need to lock only if the data dictionary is in DDL cache mode
- */
- if (dd.getCacheMode() == DataDictionary.DDL_MODE)
- {
- ConglomerateController heapCC;
- TransactionController tc =
- getLanguageConnectionContext().getTransactionCompile();
-
- heapCC = tc.openConglomerate(td.getHeapConglomerateId(),
- false,
- TransactionController.OPENMODE_FORUPDATE |
- TransactionController.OPENMODE_FOR_LOCK_ONLY,
- TransactionController.MODE_RECORD,
- TransactionController.ISOLATION_SERIALIZABLE);
- heapCC.close();
- /*
- ** Need to get TableDescriptor again after getting the lock, in
- ** case for example, a concurrent add column thread commits
- ** while we are binding.
- */
- String tableName = td.getName();
- td = getTableDescriptor(td.getName(), getSchemaDescriptor(td.getSchemaName()));
- if (td == null)
- {
- throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, tableName);
- }
- }
- return td;
- }
-
-
- /**
- * Do code generation for this statement.
- *
- * @param the generated byte code for this statement.
- * if non-null, then the byte code is saved
- * here.
- *
- * @return A GeneratedClass for this statement
- *
- * @exception StandardException Thrown on error
- */
- public GeneratedClass generate(ByteArray byteCode) throws StandardException
- {
- // start the new activation class.
- // it starts with the Execute method
- // and the appropriate superclass (based on
- // statement type, from inspecting the queryTree).
-
- int nodeChoice = activationKind();
-
- /* RESOLVE: Activation hierarchy was way too complicated
- * and added no value. Simple thing to do was to simply
- * leave calling code alone and to handle here and to
- * eliminate unnecessary classes.
- */
- String superClass;
- switch (nodeChoice)
- {
- case NEED_CURSOR_ACTIVATION:
- superClass = ClassName.CursorActivation;
- break;
- case NEED_DDL_ACTIVATION:
- return getClassFactory().loadGeneratedClass(
- "org.apache.derby.impl.sql.execute.ConstantActionActivation", null);
-
- case NEED_NOTHING_ACTIVATION :
- case NEED_ROW_ACTIVATION :
- case NEED_PARAM_ACTIVATION :
- superClass = ClassName.BaseActivation;
- break;
- default :
- throw StandardException.newException(SQLState.LANG_UNAVAILABLE_ACTIVATION_NEED,
- String.valueOf(nodeChoice));
- }
-
- ActivationClassBuilder generatingClass = new ActivationClassBuilder(
- superClass,
- getCompilerContext());
- MethodBuilder executeMethod = generatingClass.getExecuteMethod();
-
-
- /*
- ** the resultSet variable is cached.
- **
- ** resultSet = (resultSet == null) ? ... : resultSet
- */
-
- executeMethod.pushThis();
- executeMethod.getField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
- executeMethod.conditionalIfNull();
-
- /* We should generate the result set here. However, the generated
- * code size may be too big to fit in a conditional statement for
- * Java compiler to handle (it has a jump/branch step limit). For
- * example, a extremely huge insert is issued with many many rows
- * (beetle 4293). We fork a worker method here to get the
- * generated result set, pass our parameter to it and call it.
- */
- MethodBuilder mbWorker = generatingClass.getClassBuilder().newMethodBuilder(
- Modifier.PROTECTED,
- ClassName.ResultSet,
- "fillResultSet");
- mbWorker.addThrownException(ClassName.StandardException);
-
- // we expect to get back an expression that will give a resultSet
- // the nodes use the generatingClass: they add expression functions
- // to it, and then use those functions in their expressions.
- generate(generatingClass, mbWorker);
-
- mbWorker.methodReturn();
- mbWorker.complete();
- executeMethod.pushThis();
- executeMethod.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null,
- "fillResultSet", ClassName.ResultSet, 0);
-
- executeMethod.startElseCode(); // this is here as the compiler only supports ? :
- executeMethod.pushThis();
- executeMethod.getField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
- executeMethod.completeConditional();
-
- executeMethod.pushThis();
- executeMethod.swap();
- executeMethod.putField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
-
- executeMethod.endStatement();
-
- // wrap up the activation class definition
- // generate on the tree gave us back the newExpr
- // for getting a result set on the tree.
- // we put it in a return statement and stuff
- // it in the execute method of the activation.
- // The generated statement is the expression:
- // the activation class builder takes care of constructing it
- // for us, given the resultSetExpr to use.
- // return (this.resultSet = #resultSetExpr);
- generatingClass.finishExecuteMethod(this instanceof CursorNode);
-
- // wrap up the constructor by putting a return at the end of it
- generatingClass.finishConstructor();
-
- // cook the completed class into a real class
- // and stuff it into activationClass
- GeneratedClass activationClass = generatingClass.getGeneratedClass(byteCode);
-
- return activationClass;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.context.ContextManager;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+import org.apache.derby.iapi.store.access.ConglomerateController;
+import org.apache.derby.iapi.store.access.TransactionController;
+
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.reference.ClassName;
+import org.apache.derby.iapi.services.loader.GeneratedClass;
+
+import org.apache.derby.iapi.util.ByteArray;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * A StatementNode represents a single statement in the language. It is
+ * the top node for any statement.
+ * <p>
+ * StatementNode controls the class generation for query tree nodes.
+ *
+ * @author Jeff Lichtman
+ */
+
+/*
+* History:
+* 5/8/97 Rick Hilleags Moved node-name-string to child classes.
+*/
+
+public abstract class StatementNode extends QueryTreeNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ /**
+ * By default, assume StatementNodes are atomic.
+ * The rare statements that aren't atomic (e.g.
+ * CALL method()) override this.
+ *
+ * @return true if the statement is atomic
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean isAtomic() throws StandardException
+ {
+ return true;
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ return "statementType: " + statementToString() + "\n" +
+ super.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ public abstract String statementToString();
+
+ /**
+ * create the outer shell class builder for the class we will
+ * be generating, generate the expression to stuff in it,
+ * and turn it into a class.
+ */
+ static final int NEED_DDL_ACTIVATION = 5;
+ static final int NEED_CURSOR_ACTIVATION = 4;
+ static final int NEED_PARAM_ACTIVATION = 2;
+ static final int NEED_ROW_ACTIVATION = 1;
+ static final int NEED_NOTHING_ACTIVATION = 0;
+
+ abstract int activationKind();
+
+ /* We need to get some kind of table lock (IX here) at the beginning of
+ * compilation of DMLModStatementNode and DDLStatementNode, to prevent the
+ * interference of insert/update/delete/DDL compilation and DDL execution,
+ * see beetle 3976, 4343, and $WS/language/SolutionsToConcurrencyIssues.txt
+ */
+ protected TableDescriptor lockTableForCompilation(TableDescriptor td)
+ throws StandardException
+ {
+ DataDictionary dd = getDataDictionary();
+
+ /* we need to lock only if the data dictionary is in DDL cache mode
+ */
+ if (dd.getCacheMode() == DataDictionary.DDL_MODE)
+ {
+ ConglomerateController heapCC;
+ TransactionController tc =
+ getLanguageConnectionContext().getTransactionCompile();
+
+ heapCC = tc.openConglomerate(td.getHeapConglomerateId(),
+ false,
+ TransactionController.OPENMODE_FORUPDATE |
+ TransactionController.OPENMODE_FOR_LOCK_ONLY,
+ TransactionController.MODE_RECORD,
+ TransactionController.ISOLATION_SERIALIZABLE);
+ heapCC.close();
+ /*
+ ** Need to get TableDescriptor again after getting the lock, in
+ ** case for example, a concurrent add column thread commits
+ ** while we are binding.
+ */
+ String tableName = td.getName();
+ td = getTableDescriptor(td.getName(), getSchemaDescriptor(td.getSchemaName()));
+ if (td == null)
+ {
+ throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, tableName);
+ }
+ }
+ return td;
+ }
+
+
+ /**
+ * Do code generation for this statement.
+ *
+ * @param the generated byte code for this statement.
+ * if non-null, then the byte code is saved
+ * here.
+ *
+ * @return A GeneratedClass for this statement
+ *
+ * @exception StandardException Thrown on error
+ */
+ public GeneratedClass generate(ByteArray byteCode) throws StandardException
+ {
+ // start the new activation class.
+ // it starts with the Execute method
+ // and the appropriate superclass (based on
+ // statement type, from inspecting the queryTree).
+
+ int nodeChoice = activationKind();
+
+ /* RESOLVE: Activation hierarchy was way too complicated
+ * and added no value. Simple thing to do was to simply
+ * leave calling code alone and to handle here and to
+ * eliminate unnecessary classes.
+ */
+ String superClass;
+ switch (nodeChoice)
+ {
+ case NEED_CURSOR_ACTIVATION:
+ superClass = ClassName.CursorActivation;
+ break;
+ case NEED_DDL_ACTIVATION:
+ return getClassFactory().loadGeneratedClass(
+ "org.apache.derby.impl.sql.execute.ConstantActionActivation", null);
+
+ case NEED_NOTHING_ACTIVATION :
+ case NEED_ROW_ACTIVATION :
+ case NEED_PARAM_ACTIVATION :
+ superClass = ClassName.BaseActivation;
+ break;
+ default :
+ throw StandardException.newException(SQLState.LANG_UNAVAILABLE_ACTIVATION_NEED,
+ String.valueOf(nodeChoice));
+ }
+
+ ActivationClassBuilder generatingClass = new ActivationClassBuilder(
+ superClass,
+ getCompilerContext());
+ MethodBuilder executeMethod = generatingClass.getExecuteMethod();
+
+
+ /*
+ ** the resultSet variable is cached.
+ **
+ ** resultSet = (resultSet == null) ? ... : resultSet
+ */
+
+ executeMethod.pushThis();
+ executeMethod.getField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
+ executeMethod.conditionalIfNull();
+
+ /* We should generate the result set here. However, the generated
+ * code size may be too big to fit in a conditional statement for
+ * Java compiler to handle (it has a jump/branch step limit). For
+ * example, a extremely huge insert is issued with many many rows
+ * (beetle 4293). We fork a worker method here to get the
+ * generated result set, pass our parameter to it and call it.
+ */
+ MethodBuilder mbWorker = generatingClass.getClassBuilder().newMethodBuilder(
+ Modifier.PROTECTED,
+ ClassName.ResultSet,
+ "fillResultSet");
+ mbWorker.addThrownException(ClassName.StandardException);
+
+ // we expect to get back an expression that will give a resultSet
+ // the nodes use the generatingClass: they add expression functions
+ // to it, and then use those functions in their expressions.
+ generate(generatingClass, mbWorker);
+
+ mbWorker.methodReturn();
+ mbWorker.complete();
+ executeMethod.pushThis();
+ executeMethod.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null,
+ "fillResultSet", ClassName.ResultSet, 0);
+
+ executeMethod.startElseCode(); // this is here as the compiler only supports ? :
+ executeMethod.pushThis();
+ executeMethod.getField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
+ executeMethod.completeConditional();
+
+ executeMethod.pushThis();
+ executeMethod.swap();
+ executeMethod.putField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
+
+ executeMethod.endStatement();
+
+ // wrap up the activation class definition
+ // generate on the tree gave us back the newExpr
+ // for getting a result set on the tree.
+ // we put it in a return statement and stuff
+ // it in the execute method of the activation.
+ // The generated statement is the expression:
+ // the activation class builder takes care of constructing it
+ // for us, given the resultSetExpr to use.
+ // return (this.resultSet = #resultSetExpr);
+ generatingClass.finishExecuteMethod(this instanceof CursorNode);
+
+ // wrap up the constructor by putting a return at the end of it
+ generatingClass.finishConstructor();
+
+ // cook the completed class into a real class
+ // and stuff it into activationClass
+ GeneratedClass activationClass = generatingClass.getGeneratedClass(byteCode);
+
+ return activationClass;
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticClassFieldReferenceNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticClassFieldReferenceNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticClassFieldReferenceNode.java Fri Sep 24 10:33:20 2004
@@ -1,238 +1,238 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.monitor.Monitor;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.reference.SQLState;
-
-import org.apache.derby.iapi.services.loader.ClassInspector;
-
-import org.apache.derby.iapi.store.access.Qualifier;
-
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-
-import org.apache.derby.iapi.util.JBitSet;
-
-import java.lang.reflect.Member;
-import java.lang.reflect.Modifier;
-
-import java.util.Vector;
-
-/**
- * A StaticClassFieldReferenceNode represents a Java static field reference from
- * a Class (as opposed to an Object). Field references can be
- * made in DML (as expressions).
- *
- * @author Jerry Brenner
- */
-
-public final class StaticClassFieldReferenceNode extends JavaValueNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /*
- ** Name of the field.
- */
- private String fieldName;
-
- /* The class name */
- private String javaClassName;
- private boolean classNameDelimitedIdentifier;
-
- /**
- The field we are going to access.
- */
- private Member field;
-
- /**
- * Initializer for a StaticClassFieldReferenceNode
- *
- * @param javaClassName The class name
- * @param fieldName The field name
- */
- public void init(Object javaClassName, Object fieldName, Object classNameDelimitedIdentifier)
- {
- this.fieldName = (String) fieldName;
- this.javaClassName = (String) javaClassName;
- this.classNameDelimitedIdentifier = ((Boolean) classNameDelimitedIdentifier).booleanValue();
- }
-
- /**
- * Bind this expression. This means binding the sub-expressions,
- * as well as figuring out what the return type is for this expression.
- *
- * @param fromList The FROM list for the query this
- * expression is in, for binding columns.
- * @param subqueryList The subquery list being built as we find SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
-
- public JavaValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- ClassInspector classInspector = getClassFactory().getClassInspector();
-
-
- if (((getCompilerContext().getReliability() & CompilerContext.INTERNAL_SQL_ILLEGAL) != 0)
- || !javaClassName.startsWith("java.sql.")) {
-
- throw StandardException.newException(SQLState.LANG_SYNTAX_ERROR, javaClassName + "::" + fieldName);
- }
-
- javaClassName = verifyClassExist(javaClassName, ! classNameDelimitedIdentifier);
-
- /*
- ** Find the field that is public.
- */
- field = classInspector.findPublicField(javaClassName,
- fieldName,
- true);
- /* Get the field type */
- setJavaTypeName( classInspector.getType(field) );
-
- return this;
-
- }
-
- /**
- * Preprocess an expression tree. We do a number of transformations
- * here (including subqueries, IN lists, LIKE and BETWEEN) plus
- * subquery flattening.
- * NOTE: This is done before the outer ResultSetNode is preprocessed.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown on error
- */
- public void preprocess(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList)
- throws StandardException
- {
- }
-
- /**
- * Categorize this predicate. Initially, this means
- * building a bit map of the referenced tables for each predicate.
- * If the source of this ColumnReference (at the next underlying level)
- * is not a ColumnReference or a VirtualColumnNode then this predicate
- * will not be pushed down.
- *
- * For example, in:
- * select * from (select 1 from s) a (x) where x = 1
- * we will not push down x = 1.
- * NOTE: It would be easy to handle the case of a constant, but if the
- * inner SELECT returns an arbitrary expression, then we would have to copy
- * that tree into the pushed predicate, and that tree could contain
- * subqueries and method calls.
- * RESOLVE - revisit this issue once we have views.
- *
- * @param referencedTabs JBitSet with bit map of referenced FromTables
- * @param simplePredsOnly Whether or not to consider method
- * calls, field references and conditional nodes
- * when building bit map
- *
- * @return boolean Whether or not source.expression is a ColumnReference
- * or a VirtualColumnNode.
- */
- public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
- {
- return true;
- }
-
- /**
- * Remap all ColumnReferences in this tree to be clones of the
- * underlying expression.
- *
- * @return JavaValueNode The remapped expression tree.
- *
- * @exception StandardException Thrown on error
- */
- public JavaValueNode remapColumnReferencesToExpressions()
- throws StandardException
- {
- return this;
- }
-
- /**
- * Return the variant type for the underlying expression.
- * The variant type can be:
- * VARIANT - variant within a scan
- * (method calls and non-static field access)
- * SCAN_INVARIANT - invariant within a scan
- * (column references from outer tables)
- * QUERY_INVARIANT - invariant within the life of a query
- * CONSTANT - constant
- *
- * @return The variant type for the underlying expression.
- */
- protected int getOrderableVariantType()
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(field != null,
- "field is expected to be non-null");
- }
- /* Static field references are invariant for the life
- * of the query, non-static are variant.
- */
- if (Modifier.isFinal(field.getModifiers()))
- {
- return Qualifier.CONSTANT;
- }
- else
- {
- return Qualifier.VARIANT;
- }
- }
-
- /**
- * @see QueryTreeNode#generate
- *
- * @exception StandardException Thrown on error
- */
- public void generateExpression(ExpressionClassBuilder acb,
- MethodBuilder mb)
- {
- /*
- ** Generate the following:
- **
- ** <javaClassName>.<field name>
- */
-
- mb.getStaticField(field.getDeclaringClass().getName(),
- fieldName,
- getJavaTypeName());
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.monitor.Monitor;
+
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.reference.SQLState;
+
+import org.apache.derby.iapi.services.loader.ClassInspector;
+
+import org.apache.derby.iapi.store.access.Qualifier;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+
+import org.apache.derby.iapi.util.JBitSet;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+
+import java.util.Vector;
+
+/**
+ * A StaticClassFieldReferenceNode represents a Java static field reference from
+ * a Class (as opposed to an Object). Field references can be
+ * made in DML (as expressions).
+ *
+ * @author Jerry Brenner
+ */
+
+public final class StaticClassFieldReferenceNode extends JavaValueNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /*
+ ** Name of the field.
+ */
+ private String fieldName;
+
+ /* The class name */
+ private String javaClassName;
+ private boolean classNameDelimitedIdentifier;
+
+ /**
+ The field we are going to access.
+ */
+ private Member field;
+
+ /**
+ * Initializer for a StaticClassFieldReferenceNode
+ *
+ * @param javaClassName The class name
+ * @param fieldName The field name
+ */
+ public void init(Object javaClassName, Object fieldName, Object classNameDelimitedIdentifier)
+ {
+ this.fieldName = (String) fieldName;
+ this.javaClassName = (String) javaClassName;
+ this.classNameDelimitedIdentifier = ((Boolean) classNameDelimitedIdentifier).booleanValue();
+ }
+
+ /**
+ * Bind this expression. This means binding the sub-expressions,
+ * as well as figuring out what the return type is for this expression.
+ *
+ * @param fromList The FROM list for the query this
+ * expression is in, for binding columns.
+ * @param subqueryList The subquery list being built as we find SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public JavaValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ ClassInspector classInspector = getClassFactory().getClassInspector();
+
+
+ if (((getCompilerContext().getReliability() & CompilerContext.INTERNAL_SQL_ILLEGAL) != 0)
+ || !javaClassName.startsWith("java.sql.")) {
+
+ throw StandardException.newException(SQLState.LANG_SYNTAX_ERROR, javaClassName + "::" + fieldName);
+ }
+
+ javaClassName = verifyClassExist(javaClassName, ! classNameDelimitedIdentifier);
+
+ /*
+ ** Find the field that is public.
+ */
+ field = classInspector.findPublicField(javaClassName,
+ fieldName,
+ true);
+ /* Get the field type */
+ setJavaTypeName( classInspector.getType(field) );
+
+ return this;
+
+ }
+
+ /**
+ * Preprocess an expression tree. We do a number of transformations
+ * here (including subqueries, IN lists, LIKE and BETWEEN) plus
+ * subquery flattening.
+ * NOTE: This is done before the outer ResultSetNode is preprocessed.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void preprocess(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList)
+ throws StandardException
+ {
+ }
+
+ /**
+ * Categorize this predicate. Initially, this means
+ * building a bit map of the referenced tables for each predicate.
+ * If the source of this ColumnReference (at the next underlying level)
+ * is not a ColumnReference or a VirtualColumnNode then this predicate
+ * will not be pushed down.
+ *
+ * For example, in:
+ * select * from (select 1 from s) a (x) where x = 1
+ * we will not push down x = 1.
+ * NOTE: It would be easy to handle the case of a constant, but if the
+ * inner SELECT returns an arbitrary expression, then we would have to copy
+ * that tree into the pushed predicate, and that tree could contain
+ * subqueries and method calls.
+ * RESOLVE - revisit this issue once we have views.
+ *
+ * @param referencedTabs JBitSet with bit map of referenced FromTables
+ * @param simplePredsOnly Whether or not to consider method
+ * calls, field references and conditional nodes
+ * when building bit map
+ *
+ * @return boolean Whether or not source.expression is a ColumnReference
+ * or a VirtualColumnNode.
+ */
+ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
+ {
+ return true;
+ }
+
+ /**
+ * Remap all ColumnReferences in this tree to be clones of the
+ * underlying expression.
+ *
+ * @return JavaValueNode The remapped expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public JavaValueNode remapColumnReferencesToExpressions()
+ throws StandardException
+ {
+ return this;
+ }
+
+ /**
+ * Return the variant type for the underlying expression.
+ * The variant type can be:
+ * VARIANT - variant within a scan
+ * (method calls and non-static field access)
+ * SCAN_INVARIANT - invariant within a scan
+ * (column references from outer tables)
+ * QUERY_INVARIANT - invariant within the life of a query
+ * CONSTANT - constant
+ *
+ * @return The variant type for the underlying expression.
+ */
+ protected int getOrderableVariantType()
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(field != null,
+ "field is expected to be non-null");
+ }
+ /* Static field references are invariant for the life
+ * of the query, non-static are variant.
+ */
+ if (Modifier.isFinal(field.getModifiers()))
+ {
+ return Qualifier.CONSTANT;
+ }
+ else
+ {
+ return Qualifier.VARIANT;
+ }
+ }
+
+ /**
+ * @see QueryTreeNode#generate
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void generateExpression(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ {
+ /*
+ ** Generate the following:
+ **
+ ** <javaClassName>.<field name>
+ */
+
+ mb.getStaticField(field.getDeclaringClass().getName(),
+ fieldName,
+ getJavaTypeName());
+ }
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java Fri Sep 24 10:33:20 2004
@@ -1,1006 +1,1006 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-import org.apache.derby.iapi.sql.compile.C_NodeTypes;
-import org.apache.derby.iapi.types.JSQLType;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.TypeId;
-
-import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
-
-import org.apache.derby.iapi.reference.ClassName;
-import org.apache.derby.iapi.reference.SQLState;
-import org.apache.derby.iapi.reference.JDBC30Translation;
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.iapi.services.loader.ClassInspector;
-import org.apache.derby.iapi.services.compiler.LocalField;
-
-import org.apache.derby.iapi.util.JBitSet;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import org.apache.derby.iapi.sql.conn.Authorizer;
-
-import org.apache.derby.catalog.AliasInfo;
-import org.apache.derby.catalog.TypeDescriptor;
-import org.apache.derby.catalog.types.RoutineAliasInfo;
-import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
-
-import org.apache.derby.catalog.UUID;
-
-import java.util.Vector;
-import java.lang.reflect.Modifier;
-
-/**
- * A StaticMethodCallNode represents a static method call from a Class
- * (as opposed to from an Object).
-
- For a procedure the call requires that the arguments be ? parameters.
- The parameter is *logically* passed into the method call a number of different ways.
-
- <P>
- For a application call like CALL MYPROC(?) the logically Java method call is
- (in psuedo Java/SQL code) (examples with CHAR(10) parameter)
- <BR>
- Fixed length IN parameters - com.acme.MyProcedureMethod(?)
- <BR>
- Variable length IN parameters - com.acme.MyProcedureMethod(CAST (? AS CHAR(10))
- <BR>
- Fixed length INOUT parameter -
- String[] holder = new String[] {?}; com.acme.MyProcedureMethod(holder); ? = holder[0]
- <BR>
- Variable length INOUT parameter -
- String[] holder = new String[] {CAST (? AS CHAR(10)}; com.acme.MyProcedureMethod(holder); ? = CAST (holder[0] AS CHAR(10))
-
- <BR>
- Fixed length OUT parameter -
- String[] holder = new String[1]; com.acme.MyProcedureMethod(holder); ? = holder[0]
-
- <BR>
- Variable length INOUT parameter -
- String[] holder = new String[1]; com.acme.MyProcedureMethod(holder); ? = CAST (holder[0] AS CHAR(10))
-
-
- <P>
- For static method calls there is no pre-definition of an IN or INOUT parameter, so a call to CallableStatement.registerOutParameter()
- makes the parameter an INOUT parameter, provided:
- - the parameter is passed directly to the method call (no casts or expressions).
- - the method's parameter type is a Java array type.
-
- Since this is a dynmaic decision we compile in code to take both paths, based upon a boolean isINOUT which is dervied from the
- ParameterValueSet. Code is logically (only single parameter String[] shown here). Note, no casts can exist here.
-
- boolean isINOUT = getParameterValueSet().getParameterMode(0) == PARAMETER_IN_OUT;
- if (isINOUT) {
- String[] holder = new String[] {?}; com.acme.MyProcedureMethod(holder); ? = holder[0]
-
- } else {
- com.acme.MyProcedureMethod(?)
- }
-
- *
- * @author Jerry Brenner
- */
-public class StaticMethodCallNode extends MethodCallNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- private TableName procedureName;
-
- private LocalField[] outParamArrays;
- private int[] applicationParameterNumbers;
-
- private boolean isSystemCode;
- private boolean alreadyBound;
-
- private LocalField returnsNullOnNullState;
-
-
- AliasDescriptor ad;
-
-
- /**
- * Intializer for a NonStaticMethodCallNode
- *
- * @param methodName The name of the method to call
- * @param javaClassName The name of the java class that the static method belongs to.
- */
- public void init(Object methodName, Object javaClassName)
- {
- if (methodName instanceof String)
- init(methodName);
- else {
- procedureName = (TableName) methodName;
- init(procedureName.getTableName());
- }
-
- this.javaClassName = (String) javaClassName;
- }
-
- /**
- * Bind this expression. This means binding the sub-expressions,
- * as well as figuring out what the return type is for this expression.
- *
- * @param fromList The FROM list for the query this
- * expression is in, for binding columns.
- * @param subqueryList The subquery list being built as we find SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return this or an AggregateNode
- *
- * @exception StandardException Thrown on error
- */
-
- public JavaValueNode bindExpression(
- FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- // for a function we can get called recursively
- if (alreadyBound)
- return this;
-
-
- bindParameters(fromList, subqueryList, aggregateVector);
-
-
- /* If javaClassName is null then we assume that the current methodName
- * is an alias and we must go to sysmethods to
- * get the real method and java class names for this alias.
- */
- if (javaClassName == null)
- {
- CompilerContext cc = getCompilerContext();
-
- // look for a routine
- if (ad == null) {
-
- String schemaName = procedureName != null ?
- procedureName.getSchemaName() : null;
-
- SchemaDescriptor sd = getSchemaDescriptor(schemaName, schemaName != null);
-
-
- if (sd.getUUID() != null) {
-
- java.util.List list = getDataDictionary().getRoutineList(
- sd.getUUID().toString(), methodName,
- forCallStatement ? AliasInfo.ALIAS_NAME_SPACE_PROCEDURE_AS_CHAR : AliasInfo.ALIAS_NAME_SPACE_FUNCTION_AS_CHAR
- );
-
- for (int i = list.size() - 1; i >= 0; i--) {
-
- AliasDescriptor proc = (AliasDescriptor) list.get(i);
-
- RoutineAliasInfo routineInfo = (RoutineAliasInfo) proc.getAliasInfo();
- int parameterCount = routineInfo.getParameterCount();
- if (parameterCount != methodParms.length)
- continue;
-
- // pre-form the method signature. If it is a dynamic result set procedure
- // then we need to add in the ResultSet array
-
- TypeDescriptor[] parameterTypes = routineInfo.getParameterTypes();
-
- int sigParameterCount = parameterCount;
- if (routineInfo.getMaxDynamicResultSets() > 0)
- sigParameterCount++;
-
- signature = new JSQLType[sigParameterCount];
- for (int p = 0; p < parameterCount; p++) {
-
- // find the declared type.
-
- TypeDescriptor td = parameterTypes[p];
-
- TypeId typeId = TypeId.getBuiltInTypeId(td.getJDBCTypeId());
-
- TypeId parameterTypeId = typeId;
-
-
- // if it's an OUT or INOUT parameter we need an array.
- int parameterMode = routineInfo.getParameterModes()[p];
-
- if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
-
- String arrayType;
- switch (typeId.getJDBCTypeId()) {
- case java.sql.Types.SMALLINT:
- case java.sql.Types.INTEGER:
- case java.sql.Types.BIGINT:
- case java.sql.Types.REAL:
- case java.sql.Types.DOUBLE:
- arrayType = getTypeCompiler(typeId).getCorrespondingPrimitiveTypeName().concat("[]");
- break;
- default:
- arrayType = typeId.getCorrespondingJavaTypeName().concat("[]");
- break;
- }
-
- typeId = TypeId.getUserDefinedTypeId(arrayType, false);
- }
-
- // this is the type descriptor of the require method parameter
- DataTypeDescriptor methoddtd = new DataTypeDescriptor(
- typeId,
- td.getPrecision(),
- td.getScale(),
- td.isNullable(),
- td.getMaximumWidth()
- );
-
- signature[p] = new JSQLType(methoddtd);
-
- // check parameter is a ? node for INOUT and OUT parameters.
-
- ValueNode sqlParamNode = null;
-
- if (methodParms[p] instanceof SQLToJavaValueNode) {
- SQLToJavaValueNode sql2j = (SQLToJavaValueNode) methodParms[p];
- sqlParamNode = sql2j.getSQLValueNode();
- }
- else
- {
- }
-
- boolean isParameterMarker = true;
- if ((sqlParamNode == null) || !sqlParamNode.isParameterNode())
- {
- if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
-
- throw StandardException.newException(SQLState.LANG_DB2_PARAMETER_NEEDS_MARKER,
- RoutineAliasInfo.parameterMode(parameterMode),
- routineInfo.getParameterNames()[p]);
- }
- isParameterMarker = false;
- }
- else
- {
- if (applicationParameterNumbers == null)
- applicationParameterNumbers = new int[parameterCount];
- applicationParameterNumbers[p] = ((ParameterNode) sqlParamNode).getParameterNumber();
- }
-
- // this is the SQL type of the procedure parameter.
- DataTypeDescriptor paramdtd = new DataTypeDescriptor(
- parameterTypeId,
- td.getPrecision(),
- td.getScale(),
- td.isNullable(),
- td.getMaximumWidth()
- );
-
- boolean needCast = false;
- if (!isParameterMarker)
- {
-
- // can only be an IN parameter.
- // check that the value can be assigned to the
- // type of the procedure parameter.
- if (sqlParamNode instanceof UntypedNullConstantNode)
- {
- sqlParamNode.setDescriptor(paramdtd);
- }
- else
- {
-
-
- DataTypeDescriptor dts;
- TypeId argumentTypeId;
-
- if (sqlParamNode != null)
- {
- // a node from the SQL world
- argumentTypeId = sqlParamNode.getTypeId();
- dts = sqlParamNode.getTypeServices();
- }
- else
- {
- // a node from the Java world
- dts = DataTypeDescriptor.getSQLDataTypeDescriptor(methodParms[p].getJavaTypeName());
- if (dts == null)
- {
- throw StandardException.newException(SQLState.LANG_NO_CORRESPONDING_S_Q_L_TYPE,
- methodParms[p].getJavaTypeName());
- }
-
- argumentTypeId = dts.getTypeId();
- }
-
- if (! getTypeCompiler(parameterTypeId).storable(argumentTypeId, getClassFactory()))
- throw StandardException.newException(SQLState.LANG_NOT_STORABLE,
- parameterTypeId.getSQLTypeName(),
- argumentTypeId.getSQLTypeName() );
-
- // if it's not an exact length match then some cast will be needed.
- if (!paramdtd.isExactTypeAndLengthMatch(dts))
- needCast = true;
- }
- }
- else
- {
- // any variable length type will need a cast from the
- // Java world (the ? parameter) to the SQL type. This
- // ensures values like CHAR(10) are passed into the procedure
- // correctly as 10 characters long.
- if (parameterTypeId.variableLength()) {
-
- if (parameterMode != JDBC30Translation.PARAMETER_MODE_OUT)
- needCast = true;
- }
- }
-
-
- if (needCast)
- {
- // push a cast node to ensure the
- // correct type is passed to the method
- // this gets tacky because before we knew
- // it was a procedure call we ensured all the
- // parameter are JavaNodeTypes. Now we need to
- // push them back to the SQL domain, cast them
- // and then push them back to the Java domain.
-
- if (sqlParamNode == null) {
-
- sqlParamNode = (ValueNode) getNodeFactory().getNode(
- C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,
- methodParms[p],
- getContextManager());
- }
-
- ValueNode castNode = (ValueNode) getNodeFactory().getNode(
- C_NodeTypes.CAST_NODE,
- sqlParamNode,
- paramdtd,
- getContextManager());
-
-
- methodParms[p] = (JavaValueNode) getNodeFactory().getNode(
- C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,
- castNode,
- getContextManager());
-
- methodParms[p] = methodParms[p].bindExpression(fromList, subqueryList, aggregateVector);
- }
-
- // only force the type for a ? so that the correct type shows up
- // in parameter meta data
- if (isParameterMarker)
- sqlParamNode.setDescriptor(paramdtd);
- }
-
- if (sigParameterCount != parameterCount) {
-
- TypeId typeId = TypeId.getUserDefinedTypeId("java.sql.ResultSet[]", false);
-
- DataTypeDescriptor dtd = new DataTypeDescriptor(
- typeId,
- 0,
- 0,
- false,
- -1
- );
-
- signature[parameterCount] = new JSQLType(dtd);
-
- }
-
- this.routineInfo = routineInfo;
- ad = proc;
-
- // If a procedure is in the system schema and defined as executing
- // SQL do we set we are in system code.
- if (sd.isSystemSchema() && (routineInfo.getReturnType() == null) && routineInfo.getSQLAllowed() != RoutineAliasInfo.NO_SQL)
- isSystemCode = true;
-
- break;
- }
- }
-
- }
-
- /* Throw exception if no alias found */
- if (ad == null)
- {
- Object errName;
- if (procedureName == null)
- errName = methodName;
- else
- errName = procedureName;
-
- throw StandardException.newException(SQLState.LANG_NO_SUCH_METHOD_ALIAS, errName);
- }
-
-
-
- /* Query is dependent on the AliasDescriptor */
- cc.createDependency(ad);
-
-
- methodName = ad.getAliasInfo().getMethodName();
- javaClassName = ad.getJavaClassName();
- }
-
-
- javaClassName = verifyClassExist(javaClassName, true);
-
- /* Resolve the method call */
- resolveMethodCall(javaClassName, true);
-
-
- alreadyBound = true;
-
- // If this is a function call with a variable length
- // return type, then we need to push a CAST node.
- if (routineInfo != null)
- {
- TypeDescriptor returnType = routineInfo.getReturnType();
- if (returnType != null)
- {
- TypeId returnTypeId = TypeId.getBuiltInTypeId(returnType.getJDBCTypeId());
-
- if (returnTypeId.variableLength()) {
- // Cast the return using a cast node, but have to go
- // into the SQL domain, and back to the Java domain.
-
- DataTypeDescriptor returnValueDtd = new DataTypeDescriptor(
- returnTypeId,
- returnType.getPrecision(),
- returnType.getScale(),
- returnType.isNullable(),
- returnType.getMaximumWidth()
- );
-
-
- ValueNode returnValueToSQL = (ValueNode) getNodeFactory().getNode(
- C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,
- this,
- getContextManager());
-
- ValueNode returnValueCastNode = (ValueNode) getNodeFactory().getNode(
- C_NodeTypes.CAST_NODE,
- returnValueToSQL,
- returnValueDtd,
- getContextManager());
-
-
- JavaValueNode returnValueToJava = (JavaValueNode) getNodeFactory().getNode(
- C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,
- returnValueCastNode,
- getContextManager());
-
- return returnValueToJava.bindExpression(fromList, subqueryList, aggregateVector);
- }
-
- }
- }
-
- return this;
- }
-
- /**
- Push extra code to generate the casts within the
- arrays for the parameters passed as arrays.
- */
- public void generateOneParameter(ExpressionClassBuilder acb,
- MethodBuilder mb,
- int parameterNumber )
- throws StandardException
- {
- int parameterMode;
-
-
- SQLToJavaValueNode sql2j = null;
- if (methodParms[parameterNumber] instanceof SQLToJavaValueNode)
- sql2j = (SQLToJavaValueNode) methodParms[parameterNumber];
-
- if (routineInfo != null) {
- parameterMode = routineInfo.getParameterModes()[parameterNumber];
- } else {
- // for a static method call the parameter always starts out as a in parameter, but
- // may be registered as an IN OUT parameter. For a static method argument to be
- // a dynmaically registered out parameter it must be a simple ? parameter
-
- parameterMode = JDBC30Translation.PARAMETER_MODE_IN;
-
- if (sql2j != null) {
- if (sql2j.getSQLValueNode().isParameterNode()) {
-
- // applicationParameterNumbers is only set up for a procedure.
- int applicationParameterNumber = ((ParameterNode) (sql2j.getSQLValueNode())).getParameterNumber();
-
- String parameterType = methodParameterTypes[parameterNumber];
-
- if (parameterType.endsWith("[]")) {
-
- // constructor - setting up correct paramter type info
- MethodBuilder constructor = acb.getConstructor();
- acb.pushThisAsActivation(constructor);
- constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getParameterValueSet", ClassName.ParameterValueSet, 0);
-
- constructor.push(applicationParameterNumber);
- constructor.push(JDBC30Translation.PARAMETER_MODE_UNKNOWN);
- constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "setParameterMode", "void", 2);
- constructor.endStatement();
- }
- }
- }
- }
-
- switch (parameterMode) {
- case JDBC30Translation.PARAMETER_MODE_IN:
- case JDBC30Translation.PARAMETER_MODE_IN_OUT:
- case JDBC30Translation.PARAMETER_MODE_UNKNOWN:
- if (sql2j != null)
- sql2j.returnsNullOnNullState = returnsNullOnNullState;
- super.generateOneParameter(acb, mb, parameterNumber);
- break;
-
- case JDBC30Translation.PARAMETER_MODE_OUT:
- // For an OUT parameter we require nothing to be pushed into the
- // method call from the parameter node.
- break;
- }
-
- switch (parameterMode) {
- case JDBC30Translation.PARAMETER_MODE_IN:
- case JDBC30Translation.PARAMETER_MODE_UNKNOWN:
- break;
-
- case JDBC30Translation.PARAMETER_MODE_IN_OUT:
- case JDBC30Translation.PARAMETER_MODE_OUT:
- {
- // Create the array used to pass into the method. We create a
- // new array for each call as there is a small chance the
- // application could retain a reference to it and corrupt
- // future calls with the same CallableStatement object.
-
- String methodParameterType = methodParameterTypes[parameterNumber];
- String arrayType = methodParameterType.substring(0, methodParameterType.length() - 2);
- LocalField lf = acb.newFieldDeclaration(Modifier.PRIVATE, methodParameterType);
-
- if (outParamArrays == null)
- outParamArrays = new LocalField[methodParms.length];
-
- outParamArrays[parameterNumber] = lf;
-
- mb.pushNewArray(arrayType, 1);
- mb.putField(lf);
-
- // set the IN part of the parameter into the INOUT parameter.
- if (parameterMode != JDBC30Translation.PARAMETER_MODE_OUT) {
- mb.swap();
- mb.setArrayElement(0);
- mb.getField(lf);
- }
- break;
- }
- }
-
- }
-
- /**
- * Categorize this predicate. Initially, this means
- * building a bit map of the referenced tables for each predicate.
- * If the source of this ColumnReference (at the next underlying level)
- * is not a ColumnReference or a VirtualColumnNode then this predicate
- * will not be pushed down.
- *
- * For example, in:
- * select * from (select 1 from s) a (x) where x = 1
- * we will not push down x = 1.
- * NOTE: It would be easy to handle the case of a constant, but if the
- * inner SELECT returns an arbitrary expression, then we would have to copy
- * that tree into the pushed predicate, and that tree could contain
- * subqueries and method calls.
- * RESOLVE - revisit this issue once we have views.
- *
- * @param referencedTabs JBitSet with bit map of referenced FromTables
- * @param simplePredsOnly Whether or not to consider method
- * calls, field references and conditional nodes
- * when building bit map
- *
- * @return boolean Whether or not source.expression is a ColumnReference
- * or a VirtualColumnNode.
- *
- * @exception StandardException Thrown on error
- */
- public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
- throws StandardException
- {
- /* We stop here when only considering simple predicates
- * as we don't consider method calls when looking
- * for null invariant predicates.
- */
- if (simplePredsOnly)
- {
- return false;
- }
-
- boolean pushable = true;
-
- pushable = pushable && super.categorize(referencedTabs, simplePredsOnly);
-
- return pushable;
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- return "javaClassName: " +
- (javaClassName != null ? javaClassName : "null") + "\n" +
- super.toString();
- }
- else
- {
- return "";
- }
- }
-
- /**
- * Do code generation for this method call
- *
- * @param acb The ExpressionClassBuilder for the class we're generating
- * @param mb The method the expression will go into
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateExpression(ExpressionClassBuilder acb,
- MethodBuilder mb)
- throws StandardException
- {
- if (routineInfo != null) {
-
- if (!routineInfo.calledOnNullInput() && routineInfo.getParameterCount() != 0)
- returnsNullOnNullState = acb.newFieldDeclaration(Modifier.PRIVATE, "boolean");
-
- }
-
- // reset the parameters are null indicator.
- if (returnsNullOnNullState != null) {
- mb.push(false);
- mb.putField(returnsNullOnNullState);
- mb.endStatement();
-
- // for the call to the generated method below.
- mb.pushThis();
- }
-
- int nargs = generateParameters(acb, mb);
-
- LocalField functionEntrySQLAllowed = null;
-
- if (routineInfo != null) {
-
- short sqlAllowed = routineInfo.getSQLAllowed();
-
- // Before we set up our authorization level, add a check to see if this
- // method can be called. If the routine is NO SQL or CONTAINS SQL
- // then there is no need for a check. As follows:
- //
- // Current Level = NO_SQL - CALL will be rejected when getting CALL result set
- // Current Level = anything else - calls to procedures defined as NO_SQL and CONTAINS SQL both allowed.
-
-
- if (sqlAllowed != RoutineAliasInfo.NO_SQL)
- {
-
- int sqlOperation;
-
- if (sqlAllowed == RoutineAliasInfo.READS_SQL_DATA)
- sqlOperation = Authorizer.SQL_SELECT_OP;
- else if (sqlAllowed == RoutineAliasInfo.MODIFIES_SQL_DATA)
- sqlOperation = Authorizer.SQL_WRITE_OP;
- else
- sqlOperation = Authorizer.SQL_ARBITARY_OP;
-
- generateAuthorizeCheck((ActivationClassBuilder) acb, mb, sqlOperation);
- }
-
- int statmentContextReferences = isSystemCode ? 2 : 1;
-
- boolean isFunction = routineInfo.getReturnType() != null;
-
- if (isFunction)
- statmentContextReferences++;
-
-
- if (statmentContextReferences != 0) {
- acb.pushThisAsActivation(mb);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getStatementContext", "org.apache.derby.iapi.sql.conn.StatementContext", 0);
-
- for (int scc = 1; scc < statmentContextReferences; scc++)
- mb.dup();
- }
-
- /**
- Set the statement context to reflect we are running
- System procedures, so that we can execute non-standard SQL.
- */
- if (isSystemCode) {
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "setSystemCode", "void", 0);
- }
-
- // for a function we need to fetch the current SQL control
- // so that we can reset it once the function is complete.
- //
- if (isFunction)
- {
- functionEntrySQLAllowed = acb.newFieldDeclaration(Modifier.PRIVATE, "short");
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getSQLAllowed", "short", 0);
- mb.putField(functionEntrySQLAllowed);
- mb.endStatement();
-
- }
-
-
- // Set up the statement context to reflect the
- // restricted SQL execution allowed by this routine.
-
- mb.push(sqlAllowed);
- mb.push(false);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "setSQLAllowed", "void", 2);
-
- }
-
- // add in the ResultSet arrays.
- if (routineInfo != null) {
-
- int compiledResultSets = methodParameterTypes.length - methodParms.length;
-
- if (compiledResultSets != 0) {
-
- // Add a method that indicates the maxium number of dynamic result sets.
- int maxDynamicResults = routineInfo.getMaxDynamicResultSets();
- if (maxDynamicResults > 0) {
- MethodBuilder gdr = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, "int", "getMaxDynamicResults");
- gdr.push(maxDynamicResults);
- gdr.methodReturn();
- gdr.complete();
- }
-
- // add a method to return all the dynamic result sets (unordered)
- MethodBuilder gdr = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, "java.sql.ResultSet[][]", "getDynamicResults");
-
- MethodBuilder cons = acb.getConstructor();
- // if (procDef.getParameterStyle() == RoutineAliasInfo.PS_JAVA)
- {
- // PARAMETER STYLE JAVA
-
- LocalField procedureResultSetsHolder = acb.newFieldDeclaration(Modifier.PRIVATE, "java.sql.ResultSet[][]");
-
- // getDynamicResults body
- gdr.getField(procedureResultSetsHolder);
-
- // create the holder of all the ResultSet arrays, new java.sql.ResultSet[][compiledResultSets]
- cons.pushNewArray("java.sql.ResultSet[]", compiledResultSets);
- cons.putField(procedureResultSetsHolder);
- cons.endStatement();
-
-
- // arguments for the dynamic result sets
- for (int i = 0; i < compiledResultSets; i++) {
-
- mb.pushNewArray("java.sql.ResultSet", 1);
- mb.dup();
-
- mb.getField(procedureResultSetsHolder);
- mb.swap();
-
- mb.setArrayElement(i);
- }
- }
-
- // complete the method that returns the ResultSet[][] to the
- gdr.methodReturn();
- gdr.complete();
-
- nargs += compiledResultSets;
- }
-
- }
-
- String javaReturnType = getJavaTypeName();
-
- MethodBuilder mbnc = null;
- MethodBuilder mbcm = mb;
-
-
- // If any of the parameters are null then
- // do not call the method, just return null.
- if (returnsNullOnNullState != null)
- {
- mbnc = acb.newGeneratedFun(javaReturnType, Modifier.PRIVATE, methodParameterTypes);
-
- // add the throws clause for the public static method we are going to call.
- Class[] throwsSet = ((java.lang.reflect.Method) method).getExceptionTypes();
- for (int te = 0; te < throwsSet.length; te++)
- {
- mbnc.addThrownException(throwsSet[te].getName());
- }
-
- mbnc.getField(returnsNullOnNullState);
- mbnc.conditionalIf();
-
- // set up for a null!!
- // for objects is easy.
- mbnc.pushNull(javaReturnType);
-
- mbnc.startElseCode();
-
- if (!actualMethodReturnType.equals(javaReturnType))
- mbnc.pushNewStart(javaReturnType);
-
- // fetch all the arguments
- for (int pa = 0; pa < nargs; pa++)
- {
- mbnc.getParameter(pa);
- }
-
- mbcm = mbnc;
- }
-
- mbcm.callMethod(VMOpcode.INVOKESTATIC, method.getDeclaringClass().getName(), methodName,
- actualMethodReturnType, nargs);
-
-
- if (returnsNullOnNullState != null)
- {
- if (!actualMethodReturnType.equals(javaReturnType))
- mbnc.pushNewComplete(1);
-
- mbnc.completeConditional();
-
- mbnc.methodReturn();
- mbnc.complete();
-
- // now call the wrapper method
- mb.callMethod(VMOpcode.INVOKEVIRTUAL, acb.getClassBuilder().getFullName(), mbnc.getName(),
- javaReturnType, nargs);
- mbnc = null;
- }
-
-
- if (routineInfo != null) {
-
- // reset the SQL allowed setting that we set upon
- // entry to the method.
- if (functionEntrySQLAllowed != null) {
- acb.pushThisAsActivation(mb);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getStatementContext", "org.apache.derby.iapi.sql.conn.StatementContext", 0);
- mb.getField(functionEntrySQLAllowed);
- mb.push(true); // override as we are ending the control set by this function all.
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "setSQLAllowed", "void", 2);
-
- }
-
- if (outParamArrays != null) {
-
- MethodBuilder constructor = acb.getConstructor();
-
- // constructor - setting up correct paramter type info
- acb.pushThisAsActivation(constructor);
- constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getParameterValueSet", ClassName.ParameterValueSet, 0);
-
- // execute - passing out parameters back.
- acb.pushThisAsActivation(mb);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getParameterValueSet", ClassName.ParameterValueSet, 0);
-
- int[] parameterModes = routineInfo.getParameterModes();
- for (int i = 0; i < outParamArrays.length; i++) {
-
- int parameterMode = parameterModes[i];
- if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
-
- // must be a parameter if it is INOUT or OUT.
- ValueNode sqlParamNode = ((SQLToJavaValueNode) methodParms[i]).getSQLValueNode();
-
-
- int applicationParameterNumber = applicationParameterNumbers[i];
-
- // Set the correct parameter nodes in the ParameterValueSet at constructor time.
- constructor.dup();
- constructor.push(applicationParameterNumber);
- constructor.push(parameterMode);
- constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "setParameterMode", "void", 2);
-
- // Pass the value of the outparameters back to the calling code
- LocalField lf = outParamArrays[i];
-
- mb.dup();
- mb.push(applicationParameterNumber);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
- "getParameter", ClassName.DataValueDescriptor, 1);
-
- // see if we need to set the desired length/scale/precision of the type
- DataTypeDescriptor paramdtd = sqlParamNode.getTypeServices();
-
- boolean isNumericType = paramdtd.getTypeId().isNumericTypeId();
-
- if (isNumericType) {
- if (!paramdtd.getTypeId().isDecimalTypeId()) {
-
- if (!((java.lang.reflect.Method) method).getParameterTypes()[i].getComponentType().isPrimitive())
- mb.cast(ClassName.NumberDataValue);
- }
- }
- else if (paramdtd.getTypeId().isBooleanTypeId())
- {
- if (!((java.lang.reflect.Method) method).getParameterTypes()[i].getComponentType().isPrimitive())
- mb.cast(ClassName.BooleanDataValue);
- }
-
-
-
- if (paramdtd.getTypeId().variableLength()) {
- // need another DVD reference for the set width below.
- mb.dup();
- }
-
-
- mb.getField(lf); // pvs, dvd, array
- mb.getArrayElement(0); // pvs, dvd, value
- mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "setValue", "void", 1);
-
- if (paramdtd.getTypeId().variableLength()) {
- mb.push(isNumericType ? paramdtd.getPrecision() : paramdtd.getMaximumWidth());
- mb.push(paramdtd.getScale());
- mb.push(isNumericType);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", ClassName.DataValueDescriptor, 3);
- mb.endStatement();
- }
- }
- }
- constructor.endStatement();
- mb.endStatement();
- }
-
- }
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+import org.apache.derby.iapi.sql.compile.TypeCompiler;
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+import org.apache.derby.iapi.types.JSQLType;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.types.TypeId;
+
+import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+
+import org.apache.derby.iapi.reference.ClassName;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.reference.JDBC30Translation;
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+import org.apache.derby.iapi.services.loader.ClassInspector;
+import org.apache.derby.iapi.services.compiler.LocalField;
+
+import org.apache.derby.iapi.util.JBitSet;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import org.apache.derby.iapi.sql.conn.Authorizer;
+
+import org.apache.derby.catalog.AliasInfo;
+import org.apache.derby.catalog.TypeDescriptor;
+import org.apache.derby.catalog.types.RoutineAliasInfo;
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
+
+import org.apache.derby.catalog.UUID;
+
+import java.util.Vector;
+import java.lang.reflect.Modifier;
+
+/**
+ * A StaticMethodCallNode represents a static method call from a Class
+ * (as opposed to from an Object).
+
+ For a procedure the call requires that the arguments be ? parameters.
+ The parameter is *logically* passed into the method call a number of different ways.
+
+ <P>
+ For a application call like CALL MYPROC(?) the logically Java method call is
+ (in psuedo Java/SQL code) (examples with CHAR(10) parameter)
+ <BR>
+ Fixed length IN parameters - com.acme.MyProcedureMethod(?)
+ <BR>
+ Variable length IN parameters - com.acme.MyProcedureMethod(CAST (? AS CHAR(10))
+ <BR>
+ Fixed length INOUT parameter -
+ String[] holder = new String[] {?}; com.acme.MyProcedureMethod(holder); ? = holder[0]
+ <BR>
+ Variable length INOUT parameter -
+ String[] holder = new String[] {CAST (? AS CHAR(10)}; com.acme.MyProcedureMethod(holder); ? = CAST (holder[0] AS CHAR(10))
+
+ <BR>
+ Fixed length OUT parameter -
+ String[] holder = new String[1]; com.acme.MyProcedureMethod(holder); ? = holder[0]
+
+ <BR>
+ Variable length INOUT parameter -
+ String[] holder = new String[1]; com.acme.MyProcedureMethod(holder); ? = CAST (holder[0] AS CHAR(10))
+
+
+ <P>
+ For static method calls there is no pre-definition of an IN or INOUT parameter, so a call to CallableStatement.registerOutParameter()
+ makes the parameter an INOUT parameter, provided:
+ - the parameter is passed directly to the method call (no casts or expressions).
+ - the method's parameter type is a Java array type.
+
+ Since this is a dynmaic decision we compile in code to take both paths, based upon a boolean isINOUT which is dervied from the
+ ParameterValueSet. Code is logically (only single parameter String[] shown here). Note, no casts can exist here.
+
+ boolean isINOUT = getParameterValueSet().getParameterMode(0) == PARAMETER_IN_OUT;
+ if (isINOUT) {
+ String[] holder = new String[] {?}; com.acme.MyProcedureMethod(holder); ? = holder[0]
+
+ } else {
+ com.acme.MyProcedureMethod(?)
+ }
+
+ *
+ * @author Jerry Brenner
+ */
+public class StaticMethodCallNode extends MethodCallNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ private TableName procedureName;
+
+ private LocalField[] outParamArrays;
+ private int[] applicationParameterNumbers;
+
+ private boolean isSystemCode;
+ private boolean alreadyBound;
+
+ private LocalField returnsNullOnNullState;
+
+
+ AliasDescriptor ad;
+
+
+ /**
+ * Intializer for a NonStaticMethodCallNode
+ *
+ * @param methodName The name of the method to call
+ * @param javaClassName The name of the java class that the static method belongs to.
+ */
+ public void init(Object methodName, Object javaClassName)
+ {
+ if (methodName instanceof String)
+ init(methodName);
+ else {
+ procedureName = (TableName) methodName;
+ init(procedureName.getTableName());
+ }
+
+ this.javaClassName = (String) javaClassName;
+ }
+
+ /**
+ * Bind this expression. This means binding the sub-expressions,
+ * as well as figuring out what the return type is for this expression.
+ *
+ * @param fromList The FROM list for the query this
+ * expression is in, for binding columns.
+ * @param subqueryList The subquery list being built as we find SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return this or an AggregateNode
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public JavaValueNode bindExpression(
+ FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ // for a function we can get called recursively
+ if (alreadyBound)
+ return this;
+
+
+ bindParameters(fromList, subqueryList, aggregateVector);
+
+
+ /* If javaClassName is null then we assume that the current methodName
+ * is an alias and we must go to sysmethods to
+ * get the real method and java class names for this alias.
+ */
+ if (javaClassName == null)
+ {
+ CompilerContext cc = getCompilerContext();
+
+ // look for a routine
+ if (ad == null) {
+
+ String schemaName = procedureName != null ?
+ procedureName.getSchemaName() : null;
+
+ SchemaDescriptor sd = getSchemaDescriptor(schemaName, schemaName != null);
+
+
+ if (sd.getUUID() != null) {
+
+ java.util.List list = getDataDictionary().getRoutineList(
+ sd.getUUID().toString(), methodName,
+ forCallStatement ? AliasInfo.ALIAS_NAME_SPACE_PROCEDURE_AS_CHAR : AliasInfo.ALIAS_NAME_SPACE_FUNCTION_AS_CHAR
+ );
+
+ for (int i = list.size() - 1; i >= 0; i--) {
+
+ AliasDescriptor proc = (AliasDescriptor) list.get(i);
+
+ RoutineAliasInfo routineInfo = (RoutineAliasInfo) proc.getAliasInfo();
+ int parameterCount = routineInfo.getParameterCount();
+ if (parameterCount != methodParms.length)
+ continue;
+
+ // pre-form the method signature. If it is a dynamic result set procedure
+ // then we need to add in the ResultSet array
+
+ TypeDescriptor[] parameterTypes = routineInfo.getParameterTypes();
+
+ int sigParameterCount = parameterCount;
+ if (routineInfo.getMaxDynamicResultSets() > 0)
+ sigParameterCount++;
+
+ signature = new JSQLType[sigParameterCount];
+ for (int p = 0; p < parameterCount; p++) {
+
+ // find the declared type.
+
+ TypeDescriptor td = parameterTypes[p];
+
+ TypeId typeId = TypeId.getBuiltInTypeId(td.getJDBCTypeId());
+
+ TypeId parameterTypeId = typeId;
+
+
+ // if it's an OUT or INOUT parameter we need an array.
+ int parameterMode = routineInfo.getParameterModes()[p];
+
+ if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
+
+ String arrayType;
+ switch (typeId.getJDBCTypeId()) {
+ case java.sql.Types.SMALLINT:
+ case java.sql.Types.INTEGER:
+ case java.sql.Types.BIGINT:
+ case java.sql.Types.REAL:
+ case java.sql.Types.DOUBLE:
+ arrayType = getTypeCompiler(typeId).getCorrespondingPrimitiveTypeName().concat("[]");
+ break;
+ default:
+ arrayType = typeId.getCorrespondingJavaTypeName().concat("[]");
+ break;
+ }
+
+ typeId = TypeId.getUserDefinedTypeId(arrayType, false);
+ }
+
+ // this is the type descriptor of the require method parameter
+ DataTypeDescriptor methoddtd = new DataTypeDescriptor(
+ typeId,
+ td.getPrecision(),
+ td.getScale(),
+ td.isNullable(),
+ td.getMaximumWidth()
+ );
+
+ signature[p] = new JSQLType(methoddtd);
+
+ // check parameter is a ? node for INOUT and OUT parameters.
+
+ ValueNode sqlParamNode = null;
+
+ if (methodParms[p] instanceof SQLToJavaValueNode) {
+ SQLToJavaValueNode sql2j = (SQLToJavaValueNode) methodParms[p];
+ sqlParamNode = sql2j.getSQLValueNode();
+ }
+ else
+ {
+ }
+
+ boolean isParameterMarker = true;
+ if ((sqlParamNode == null) || !sqlParamNode.isParameterNode())
+ {
+ if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
+
+ throw StandardException.newException(SQLState.LANG_DB2_PARAMETER_NEEDS_MARKER,
+ RoutineAliasInfo.parameterMode(parameterMode),
+ routineInfo.getParameterNames()[p]);
+ }
+ isParameterMarker = false;
+ }
+ else
+ {
+ if (applicationParameterNumbers == null)
+ applicationParameterNumbers = new int[parameterCount];
+ applicationParameterNumbers[p] = ((ParameterNode) sqlParamNode).getParameterNumber();
+ }
+
+ // this is the SQL type of the procedure parameter.
+ DataTypeDescriptor paramdtd = new DataTypeDescriptor(
+ parameterTypeId,
+ td.getPrecision(),
+ td.getScale(),
+ td.isNullable(),
+ td.getMaximumWidth()
+ );
+
+ boolean needCast = false;
+ if (!isParameterMarker)
+ {
+
+ // can only be an IN parameter.
+ // check that the value can be assigned to the
+ // type of the procedure parameter.
+ if (sqlParamNode instanceof UntypedNullConstantNode)
+ {
+ sqlParamNode.setDescriptor(paramdtd);
+ }
+ else
+ {
+
+
+ DataTypeDescriptor dts;
+ TypeId argumentTypeId;
+
+ if (sqlParamNode != null)
+ {
+ // a node from the SQL world
+ argumentTypeId = sqlParamNode.getTypeId();
+ dts = sqlParamNode.getTypeServices();
+ }
+ else
+ {
+ // a node from the Java world
+ dts = DataTypeDescriptor.getSQLDataTypeDescriptor(methodParms[p].getJavaTypeName());
+ if (dts == null)
+ {
+ throw StandardException.newException(SQLState.LANG_NO_CORRESPONDING_S_Q_L_TYPE,
+ methodParms[p].getJavaTypeName());
+ }
+
+ argumentTypeId = dts.getTypeId();
+ }
+
+ if (! getTypeCompiler(parameterTypeId).storable(argumentTypeId, getClassFactory()))
+ throw StandardException.newException(SQLState.LANG_NOT_STORABLE,
+ parameterTypeId.getSQLTypeName(),
+ argumentTypeId.getSQLTypeName() );
+
+ // if it's not an exact length match then some cast will be needed.
+ if (!paramdtd.isExactTypeAndLengthMatch(dts))
+ needCast = true;
+ }
+ }
+ else
+ {
+ // any variable length type will need a cast from the
+ // Java world (the ? parameter) to the SQL type. This
+ // ensures values like CHAR(10) are passed into the procedure
+ // correctly as 10 characters long.
+ if (parameterTypeId.variableLength()) {
+
+ if (parameterMode != JDBC30Translation.PARAMETER_MODE_OUT)
+ needCast = true;
+ }
+ }
+
+
+ if (needCast)
+ {
+ // push a cast node to ensure the
+ // correct type is passed to the method
+ // this gets tacky because before we knew
+ // it was a procedure call we ensured all the
+ // parameter are JavaNodeTypes. Now we need to
+ // push them back to the SQL domain, cast them
+ // and then push them back to the Java domain.
+
+ if (sqlParamNode == null) {
+
+ sqlParamNode = (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,
+ methodParms[p],
+ getContextManager());
+ }
+
+ ValueNode castNode = (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.CAST_NODE,
+ sqlParamNode,
+ paramdtd,
+ getContextManager());
+
+
+ methodParms[p] = (JavaValueNode) getNodeFactory().getNode(
+ C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,
+ castNode,
+ getContextManager());
+
+ methodParms[p] = methodParms[p].bindExpression(fromList, subqueryList, aggregateVector);
+ }
+
+ // only force the type for a ? so that the correct type shows up
+ // in parameter meta data
+ if (isParameterMarker)
+ sqlParamNode.setDescriptor(paramdtd);
+ }
+
+ if (sigParameterCount != parameterCount) {
+
+ TypeId typeId = TypeId.getUserDefinedTypeId("java.sql.ResultSet[]", false);
+
+ DataTypeDescriptor dtd = new DataTypeDescriptor(
+ typeId,
+ 0,
+ 0,
+ false,
+ -1
+ );
+
+ signature[parameterCount] = new JSQLType(dtd);
+
+ }
+
+ this.routineInfo = routineInfo;
+ ad = proc;
+
+ // If a procedure is in the system schema and defined as executing
+ // SQL do we set we are in system code.
+ if (sd.isSystemSchema() && (routineInfo.getReturnType() == null) && routineInfo.getSQLAllowed() != RoutineAliasInfo.NO_SQL)
+ isSystemCode = true;
+
+ break;
+ }
+ }
+
+ }
+
+ /* Throw exception if no alias found */
+ if (ad == null)
+ {
+ Object errName;
+ if (procedureName == null)
+ errName = methodName;
+ else
+ errName = procedureName;
+
+ throw StandardException.newException(SQLState.LANG_NO_SUCH_METHOD_ALIAS, errName);
+ }
+
+
+
+ /* Query is dependent on the AliasDescriptor */
+ cc.createDependency(ad);
+
+
+ methodName = ad.getAliasInfo().getMethodName();
+ javaClassName = ad.getJavaClassName();
+ }
+
+
+ javaClassName = verifyClassExist(javaClassName, true);
+
+ /* Resolve the method call */
+ resolveMethodCall(javaClassName, true);
+
+
+ alreadyBound = true;
+
+ // If this is a function call with a variable length
+ // return type, then we need to push a CAST node.
+ if (routineInfo != null)
+ {
+ TypeDescriptor returnType = routineInfo.getReturnType();
+ if (returnType != null)
+ {
+ TypeId returnTypeId = TypeId.getBuiltInTypeId(returnType.getJDBCTypeId());
+
+ if (returnTypeId.variableLength()) {
+ // Cast the return using a cast node, but have to go
+ // into the SQL domain, and back to the Java domain.
+
+ DataTypeDescriptor returnValueDtd = new DataTypeDescriptor(
+ returnTypeId,
+ returnType.getPrecision(),
+ returnType.getScale(),
+ returnType.isNullable(),
+ returnType.getMaximumWidth()
+ );
+
+
+ ValueNode returnValueToSQL = (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,
+ this,
+ getContextManager());
+
+ ValueNode returnValueCastNode = (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.CAST_NODE,
+ returnValueToSQL,
+ returnValueDtd,
+ getContextManager());
+
+
+ JavaValueNode returnValueToJava = (JavaValueNode) getNodeFactory().getNode(
+ C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,
+ returnValueCastNode,
+ getContextManager());
+
+ return returnValueToJava.bindExpression(fromList, subqueryList, aggregateVector);
+ }
+
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ Push extra code to generate the casts within the
+ arrays for the parameters passed as arrays.
+ */
+ public void generateOneParameter(ExpressionClassBuilder acb,
+ MethodBuilder mb,
+ int parameterNumber )
+ throws StandardException
+ {
+ int parameterMode;
+
+
+ SQLToJavaValueNode sql2j = null;
+ if (methodParms[parameterNumber] instanceof SQLToJavaValueNode)
+ sql2j = (SQLToJavaValueNode) methodParms[parameterNumber];
+
+ if (routineInfo != null) {
+ parameterMode = routineInfo.getParameterModes()[parameterNumber];
+ } else {
+ // for a static method call the parameter always starts out as a in parameter, but
+ // may be registered as an IN OUT parameter. For a static method argument to be
+ // a dynmaically registered out parameter it must be a simple ? parameter
+
+ parameterMode = JDBC30Translation.PARAMETER_MODE_IN;
+
+ if (sql2j != null) {
+ if (sql2j.getSQLValueNode().isParameterNode()) {
+
+ // applicationParameterNumbers is only set up for a procedure.
+ int applicationParameterNumber = ((ParameterNode) (sql2j.getSQLValueNode())).getParameterNumber();
+
+ String parameterType = methodParameterTypes[parameterNumber];
+
+ if (parameterType.endsWith("[]")) {
+
+ // constructor - setting up correct paramter type info
+ MethodBuilder constructor = acb.getConstructor();
+ acb.pushThisAsActivation(constructor);
+ constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getParameterValueSet", ClassName.ParameterValueSet, 0);
+
+ constructor.push(applicationParameterNumber);
+ constructor.push(JDBC30Translation.PARAMETER_MODE_UNKNOWN);
+ constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "setParameterMode", "void", 2);
+ constructor.endStatement();
+ }
+ }
+ }
+ }
+
+ switch (parameterMode) {
+ case JDBC30Translation.PARAMETER_MODE_IN:
+ case JDBC30Translation.PARAMETER_MODE_IN_OUT:
+ case JDBC30Translation.PARAMETER_MODE_UNKNOWN:
+ if (sql2j != null)
+ sql2j.returnsNullOnNullState = returnsNullOnNullState;
+ super.generateOneParameter(acb, mb, parameterNumber);
+ break;
+
+ case JDBC30Translation.PARAMETER_MODE_OUT:
+ // For an OUT parameter we require nothing to be pushed into the
+ // method call from the parameter node.
+ break;
+ }
+
+ switch (parameterMode) {
+ case JDBC30Translation.PARAMETER_MODE_IN:
+ case JDBC30Translation.PARAMETER_MODE_UNKNOWN:
+ break;
+
+ case JDBC30Translation.PARAMETER_MODE_IN_OUT:
+ case JDBC30Translation.PARAMETER_MODE_OUT:
+ {
+ // Create the array used to pass into the method. We create a
+ // new array for each call as there is a small chance the
+ // application could retain a reference to it and corrupt
+ // future calls with the same CallableStatement object.
+
+ String methodParameterType = methodParameterTypes[parameterNumber];
+ String arrayType = methodParameterType.substring(0, methodParameterType.length() - 2);
+ LocalField lf = acb.newFieldDeclaration(Modifier.PRIVATE, methodParameterType);
+
+ if (outParamArrays == null)
+ outParamArrays = new LocalField[methodParms.length];
+
+ outParamArrays[parameterNumber] = lf;
+
+ mb.pushNewArray(arrayType, 1);
+ mb.putField(lf);
+
+ // set the IN part of the parameter into the INOUT parameter.
+ if (parameterMode != JDBC30Translation.PARAMETER_MODE_OUT) {
+ mb.swap();
+ mb.setArrayElement(0);
+ mb.getField(lf);
+ }
+ break;
+ }
+ }
+
+ }
+
+ /**
+ * Categorize this predicate. Initially, this means
+ * building a bit map of the referenced tables for each predicate.
+ * If the source of this ColumnReference (at the next underlying level)
+ * is not a ColumnReference or a VirtualColumnNode then this predicate
+ * will not be pushed down.
+ *
+ * For example, in:
+ * select * from (select 1 from s) a (x) where x = 1
+ * we will not push down x = 1.
+ * NOTE: It would be easy to handle the case of a constant, but if the
+ * inner SELECT returns an arbitrary expression, then we would have to copy
+ * that tree into the pushed predicate, and that tree could contain
+ * subqueries and method calls.
+ * RESOLVE - revisit this issue once we have views.
+ *
+ * @param referencedTabs JBitSet with bit map of referenced FromTables
+ * @param simplePredsOnly Whether or not to consider method
+ * calls, field references and conditional nodes
+ * when building bit map
+ *
+ * @return boolean Whether or not source.expression is a ColumnReference
+ * or a VirtualColumnNode.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
+ throws StandardException
+ {
+ /* We stop here when only considering simple predicates
+ * as we don't consider method calls when looking
+ * for null invariant predicates.
+ */
+ if (simplePredsOnly)
+ {
+ return false;
+ }
+
+ boolean pushable = true;
+
+ pushable = pushable && super.categorize(referencedTabs, simplePredsOnly);
+
+ return pushable;
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ return "javaClassName: " +
+ (javaClassName != null ? javaClassName : "null") + "\n" +
+ super.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Do code generation for this method call
+ *
+ * @param acb The ExpressionClassBuilder for the class we're generating
+ * @param mb The method the expression will go into
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateExpression(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ throws StandardException
+ {
+ if (routineInfo != null) {
+
+ if (!routineInfo.calledOnNullInput() && routineInfo.getParameterCount() != 0)
+ returnsNullOnNullState = acb.newFieldDeclaration(Modifier.PRIVATE, "boolean");
+
+ }
+
+ // reset the parameters are null indicator.
+ if (returnsNullOnNullState != null) {
+ mb.push(false);
+ mb.putField(returnsNullOnNullState);
+ mb.endStatement();
+
+ // for the call to the generated method below.
+ mb.pushThis();
+ }
+
+ int nargs = generateParameters(acb, mb);
+
+ LocalField functionEntrySQLAllowed = null;
+
+ if (routineInfo != null) {
+
+ short sqlAllowed = routineInfo.getSQLAllowed();
+
+ // Before we set up our authorization level, add a check to see if this
+ // method can be called. If the routine is NO SQL or CONTAINS SQL
+ // then there is no need for a check. As follows:
+ //
+ // Current Level = NO_SQL - CALL will be rejected when getting CALL result set
+ // Current Level = anything else - calls to procedures defined as NO_SQL and CONTAINS SQL both allowed.
+
+
+ if (sqlAllowed != RoutineAliasInfo.NO_SQL)
+ {
+
+ int sqlOperation;
+
+ if (sqlAllowed == RoutineAliasInfo.READS_SQL_DATA)
+ sqlOperation = Authorizer.SQL_SELECT_OP;
+ else if (sqlAllowed == RoutineAliasInfo.MODIFIES_SQL_DATA)
+ sqlOperation = Authorizer.SQL_WRITE_OP;
+ else
+ sqlOperation = Authorizer.SQL_ARBITARY_OP;
+
+ generateAuthorizeCheck((ActivationClassBuilder) acb, mb, sqlOperation);
+ }
+
+ int statmentContextReferences = isSystemCode ? 2 : 1;
+
+ boolean isFunction = routineInfo.getReturnType() != null;
+
+ if (isFunction)
+ statmentContextReferences++;
+
+
+ if (statmentContextReferences != 0) {
+ acb.pushThisAsActivation(mb);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getStatementContext", "org.apache.derby.iapi.sql.conn.StatementContext", 0);
+
+ for (int scc = 1; scc < statmentContextReferences; scc++)
+ mb.dup();
+ }
+
+ /**
+ Set the statement context to reflect we are running
+ System procedures, so that we can execute non-standard SQL.
+ */
+ if (isSystemCode) {
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "setSystemCode", "void", 0);
+ }
+
+ // for a function we need to fetch the current SQL control
+ // so that we can reset it once the function is complete.
+ //
+ if (isFunction)
+ {
+ functionEntrySQLAllowed = acb.newFieldDeclaration(Modifier.PRIVATE, "short");
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getSQLAllowed", "short", 0);
+ mb.putField(functionEntrySQLAllowed);
+ mb.endStatement();
+
+ }
+
+
+ // Set up the statement context to reflect the
+ // restricted SQL execution allowed by this routine.
+
+ mb.push(sqlAllowed);
+ mb.push(false);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "setSQLAllowed", "void", 2);
+
+ }
+
+ // add in the ResultSet arrays.
+ if (routineInfo != null) {
+
+ int compiledResultSets = methodParameterTypes.length - methodParms.length;
+
+ if (compiledResultSets != 0) {
+
+ // Add a method that indicates the maxium number of dynamic result sets.
+ int maxDynamicResults = routineInfo.getMaxDynamicResultSets();
+ if (maxDynamicResults > 0) {
+ MethodBuilder gdr = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, "int", "getMaxDynamicResults");
+ gdr.push(maxDynamicResults);
+ gdr.methodReturn();
+ gdr.complete();
+ }
+
+ // add a method to return all the dynamic result sets (unordered)
+ MethodBuilder gdr = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, "java.sql.ResultSet[][]", "getDynamicResults");
+
+ MethodBuilder cons = acb.getConstructor();
+ // if (procDef.getParameterStyle() == RoutineAliasInfo.PS_JAVA)
+ {
+ // PARAMETER STYLE JAVA
+
+ LocalField procedureResultSetsHolder = acb.newFieldDeclaration(Modifier.PRIVATE, "java.sql.ResultSet[][]");
+
+ // getDynamicResults body
+ gdr.getField(procedureResultSetsHolder);
+
+ // create the holder of all the ResultSet arrays, new java.sql.ResultSet[][compiledResultSets]
+ cons.pushNewArray("java.sql.ResultSet[]", compiledResultSets);
+ cons.putField(procedureResultSetsHolder);
+ cons.endStatement();
+
+
+ // arguments for the dynamic result sets
+ for (int i = 0; i < compiledResultSets; i++) {
+
+ mb.pushNewArray("java.sql.ResultSet", 1);
+ mb.dup();
+
+ mb.getField(procedureResultSetsHolder);
+ mb.swap();
+
+ mb.setArrayElement(i);
+ }
+ }
+
+ // complete the method that returns the ResultSet[][] to the
+ gdr.methodReturn();
+ gdr.complete();
+
+ nargs += compiledResultSets;
+ }
+
+ }
+
+ String javaReturnType = getJavaTypeName();
+
+ MethodBuilder mbnc = null;
+ MethodBuilder mbcm = mb;
+
+
+ // If any of the parameters are null then
+ // do not call the method, just return null.
+ if (returnsNullOnNullState != null)
+ {
+ mbnc = acb.newGeneratedFun(javaReturnType, Modifier.PRIVATE, methodParameterTypes);
+
+ // add the throws clause for the public static method we are going to call.
+ Class[] throwsSet = ((java.lang.reflect.Method) method).getExceptionTypes();
+ for (int te = 0; te < throwsSet.length; te++)
+ {
+ mbnc.addThrownException(throwsSet[te].getName());
+ }
+
+ mbnc.getField(returnsNullOnNullState);
+ mbnc.conditionalIf();
+
+ // set up for a null!!
+ // for objects is easy.
+ mbnc.pushNull(javaReturnType);
+
+ mbnc.startElseCode();
+
+ if (!actualMethodReturnType.equals(javaReturnType))
+ mbnc.pushNewStart(javaReturnType);
+
+ // fetch all the arguments
+ for (int pa = 0; pa < nargs; pa++)
+ {
+ mbnc.getParameter(pa);
+ }
+
+ mbcm = mbnc;
+ }
+
+ mbcm.callMethod(VMOpcode.INVOKESTATIC, method.getDeclaringClass().getName(), methodName,
+ actualMethodReturnType, nargs);
+
+
+ if (returnsNullOnNullState != null)
+ {
+ if (!actualMethodReturnType.equals(javaReturnType))
+ mbnc.pushNewComplete(1);
+
+ mbnc.completeConditional();
+
+ mbnc.methodReturn();
+ mbnc.complete();
+
+ // now call the wrapper method
+ mb.callMethod(VMOpcode.INVOKEVIRTUAL, acb.getClassBuilder().getFullName(), mbnc.getName(),
+ javaReturnType, nargs);
+ mbnc = null;
+ }
+
+
+ if (routineInfo != null) {
+
+ // reset the SQL allowed setting that we set upon
+ // entry to the method.
+ if (functionEntrySQLAllowed != null) {
+ acb.pushThisAsActivation(mb);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getStatementContext", "org.apache.derby.iapi.sql.conn.StatementContext", 0);
+ mb.getField(functionEntrySQLAllowed);
+ mb.push(true); // override as we are ending the control set by this function all.
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "setSQLAllowed", "void", 2);
+
+ }
+
+ if (outParamArrays != null) {
+
+ MethodBuilder constructor = acb.getConstructor();
+
+ // constructor - setting up correct paramter type info
+ acb.pushThisAsActivation(constructor);
+ constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getParameterValueSet", ClassName.ParameterValueSet, 0);
+
+ // execute - passing out parameters back.
+ acb.pushThisAsActivation(mb);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getParameterValueSet", ClassName.ParameterValueSet, 0);
+
+ int[] parameterModes = routineInfo.getParameterModes();
+ for (int i = 0; i < outParamArrays.length; i++) {
+
+ int parameterMode = parameterModes[i];
+ if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) {
+
+ // must be a parameter if it is INOUT or OUT.
+ ValueNode sqlParamNode = ((SQLToJavaValueNode) methodParms[i]).getSQLValueNode();
+
+
+ int applicationParameterNumber = applicationParameterNumbers[i];
+
+ // Set the correct parameter nodes in the ParameterValueSet at constructor time.
+ constructor.dup();
+ constructor.push(applicationParameterNumber);
+ constructor.push(parameterMode);
+ constructor.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "setParameterMode", "void", 2);
+
+ // Pass the value of the outparameters back to the calling code
+ LocalField lf = outParamArrays[i];
+
+ mb.dup();
+ mb.push(applicationParameterNumber);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+ "getParameter", ClassName.DataValueDescriptor, 1);
+
+ // see if we need to set the desired length/scale/precision of the type
+ DataTypeDescriptor paramdtd = sqlParamNode.getTypeServices();
+
+ boolean isNumericType = paramdtd.getTypeId().isNumericTypeId();
+
+ if (isNumericType) {
+ if (!paramdtd.getTypeId().isDecimalTypeId()) {
+
+ if (!((java.lang.reflect.Method) method).getParameterTypes()[i].getComponentType().isPrimitive())
+ mb.cast(ClassName.NumberDataValue);
+ }
+ }
+ else if (paramdtd.getTypeId().isBooleanTypeId())
+ {
+ if (!((java.lang.reflect.Method) method).getParameterTypes()[i].getComponentType().isPrimitive())
+ mb.cast(ClassName.BooleanDataValue);
+ }
+
+
+
+ if (paramdtd.getTypeId().variableLength()) {
+ // need another DVD reference for the set width below.
+ mb.dup();
+ }
+
+
+ mb.getField(lf); // pvs, dvd, array
+ mb.getArrayElement(0); // pvs, dvd, value
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "setValue", "void", 1);
+
+ if (paramdtd.getTypeId().variableLength()) {
+ mb.push(isNumericType ? paramdtd.getPrecision() : paramdtd.getMaximumWidth());
+ mb.push(paramdtd.getScale());
+ mb.push(isNumericType);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", ClassName.DataValueDescriptor, 3);
+ mb.endStatement();
+ }
+ }
+ }
+ constructor.endStatement();
+ mb.endStatement();
+ }
+
+ }
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StringSlicer.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StringSlicer.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StringSlicer.java Fri Sep 24 10:33:20 2004
@@ -1,93 +1,93 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import java.lang.Math;
-
-/**
- * This utility class wraps a string, making it possible
- * to extract substrings, given byte offsets into the
- * original string.
- *
- */
-public class StringSlicer
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- private char[] charArray;
- private int charLength;
-
- /**
- * Construct a StringSlicer from a String.
- *
- * @param sourceString Source string to be sliced.
- */
- public StringSlicer( String sourceString)
- {
- if ( sourceString == null )
- {
- charArray = null;
- charLength = 0;
- }
- else
- {
- charArray = sourceString.toCharArray();
- charLength = charArray.length;
- }
- }
-
- /**
- * Get the byte length of the string.
- *
- * @return byte length of the string.
- */
- public int getCharLength() { return charLength; }
-
-
- /**
- * Get the substring between two byte offsets.
- *
- * If the beginning offset is past the end of the string,
- * returns null. If the ending offset is past the end of
- * the string, truncates the substring accordingly.
- *
- * @param beginOffset Start of substring.
- * @param endOffset End of substring.
- * @param trimflag true to trim leading and trailing spaces
- *
- * @return specified substring
- */
- public String slice( int beginOffset, int endOffset, boolean trimflag )
- {
- int length;
- String retval;
-
- if ( charLength == 0 || beginOffset >= charLength || endOffset < beginOffset )
- { return null; }
-
- endOffset = Math.min( endOffset, charLength - 1 );
- length = (endOffset - beginOffset) + 1;
-
- retval = new String( charArray, beginOffset, length );
-
- // Trim leading and trailing spaces if trimflag is
- // set (specifically for column defaults Beetle 3913)
- if (trimflag)
- retval = retval.trim();
-
- return retval;
- }
-
-
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import java.lang.Math;
+
+/**
+ * This utility class wraps a string, making it possible
+ * to extract substrings, given byte offsets into the
+ * original string.
+ *
+ */
+public class StringSlicer
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ private char[] charArray;
+ private int charLength;
+
+ /**
+ * Construct a StringSlicer from a String.
+ *
+ * @param sourceString Source string to be sliced.
+ */
+ public StringSlicer( String sourceString)
+ {
+ if ( sourceString == null )
+ {
+ charArray = null;
+ charLength = 0;
+ }
+ else
+ {
+ charArray = sourceString.toCharArray();
+ charLength = charArray.length;
+ }
+ }
+
+ /**
+ * Get the byte length of the string.
+ *
+ * @return byte length of the string.
+ */
+ public int getCharLength() { return charLength; }
+
+
+ /**
+ * Get the substring between two byte offsets.
+ *
+ * If the beginning offset is past the end of the string,
+ * returns null. If the ending offset is past the end of
+ * the string, truncates the substring accordingly.
+ *
+ * @param beginOffset Start of substring.
+ * @param endOffset End of substring.
+ * @param trimflag true to trim leading and trailing spaces
+ *
+ * @return specified substring
+ */
+ public String slice( int beginOffset, int endOffset, boolean trimflag )
+ {
+ int length;
+ String retval;
+
+ if ( charLength == 0 || beginOffset >= charLength || endOffset < beginOffset )
+ { return null; }
+
+ endOffset = Math.min( endOffset, charLength - 1 );
+ length = (endOffset - beginOffset) + 1;
+
+ retval = new String( charArray, beginOffset, length );
+
+ // Trim leading and trailing spaces if trimflag is
+ // set (specifically for column defaults Beetle 3913)
+ if (trimflag)
+ retval = retval.trim();
+
+ return retval;
+ }
+
+
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryList.java Fri Sep 24 10:33:20 2004
@@ -1,249 +1,249 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-/**
- * A SubqueryList represents a list of subquerys within a specific clause
- * (select, where or having) in a DML statement. It extends QueryTreeNodeVector.
- *
- * @author Jerry Brenner
- */
-
-public class SubqueryList extends QueryTreeNodeVector
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- /**
- * Prints the sub-nodes of this object. See QueryTreeNode.java for
- * how tree printing is supposed to work.
- *
- * @param depth The depth of this node in the tree
- *
- * @return Nothing
- */
-
- public void printSubNodes(int depth)
- {
- if (SanityManager.DEBUG)
- {
- SubqueryNode subqueryNode;
-
- super.printSubNodes(depth);
-
- for (int index = 0; index < size(); index++)
- {
- subqueryNode = (SubqueryNode) elementAt(index);
- subqueryNode.treePrint(depth + 1);
- }
- }
- }
-
- /**
- * Add a subquery to the list.
- *
- * @param subqueryNode A SubqueryNode to add to the list
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
-
- public void addSubqueryNode(SubqueryNode subqueryNode) throws StandardException
- {
- addElement(subqueryNode);
- }
-
- /**
- * Preprocess a SubqueryList. For now, we just preprocess each SubqueryNode
- * in the list.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- *
- * @return None.
- *
- * @exception StandardException Thrown on error
- */
- public void preprocess(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList)
- throws StandardException
- {
- SubqueryNode subqueryNode;
-
- int size = size();
- for (int index = 0; index < size; index++)
- {
- subqueryNode = (SubqueryNode) elementAt(index);
- subqueryNode.preprocess(numTables, outerFromList,
- outerSubqueryList,
- outerPredicateList);
- }
- }
-
- /**
- * Optimize the subqueries in this list.
- *
- * @param dataDictionary The data dictionary to use for optimization
- * @param outerRows The optimizer's estimate of the number of
- * times this subquery will be executed.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
-
- public void optimize(DataDictionary dataDictionary, double outerRows)
- throws StandardException
- {
- int size = size();
- for (int index = 0; index < size; index++)
- {
- SubqueryNode subqueryNode;
- subqueryNode = (SubqueryNode) elementAt(index);
- subqueryNode.optimize(dataDictionary, outerRows);
- }
- }
-
- /**
- * Modify the access paths for all subqueries in this list.
- *
- * @see ResultSetNode#modifyAccessPaths
- *
- * @exception StandardException Thrown on error
- */
- public void modifyAccessPaths()
- throws StandardException
- {
- int size = size();
- for (int index = 0; index < size; index++)
- {
- SubqueryNode subqueryNode;
- subqueryNode = (SubqueryNode) elementAt(index);
- subqueryNode.modifyAccessPaths();
- }
- }
-
- /**
- * Search to see if a query references the specifed table name.
- *
- * @param name Table name (String) to search for.
- * @param baseTable Whether or not name is for a base table
- *
- * @return true if found, else false
- *
- * @exception StandardException Thrown on error
- */
- public boolean referencesTarget(String name, boolean baseTable)
- throws StandardException
- {
- int size = size();
- for (int index = 0; index < size; index++)
- {
- SubqueryNode subqueryNode;
-
- subqueryNode = (SubqueryNode) elementAt(index);
- if (subqueryNode.isMaterializable())
- {
- continue;
- }
-
- if (subqueryNode.getResultSet().referencesTarget(name, baseTable))
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Return true if the node references SESSION schema tables (temporary or permanent)
- *
- * @return true if references SESSION schema tables, else false
- *
- * @exception StandardException Thrown on error
- */
- public boolean referencesSessionSchema()
- throws StandardException
- {
- int size = size();
- for (int index = 0; index < size; index++)
- {
- SubqueryNode subqueryNode;
-
- subqueryNode = (SubqueryNode) elementAt(index);
-
- if (subqueryNode.getResultSet().referencesSessionSchema())
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Set the point of attachment in all subqueries in this list.
- *
- * @param pointOfAttachment The point of attachment
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown on error
- */
- public void setPointOfAttachment(int pointOfAttachment)
- throws StandardException
- {
- int size = size();
-
- for (int index = 0; index < size; index++)
- {
- SubqueryNode subqueryNode;
-
- subqueryNode = (SubqueryNode) elementAt(index);
- subqueryNode.setPointOfAttachment(pointOfAttachment);
- }
- }
-
- /**
- * Decrement (query block) level (0-based) for
- * all of the tables in this subquery list.
- * This is useful when flattening a subquery.
- *
- * @param decrement The amount to decrement by.
- *
- * @return Nothing;
- */
- void decrementLevel(int decrement)
- {
- int size = size();
-
- for (int index = 0; index < size; index++)
- {
- ((SubqueryNode) elementAt(index)).getResultSet().decrementLevel(decrement);
- }
- }
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+/**
+ * A SubqueryList represents a list of subquerys within a specific clause
+ * (select, where or having) in a DML statement. It extends QueryTreeNodeVector.
+ *
+ * @author Jerry Brenner
+ */
+
+public class SubqueryList extends QueryTreeNodeVector
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ /**
+ * Prints the sub-nodes of this object. See QueryTreeNode.java for
+ * how tree printing is supposed to work.
+ *
+ * @param depth The depth of this node in the tree
+ *
+ * @return Nothing
+ */
+
+ public void printSubNodes(int depth)
+ {
+ if (SanityManager.DEBUG)
+ {
+ SubqueryNode subqueryNode;
+
+ super.printSubNodes(depth);
+
+ for (int index = 0; index < size(); index++)
+ {
+ subqueryNode = (SubqueryNode) elementAt(index);
+ subqueryNode.treePrint(depth + 1);
+ }
+ }
+ }
+
+ /**
+ * Add a subquery to the list.
+ *
+ * @param subqueryNode A SubqueryNode to add to the list
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void addSubqueryNode(SubqueryNode subqueryNode) throws StandardException
+ {
+ addElement(subqueryNode);
+ }
+
+ /**
+ * Preprocess a SubqueryList. For now, we just preprocess each SubqueryNode
+ * in the list.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ *
+ * @return None.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void preprocess(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList)
+ throws StandardException
+ {
+ SubqueryNode subqueryNode;
+
+ int size = size();
+ for (int index = 0; index < size; index++)
+ {
+ subqueryNode = (SubqueryNode) elementAt(index);
+ subqueryNode.preprocess(numTables, outerFromList,
+ outerSubqueryList,
+ outerPredicateList);
+ }
+ }
+
+ /**
+ * Optimize the subqueries in this list.
+ *
+ * @param dataDictionary The data dictionary to use for optimization
+ * @param outerRows The optimizer's estimate of the number of
+ * times this subquery will be executed.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void optimize(DataDictionary dataDictionary, double outerRows)
+ throws StandardException
+ {
+ int size = size();
+ for (int index = 0; index < size; index++)
+ {
+ SubqueryNode subqueryNode;
+ subqueryNode = (SubqueryNode) elementAt(index);
+ subqueryNode.optimize(dataDictionary, outerRows);
+ }
+ }
+
+ /**
+ * Modify the access paths for all subqueries in this list.
+ *
+ * @see ResultSetNode#modifyAccessPaths
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void modifyAccessPaths()
+ throws StandardException
+ {
+ int size = size();
+ for (int index = 0; index < size; index++)
+ {
+ SubqueryNode subqueryNode;
+ subqueryNode = (SubqueryNode) elementAt(index);
+ subqueryNode.modifyAccessPaths();
+ }
+ }
+
+ /**
+ * Search to see if a query references the specifed table name.
+ *
+ * @param name Table name (String) to search for.
+ * @param baseTable Whether or not name is for a base table
+ *
+ * @return true if found, else false
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean referencesTarget(String name, boolean baseTable)
+ throws StandardException
+ {
+ int size = size();
+ for (int index = 0; index < size; index++)
+ {
+ SubqueryNode subqueryNode;
+
+ subqueryNode = (SubqueryNode) elementAt(index);
+ if (subqueryNode.isMaterializable())
+ {
+ continue;
+ }
+
+ if (subqueryNode.getResultSet().referencesTarget(name, baseTable))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return true if the node references SESSION schema tables (temporary or permanent)
+ *
+ * @return true if references SESSION schema tables, else false
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean referencesSessionSchema()
+ throws StandardException
+ {
+ int size = size();
+ for (int index = 0; index < size; index++)
+ {
+ SubqueryNode subqueryNode;
+
+ subqueryNode = (SubqueryNode) elementAt(index);
+
+ if (subqueryNode.getResultSet().referencesSessionSchema())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set the point of attachment in all subqueries in this list.
+ *
+ * @param pointOfAttachment The point of attachment
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void setPointOfAttachment(int pointOfAttachment)
+ throws StandardException
+ {
+ int size = size();
+
+ for (int index = 0; index < size; index++)
+ {
+ SubqueryNode subqueryNode;
+
+ subqueryNode = (SubqueryNode) elementAt(index);
+ subqueryNode.setPointOfAttachment(pointOfAttachment);
+ }
+ }
+
+ /**
+ * Decrement (query block) level (0-based) for
+ * all of the tables in this subquery list.
+ * This is useful when flattening a subquery.
+ *
+ * @param decrement The amount to decrement by.
+ *
+ * @return Nothing;
+ */
+ void decrementLevel(int decrement)
+ {
+ int size = size();
+
+ for (int index = 0; index < size; index++)
+ {
+ ((SubqueryNode) elementAt(index)).getResultSet().decrementLevel(decrement);
+ }
+ }
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java Fri Sep 24 10:33:20 2004
@@ -1,2304 +1,2304 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.context.ContextManager;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-import org.apache.derby.iapi.sql.compile.CostEstimate;
-import org.apache.derby.iapi.sql.compile.Visitable;
-import org.apache.derby.iapi.sql.compile.Visitor;
-import org.apache.derby.iapi.sql.compile.C_NodeTypes;
-
-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.types.DataTypeDescriptor;
-
-import org.apache.derby.iapi.sql.execute.ExecRow;
-
-import org.apache.derby.iapi.sql.Activation;
-import org.apache.derby.iapi.types.DataValueDescriptor;
-import org.apache.derby.iapi.sql.Row;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.sql.ResultSet;
-import org.apache.derby.iapi.types.TypeId;
-
-import org.apache.derby.iapi.services.loader.GeneratedMethod;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-import org.apache.derby.iapi.services.compiler.LocalField;
-
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.store.access.Qualifier;
-
-import java.lang.reflect.Modifier;
-
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
-import org.apache.derby.impl.sql.execute.OnceResultSet;
-
-import org.apache.derby.iapi.util.JBitSet;
-import org.apache.derby.iapi.util.ReuseFactory;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import java.util.Properties;
-import java.util.Vector;
-
-/**
- * A SubqueryNode represents a subquery. Subqueries return values to their
- * outer queries. An quantified subquery is one that appears under a quantified
- * operator (like IN or EXISTS) - quantified subqueries can return more than
- * one value per invocation. An expression subquery is one that is not directly
- * under a quantified operator - expression subqueries are allowed to return
- * at most one value per invocation (returning no value is considered to be
- * equivalent to returning NULL).
- *
- * There are a large number of subquery types. Because of the large number of
- * types, and the large amount of shared code, we have decided to have 1 SubqueryNode
- * without any subclasses. The subquery type (and operator) is encoded in the
- * subqueryType field.
- *
- * The query optimizer is responsible for optimizing subqueries, and also for
- * transforming them so that code can be generated for them. The optimizer may
- * eliminate some subqueries by transforming them into joins, or it may
- * change the internal form of a subquery (for example, transforming
- * 'where x in (select y from z where ...)' into
- * 'where (select true from z where x = y and ...)').
- *
- * Note that aggregates present some additional issues. A transformation
- * such as:
- * <UL> where x in (SELECT <I>expression</I> FROM z) </UL>
- * has to be treated specially if <I>expression</I> has an aggregate.
- * We change it to:
- * <UL> where x = (SELECT true FROM (SELECT MAX(x) FROM z) WHERE SQLCOL1 = y) </UL>
- *
- * @author Jeff Lichtman
- */
-
-public class SubqueryNode extends ValueNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /*
- ** This must be a single-column result set. If the subquery is
- ** not quantified, it must also be a single-row result set - that is,
- ** expression subqueries are allowed to return only a single value
- ** per invocation.
- ** NOTE: SubqueryNodes are used as an intermediate step within the parser
- ** for building a derived table. Derived tables can be multi-column and
- ** multi-table.
- */
- ResultSetNode resultSet;
-
- /* Type of this subquery */
- int subqueryType;
-
- /* Whether or not this subquery is immediately under a top level AndNode.
- * (Important for subquery flattening.)
- */
- boolean underTopAndNode;
-
- /* Whether or not we've been preprocessed. (Only do the work once.) */
- boolean preprocessed;
-
- /* Whether or not this subquery began life as a distinct expression subquery */
- boolean distinctExpression;
-
- /* Since we do not have separate subquery operator nodes, the
- * type of the subquery is stored in the subqueryType field. Most subquery
- * types take a left operand (except for expression and exists). We could
- * either add a leftOperand field here or subclass SubqueryNode for those
- * types that take a left operand. We have decided to add the left operand
- * here for now.
- */
- ValueNode leftOperand;
- boolean pushedNewPredicate;
-
- /* Expression subqueries on the right side of a BinaryComparisonOperatorNode
- * will get passed a pointer to that node prior to preprocess(). This
- * allows us to replace the entire comparison, if we want to, when
- * flattening.
- */
- BinaryComparisonOperatorNode parentComparisonOperator;
-
- /* Private fields (all references via private methods) -
- * We reuse true BooleanConstantNodes within
- * this class, creating them on the first reference.
- */
- private BooleanConstantNode trueNode;
- /* Reuse generated code where possible */
- //private Expression genResult;
-
- /* Subquery # for this subquery */
- private int subqueryNumber = -1;
-
- /* ResultSet # for the point of attachment for this subquery */
- private int pointOfAttachment = -1;
-
- /*
- ** Indicate whether we found a correlation or not.
- ** And track whether we have checked yet.
- */
- private boolean foundCorrelation;
- private boolean doneCorrelationCheck;
-
- /*
- ** Indicate whether we found an invariant node
- ** below us or not. And track whether we have
- ** checked yet.
- */
- private boolean foundVariant;
- private boolean doneInvariantCheck;
-
- /* Subquery types.
- * NOTE: FROM_SUBQUERY only exists for a brief second in the parser. It
- * should never appear in a query tree.
- * NOTE: NOT EXISTS and NOT IN subquery types do not exist prior to NOT
- * elimination during preprocessing. Prior to that, there is a separate
- * NotNode above the SubqueryNode in the tree.
- *
- */
- public final static int NOTIMPLEMENTED_SUBQUERY = -1;
- public final static int FROM_SUBQUERY = 0;
- public final static int IN_SUBQUERY = 1;
- public final static int NOT_IN_SUBQUERY = 2;
- public final static int EQ_ANY_SUBQUERY = 3;
- public final static int EQ_ALL_SUBQUERY = 4;
- public final static int NE_ANY_SUBQUERY = 5;
- public final static int NE_ALL_SUBQUERY = 6;
- public final static int GT_ANY_SUBQUERY = 7;
- public final static int GT_ALL_SUBQUERY = 8;
- public final static int GE_ANY_SUBQUERY = 9;
- public final static int GE_ALL_SUBQUERY = 10;
- public final static int LT_ANY_SUBQUERY = 11;
- public final static int LT_ALL_SUBQUERY = 12;
- public final static int LE_ANY_SUBQUERY = 13;
- public final static int LE_ALL_SUBQUERY = 14;
- public final static int EXISTS_SUBQUERY = 15;
- public final static int NOT_EXISTS_SUBQUERY = 16;
- public final static int EXPRESSION_SUBQUERY = 17;
-
-
- /**
- * Initializer.
- *
- * @param resultSet The ResultSetNode for the subquery
- * @param subqueryType The type of the subquery
- * @param leftOperand The left operand, if any, of the subquery
- */
-
- public void init(
- Object resultSet,
- Object subqueryType,
- Object leftOperand)
- {
- this.resultSet = (ResultSetNode) resultSet;
- this.subqueryType = ((Integer) subqueryType).intValue();
-
- /* Subqueries are presumed not to be under a top level AndNode by
- * default. This is because expression normalization only recurses
- * under Ands and Ors, not under comparison operators, method calls,
- * built-in functions, etc.
- */
- underTopAndNode = false;
- this.leftOperand = (ValueNode) leftOperand;
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- return "subqueryType: " + subqueryType + "\n" +
- "underTopAndNode: " + underTopAndNode + "\n" +
- "subqueryNumber: " + subqueryNumber + "\n" +
- "pointOfAttachment: " + pointOfAttachment + "\n" +
- "preprocessed: " + preprocessed + "\n" +
- "distinctExpression: " + distinctExpression + "\n" +
- super.toString();
- }
- else
- {
- return "";
- }
- }
-
- /**
- * Prints the sub-nodes of this object. See QueryTreeNode.java for
- * how tree printing is supposed to work.
- *
- * @param depth The depth of this node in the tree
- *
- * @return Nothing
- */
-
- public void printSubNodes(int depth)
- {
- if (SanityManager.DEBUG)
- {
- super.printSubNodes(depth);
-
- if (resultSet != null)
- {
- printLabel(depth, "resultSet: ");
- resultSet.treePrint(depth + 1);
- }
-
- if (leftOperand != null)
- {
- printLabel(depth, "leftOperand: ");
- leftOperand.treePrint(depth + 1);
- }
- }
- }
-
- /**
- * Return the resultSet for this SubqueryNode.
- *
- * @return ResultSetNode underlying this SubqueryNode.
- */
- public ResultSetNode getResultSet()
- {
- return resultSet;
- }
-
- /**
- * Return the type of this subquery.
- *
- * @return int Type of this subquery.
- */
- public int getSubqueryType()
- {
- return subqueryType;
- }
-
- /**
- * Set the type of this subquery.
- *
- * @param Type of this subquery.
- *
- * @return None.
- */
- public void setSubqueryType(int subqueryType)
- {
- this.subqueryType = subqueryType;
- }
-
- /**
- * Set the point of attachment of this subquery.
- *
- * @param pointOfAttachment The point of attachment of this subquery.
- *
- * @return None.
- *
- * @exception StandardException Thrown on error
- */
- public void setPointOfAttachment(int pointOfAttachment)
- throws StandardException
- {
- /* Materialized subqueries always keep their point of
- * attachment as -1.
- */
- if (! isMaterializable())
- {
- this.pointOfAttachment = pointOfAttachment;
- }
- }
-
- /**
- * Return whether or not this subquery is immediately under a top level
- * AndNode.
- *
- * @return boolean Whether or not this subquery is immediately under a
- * top level AndNode.
- */
- public boolean getUnderTopAndNode()
- {
- return underTopAndNode;
- }
-
- /**
- * Get the ResultSet # for the point of attachment for this SubqueryNode.
- *
- * @return int The ResultSet # for the point of attachment
- */
- public int getPointOfAttachment()
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(pointOfAttachment >= 0,
- "pointOfAttachment expected to be >= 0");
- }
- return pointOfAttachment;
- }
-
- /**
- * Get whether or not this SubqueryNode has already been
- * preprocessed.
- *
- * @return Whether or not this SubqueryNode has already been
- * preprocessed.
- */
- boolean getPreprocessed()
- {
- return preprocessed;
- }
-
- /**
- * Set the parent BCON. Useful when considering flattening
- * expression subqueries.
- *
- * @param parent The parent BCON.
- *
- * @return Nothing.
- */
- void setParentComparisonOperator(BinaryComparisonOperatorNode parent)
- {
- parentComparisonOperator = parent;
- }
-
- /**
- * Remap all ColumnReferences in this tree to be clones of the
- * underlying expression.
- *
- * @return ValueNode The remapped expression tree.
- *
- * @exception StandardException Thrown on error
- */
- public ValueNode remapColumnReferencesToExpressions()
- throws StandardException
- {
- /* We need to remap both the SELECT and Predicate lists
- * since there may be correlated columns in either of them.
- */
- if (resultSet instanceof SelectNode)
- {
- ResultColumnList selectRCL = resultSet.getResultColumns();
- SelectNode select = (SelectNode) resultSet;
- PredicateList selectPL = select.getWherePredicates();
-
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(selectPL != null,
- "selectPL expected to be non-null");
- }
- selectRCL.remapColumnReferencesToExpressions();
- selectPL.remapColumnReferencesToExpressions();
- }
- return this;
- }
-
- /**
- * Bind this expression. This means binding the sub-expressions,
- * as well as figuring out what the return type is for this expression.
- *
- * @param fromList The FROM list for the query this
- * expression is in, for binding columns.
- * NOTE: fromList will be null if the subquery appears
- * in a VALUES clause.
- * @param subqueryList The subquery list being built as we find SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
- public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- ResultColumnList resultColumns;
-
- //check if subquery is allowed in expression tree
- checkReliability( CompilerContext.SUBQUERY_ILLEGAL, SQLState.LANG_SUBQUERY );
-
- resultColumns = resultSet.getResultColumns();
-
- /* The parser does not enforce the fact that a subquery can only return
- * a single column, so we must check here.
- */
- if (resultColumns.size() != 1)
- {
- throw StandardException.newException(SQLState.LANG_NON_SINGLE_COLUMN_SUBQUERY);
- }
-
- /* Verify the usage of "*" in the select list:
- * o Only valid in EXISTS subqueries
- * o If the AllResultColumn is qualified, then we have to verify
- * that the qualification is a valid exposed name.
- * NOTE: The exposed name can come from an outer query block.
- */
- resultSet.verifySelectStarSubquery(fromList, subqueryType);
-
- /* For an EXISTS subquery:
- * o If the SELECT list is a "*", then we convert it to a true.
- * (We need to do the conversion since we don't want the "*" to
- * get expanded.)
- * o We then must bind the expression under the SELECT list to
- * verify that it is a valid expression. (We must do this as a
- * separate step because we need to validate the expression and
- * we need to handle EXISTS (select * ... union all select 1 ...)
- * without getting a type compatability error.)
- * o Finally, we convert the expression to a SELECT true.
- */
- if (subqueryType == EXISTS_SUBQUERY)
- {
- /* Transform the * into true (EXISTS). */
- resultSet.setResultToBooleanTrueNode(true);
- }
-
- /* We need to bind the tables before we can bind the target list
- * (for exists subqueries). However, we need to wait until after
- * any *'s have been replaced, so that they don't get expanded.
- */
- CompilerContext cc = getCompilerContext();
-
- resultSet = resultSet.bindNonVTITables(getDataDictionary(), fromList);
- resultSet = resultSet.bindVTITables(fromList);
-
- /* Set the subquery # for this SubqueryNode */
- if (subqueryNumber == -1)
- subqueryNumber = cc.getNextSubqueryNumber();
-
- /* reject ? parameters in the select list of subqueries */
- resultSet.rejectParameters();
-
- if (subqueryType == EXISTS_SUBQUERY)
- {
- /* Bind the expression in the SELECT list */
- resultSet.bindTargetExpressions(fromList);
-
- /* Transform the ResultColumn into true.
- * NOTE: This may be a 2nd instance of the same transformation for
- * an EXISTS (select * ...), since we had to transform the
- * AllResultColumn above, but we have to also handle
- * EXISTS (select r from s ...)
- */
- resultSet.setResultToBooleanTrueNode(false);
- }
-
- /* bind the left operand, if there is one */
- if (leftOperand != null)
- {
- leftOperand = leftOperand.bindExpression(fromList, subqueryList,
- aggregateVector);
- }
-
- /* bind the expressions in the underlying subquery */
- resultSet.bindExpressions(fromList);
-
- resultSet.bindResultColumns(fromList);
-
- /* We need to reset resultColumns since the underlying resultSet may
- * be a UNION (and UnionNode.bindResultColumns() regens a new RCL).
- */
- resultColumns = resultSet.getResultColumns();
-
- /*
- * A ? parameter to the left of this subquery gets type of the
- * subquery's sole column.
- */
- if (leftOperand != null && leftOperand.isParameterNode())
- {
- ((ParameterNode) leftOperand).setDescriptor(
- ((ResultColumn) resultColumns.elementAt(0)).getTypeServices());
- }
-
- // Set the DataTypeServices
- setDataTypeServices(resultColumns);
-
- /* Add this subquery to the subquery list */
- subqueryList.addSubqueryNode(this);
-
- return this;
- }
-
- /**
- * Preprocess an expression tree. We do a number of transformations
- * here (including subqueries, IN lists, LIKE and BETWEEN) plus
- * subquery flattening.
- * NOTE: This is done before the outer ResultSetNode is preprocessed.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- *
- * @return The modified expression
- *
- * @exception StandardException Thrown on error
- */
- public ValueNode preprocess(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList)
- throws StandardException
- {
- /* Only preprocess this node once. We may get called multiple times
- * due to tree transformations.
- */
- if (preprocessed)
- {
- return this;
- }
- preprocessed = true;
-
- boolean flattenable;
- ValueNode topNode = this;
-
- resultSet = resultSet.preprocess(numTables, null, (FromList) null);
-
- // Eliminate any unnecessary DISTINCTs
- if (resultSet instanceof SelectNode)
- {
- if (((SelectNode) resultSet).hasDistinct())
- {
- ((SelectNode) resultSet).clearDistinct();
- /* We need to remember to check for single unique value
- * at execution time for expression subqueries.
- */
- if (subqueryType == EXPRESSION_SUBQUERY)
- {
- distinctExpression = true;
- }
- }
- }
-
- /* Lame transformation - For IN/ANY subqueries, if
- * result set is guaranteed to return at most 1 row
- * and it is not correlated
- * then convert the subquery into the matching expression
- * subquery type. For example:
- * c1 in (select min(c1) from t2)
- * becomes:
- * c1 = (select min(c1) from t2)
- * (This actually showed up in an app that a potential customer
- * was porting from SQL Server.)
- * The transformed query can then be flattened if appropriate.
- */
- if ((isIN() || isANY()) &&
- resultSet.returnsAtMostOneRow())
- {
- if (! hasCorrelatedCRs())
- {
- changeToCorrespondingExpressionType();
- }
- }
-
- /* NOTE: Flattening occurs before the pushing of
- * the predicate, since the pushing will add a node
- * above the SubqueryNode.
- */
-
- /* Values subquery is flattenable if:
- * o It is not under an OR.
- * o It is an expression subquery on the right side
- * of a BinaryComparisonOperatorNode.
- */
- flattenable = (resultSet instanceof RowResultSetNode) &&
- underTopAndNode &&
- parentComparisonOperator instanceof BinaryComparisonOperatorNode;
- if (flattenable)
- {
- /* If we got this far and we are an expression subquery
- * then we want to set leftOperand to be the left side
- * of the comparison in case we pull the comparison into
- * the flattened subquery.
- */
- leftOperand = parentComparisonOperator.getLeftOperand();
- // Flatten the subquery
- RowResultSetNode rrsn = (RowResultSetNode) resultSet;
- FromList fl = new FromList();
-
- // Remove ourselves from the outer subquery list
- outerSubqueryList.removeElement(this);
-
- /* We only need to add the table from the subquery into
- * the outer from list if the subquery itself contains
- * another subquery. Otherwise, it just becomes a constant.
- */
- if (rrsn.subquerys.size() != 0)
- {
- fl.addElement(rrsn);
- outerFromList.destructiveAppend(fl);
- }
-
- /* Append the subquery's subquery list to the
- * outer subquery list.
- */
- outerSubqueryList.destructiveAppend(rrsn.subquerys);
-
- /* return the new join condition
- * If we are flattening an EXISTS then there is no new join
- * condition since there is no leftOperand. Simply return
- * TRUE.
- *
- * NOTE: The outer where clause, etc. has already been normalized,
- * so we simply return the BinaryComparisonOperatorNode above
- * the new join condition.
- */
- ValueNode rightOperand;
- rightOperand = ((ResultColumn) rrsn.getResultColumns().elementAt(0)).
- getExpression();
- return getNewJoinCondition(leftOperand, rightOperand);
- }
-
- /* Select subquery is flattenable if:
- * o It is not under an OR.
- * o The subquery type is IN, ANY or EXISTS or
- * an expression subquery on the right side
- * of a BinaryComparisonOperatorNode.
- * o There are no aggregates in the select list
- * o There is no group by clause
- * o There is a uniqueness condition that ensures
- * that the flattening of the subquery will not
- * introduce duplicates into the result set.
- *
- * OR,
- * o The subquery is NOT EXISTS, NOT IN, ALL (beetle 5173).
- */
- boolean flattenableNotExists = (isNOT_EXISTS() || canAllBeFlattened());
-
- flattenable = (resultSet instanceof SelectNode) &&
- underTopAndNode &&
- (isIN() || isANY() || isEXISTS() || flattenableNotExists ||
- parentComparisonOperator != null);
-
- if (flattenable)
- {
- SelectNode select = (SelectNode) resultSet;
- if ((select.getAggregateVector(IN_SELECT_LIST).size() == 0) &&
- (! select.getGeneratedForGroupbyClause()))
- {
- ValueNode origLeftOperand = leftOperand;
-
- /* Check for uniqueness condition. */
- /* Is the column being returned by the subquery
- * a candidate for an = condition?
- */
- boolean additionalEQ =
- (subqueryType == IN_SUBQUERY) ||
- (subqueryType == EQ_ANY_SUBQUERY);
-
-
- additionalEQ = additionalEQ &&
- ((leftOperand instanceof ConstantNode) ||
- (leftOperand instanceof ColumnReference) ||
-
- (leftOperand.isParameterNode()));
- /* If we got this far and we are an expression subquery
- * then we want to set leftOperand to be the left side
- * of the comparison in case we pull the comparison into
- * the flattened subquery.
- */
- if (parentComparisonOperator instanceof BinaryComparisonOperatorNode)
- {
- leftOperand = parentComparisonOperator.getLeftOperand();
- }
- /* Never flatten to normal join for NOT EXISTS.
- */
- if ((! flattenableNotExists) && select.uniqueSubquery(additionalEQ))
- {
- // Flatten the subquery
- return flattenToNormalJoin(numTables,
- outerFromList, outerSubqueryList,
- outerPredicateList);
- }
- /* We can flatten into an EXISTS join if all of the above
- * conditions except for a uniqueness condition are true
- * and:
- * o Subquery only has a single entry in its from list
- * and that entry is a FromBaseTable
- * o All predicates in the subquery's where clause are
- * pushable.
- * o The leftOperand, if non-null, is pushable.
- * If the subquery meets these conditions then we will flatten
- * the FBT into an EXISTS FBT, pushd the subquery's
- * predicates down to the PRN above the EBT and
- * mark the predicates to say that they cannot be pulled
- * above the PRN. (The only way that we can guarantee correctness
- * is if the predicates do not get pulled up. If they get pulled
- * up then the single next logic for an EXISTS join does not work
- * because that row may get disqualified at a higher level.)
- */
- else if ( (isIN() || isANY() || isEXISTS() || flattenableNotExists) &&
- ((leftOperand == null) ? true :
- leftOperand.categorize(new JBitSet(numTables), false)) &&
- select.getWherePredicates().allPushable() &&
- singleFromBaseTable(select.getFromList()))
- {
- return flattenToExistsJoin(numTables,
- outerFromList, outerSubqueryList,
- outerPredicateList, flattenableNotExists);
- }
-
- // restore leftOperand to its original value
- leftOperand = origLeftOperand;
- }
- }
-
- /* We transform the leftOperand and the select list for quantified
- * predicates that have a leftOperand into a new predicate and push it
- * down to the subquery after we preprocess the subquery's resultSet.
- * We must do this after preprocessing the underlying subquery so that
- * we know where to attach the new predicate.
- * NOTE - If we pushed the predicate before preprocessing the underlying
- * subquery, then the point of attachment would depend on the form of
- * that subquery. (Where clause? Having clause?)
- */
- if (leftOperand != null)
- {
- topNode = pushNewPredicate(numTables);
- pushedNewPredicate = true;
- }
- /* Since NOT EXISTS subquery is not flattened, now is good time to create
- * an IS NULL node on top. Other cases are taken care of in pushNewPredicate.
- */
- else if (subqueryType == NOT_EXISTS_SUBQUERY)
- {
- topNode = genIsNullTree();
- subqueryType = EXISTS_SUBQUERY;
- }
-
- /*
- ** Do inVariant and correlated checks now. We
- ** aren't going to use the results here, but they
- ** have been stashed away by isInvariant() and hasCorrelatedCRs()
- */
- isInvariant();
- hasCorrelatedCRs();
-
- /* If parentComparisonOperator is non-null then we are an
- * expression subquery that was considered to be a candidate
- * for flattening, but we didn't get flattened. In that case
- * we are the rightOperand of the parent. We need to update
- * the parent's rightOperand with the new topNode and return
- * the parent because the parent is letting us decide whether
- * or not to replace the entire comparison, which we can do
- * if we flatten. Otherwise we simply return the new top node.
- */
- if (parentComparisonOperator != null)
- {
- parentComparisonOperator.setRightOperand(topNode);
- return parentComparisonOperator;
- }
-
- return topNode;
- }
-
- /**
- * Does the from list from the subquery contain a
- * single entry which is a FBT or a PRN/FBT.
- *
- * @param fromList The from list from the subquery
- *
- * @return Whether or not the from list from the subquery contains a
- * single entry which is a FBT or a PRN/FBT.
- */
- private boolean singleFromBaseTable(FromList fromList)
- {
- boolean retCode = (fromList.size() == 1);
-
- if (retCode)
- {
- FromTable ft = (FromTable) fromList.elementAt(0);
-
- if (((ft instanceof ProjectRestrictNode) &&
- ((ProjectRestrictNode) ft).getChildResult() instanceof FromBaseTable) ||
- ft instanceof FromBaseTable)
- {
- }
- else
- {
- retCode = false;
- }
- }
-
- return retCode;
- }
-
- /**
- * Can NOT IN, ALL be falttened to NOT EXISTS join? We can't or the flattening doesn't
- * easily make sense if either side of the comparison is nullable. (beetle 5173)
- *
- * @return Whether or not the NOT IN or ALL subquery can be flattened.
- */
- private boolean canAllBeFlattened ()
- {
- boolean result = false;
- if (isNOT_IN() || isALL())
- {
- ValueNode rightOperand = ((ResultColumn) resultSet.getResultColumns().elementAt(0)).
- getExpression();
- result = (! leftOperand.getTypeServices().isNullable() &&
- ! rightOperand.getTypeServices().isNullable());
- }
- return result;
- }
-
- /**
- * Flatten this subquery into the outer query block.
- * At this point we are only flattening based on a uniqueness
- * condition and only flattening non-aggregate subqueries.
- * So, we promote the subquery's from list, as is, into
- * the outer from list. For EXISTS subquerys, we return a
- * TRUE. Otherwise we return a new comparison between
- * the leftOperand and the expression in the subquery's
- * SELECT list.
- * RESOLVE - we will need to modify this logic to account
- * for exists joins and aggregates as we support flattening
- * for them.
- *
- * Anyway, here's what we do:
- * o We remove ourself from the outer subquery list.
- * o We decrement the nesting level for all tables
- * in the subquery tree.
- * o We append the subquery's from list to the outer
- * from list.
- * o We add the subquery's predicate list to the outer
- * predicate list. (The subquery has already been
- * preprocessed.)
- * o We add the subquery's subquery list to the outer
- * subquery list.
- * o For EXISTS, we return a true.
- * o Otherwise, we return a new comparison between the
- * leftOperand and the expression in the inner select's
- * RCL.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- *
- * @return The modified expression
- *
- * @exception StandardException Thrown on error
- */
- private ValueNode flattenToNormalJoin(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList)
- throws StandardException
- {
- SelectNode select = (SelectNode) resultSet;
- FromList fl = select.getFromList();
- int[] tableNumbers = fl.getTableNumbers();
-
- // Remove ourselves from the outer subquery list
- outerSubqueryList.removeElement(this);
-
- /* Decrease the nesting level for all
- * tables in the subquey tree.
- */
- select.decrementLevel(1);
-
- /* Add the table(s) from the subquery into the outer from list */
- outerFromList.destructiveAppend(fl);
-
- /* Append the subquery's predicate list to the
- * outer predicate list.
- */
- outerPredicateList.destructiveAppend(select.getWherePredicates());
-
- /* Append the subquery's subquery list to the
- * outer subquery list.
- * NOTE: We must propagate any subqueries from both the
- * SELECT list and WHERE clause of the subquery that's
- * getting flattened.
- */
- outerSubqueryList.destructiveAppend(select.getWhereSubquerys());
- outerSubqueryList.destructiveAppend(select.getSelectSubquerys());
-
- /* return the new join condition
- * If we are flattening an EXISTS then there is no new join
- * condition since there is no leftOperand. Simply return
- * TRUE.
- *
- * NOTE: The outer where clause, etc. has already been normalized,
- * so we simply return the BinaryComparisonOperatorNode above
- * the new join condition.
- */
- if (leftOperand == null)
- {
- return (ValueNode) getNodeFactory().getNode(
- C_NodeTypes.BOOLEAN_CONSTANT_NODE,
- Boolean.TRUE,
- getContextManager());
- }
- else
- {
- ValueNode rightOperand;
- rightOperand = ((ResultColumn) select.getResultColumns().elementAt(0)).
- getExpression();
- /* If the right operand is a CR, then we need to decrement
- * its source level as part of flattening so that
- * transitive closure will work correctly.
- */
- if (rightOperand instanceof ColumnReference)
- {
- ColumnReference cr = (ColumnReference) rightOperand;
- int tableNumber = cr.getTableNumber();
- for (int index = 0; index < tableNumbers.length; index++)
- {
- if (tableNumber == tableNumbers[index])
- {
- cr.setSourceLevel(
- cr.getSourceLevel() - 1);
- break;
- }
- }
- }
- return getNewJoinCondition(leftOperand, rightOperand);
- }
- }
-
- /**
- * Flatten this subquery into the outer query block
- * as an exists join.
- * At this point we are only flattening non-aggregate subqueries
- * with a single FBT in the from list.
- * So, we transform all FBTs in the from list into ExistBaseTables,
- * update the dependency lists for each of the tables and then
- * flatten the subquery.
- * RESOLVE - we will need to modify this logic to account
- * for aggregates as we support flattening
- * for them.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- * @param flattenableNotExists Is it a flattening into a NOT EXISTS join
- *
- * @return The modified expression
- *
- * @exception StandardException Thrown on error
- */
- private ValueNode flattenToExistsJoin(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList,
- boolean flattenableNotExists)
- throws StandardException
- {
- SelectNode select = (SelectNode) resultSet;
-
- // Replace the FromBaseTables in the from list with ExistBaseTables
- select.getFromList().genExistsBaseTables(resultSet.getReferencedTableMap(),
- outerFromList, flattenableNotExists);
-
- /* NOTE: Because we are currently only flattening single table subqueries
- * whose predicates are all pushable, we simply follow the rest of the
- * flattening algorithm for unique subqueries. Should we decide to
- * loosen these restrictions then we need to do more work such as:
- *
- * Mark all of the predicates from the subquery as non-pullable. They must
- * not be pulled so that we can guarantee correctness. Otherwise, we could
- * add or subtract rows from the result set.
- *
- * Remap all of the non-correlated CRs in the predicate list so that they
- * point to the correct source. (We've chopped a level out of the RCL/VCN
- * chain.) We then transfer those predicates to the PRN in the subquery's
- * from list.
- */
-
- return flattenToNormalJoin(numTables, outerFromList,
- outerSubqueryList, outerPredicateList);
- }
-
- /**
- * Check to see if we have a Variant value below us.
- * If so, return true. Caches the result so multiple
- * calls are ok.
- *
- * @return boolean whether we have
- *
- * @exception StandardException Thrown on error
- */
- private boolean isInvariant() throws StandardException
- {
- if (doneInvariantCheck)
- {
- return !foundVariant;
- }
-
- doneInvariantCheck = true;
- HasVariantValueNodeVisitor visitor = new HasVariantValueNodeVisitor();
- resultSet.accept(visitor);
- foundVariant = visitor.hasVariant();
- return !foundVariant;
- }
-
- /**
- * Check to see if this subquery has correlated
- * column references. Only useful results if
- * called AFTER binding (after CRs have been bound).
- *
- * @return whether the subquery has correlated column
- * references.
- * @exception StandardException Thrown on error
- */
- public boolean hasCorrelatedCRs() throws StandardException
- {
- if (doneCorrelationCheck)
- {
- return foundCorrelation;
- }
- doneCorrelationCheck = true;
-
- ResultSetNode realSubquery = resultSet;
- ResultColumnList oldRCL = null;
-
- /* If we have pushed the new join predicate on top, we want to disregard it
- * to see if anything under the predicate is correlated. If nothing correlated
- * under the new join predicate, we could then materialize the subquery.
- * See beetle 4373.
- */
- if (pushedNewPredicate)
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(resultSet instanceof ProjectRestrictNode,
- "resultSet expected to be a ProjectRestrictNode!");
- }
-
- realSubquery = ((ProjectRestrictNode) resultSet).getChildResult();
- oldRCL = realSubquery.getResultColumns();
-
- /* Only first column matters.
- */
- if (oldRCL.size() > 1)
- {
- ResultColumnList newRCL = new ResultColumnList();
- newRCL.addResultColumn(oldRCL.getResultColumn(1));
- realSubquery.setResultColumns(newRCL);
- }
- }
-
- HasCorrelatedCRsVisitor visitor = new HasCorrelatedCRsVisitor();
- realSubquery.accept(visitor);
- foundCorrelation = visitor.hasCorrelatedCRs();
-
- if (pushedNewPredicate && (oldRCL.size() > 1))
- {
- realSubquery.setResultColumns(oldRCL);
- }
-
- return foundCorrelation;
- }
-
- /**
- * Transform:
- * expresion QuantifiedOperator (select x from ...)
- * into
- * (select true from .. where expression <BinaryComparisonOperator> x ...)
- * IS [NOT] NULL
- *
- * or, if we have an aggregate:
- * (select true from
- * (select AGG(x) from ...)
- * where expression <BinaryComparisonOperator> x ...)
- * IS [NOT] NULL
- *
- *
- * For ANY and IN subqueries:
- * o We generate an IS NULL above the SubqueryNode and return the top of
- * the new tree to the caller.
- * o The operator in the new predicate that is added to the subquery
- * will correspond to the operator that modifies the ANY.
- * (eg, = for = ANY, with = for IN.)
- * For ALL and NOT IN subqueries:
- * o We generate an IS NOT NULL above the SubqueryNode and return the top of
- * the new tree to the caller.
- * o The operator in the new predicate that is added to the subquery
- * will be a BinaryAllOperatorNode whose bcoNodeType corresponds to
- * the negation of the operator that modifies the ALL.
- * (eg, <> for = ALL, with <> for NOT IN.)
- *
- * NOTE: This method is called after the underlying subquery has been
- * preprocessed, so we build a new Predicate, not just a new expression.
- *
- * @param numTables Number of tables in DML Statement
- *
- * @return UnaryComparisonOperatorNode An IS [NOT] NULL above the
- * transformed subquery.
- *
- * @exception StandardException Thrown on error
- */
- private UnaryComparisonOperatorNode pushNewPredicate(
- int numTables)
- throws StandardException
- {
- AndNode andNode;
- BinaryComparisonOperatorNode bcoNode = null;
- JBitSet tableMap;
- Predicate predicate;
- ResultColumn firstRC;
- ResultColumnList resultColumns;
- UnaryComparisonOperatorNode ucoNode = null;
- ValueNode oldWhereClause;
- ValueNode rightOperand;
-
- /* We have to ensure that the resultSet immediately under us has
- * a PredicateList, otherwise we can't push the predicate down.
- */
- resultSet = resultSet.ensurePredicateList(numTables);
-
- /* RESOLVE - once we understand how correlated columns will work,
- * we probably want to mark leftOperand as a correlated column
- */
- resultColumns = resultSet.getResultColumns();
-
- /*
- ** Create a new PR node. Put it over the original subquery. resulSet
- ** is now the new PR. We give the chance that things under the PR node
- ** can be materialized. See beetle 4373.
- */
- ResultColumnList newRCL = resultColumns.copyListAndObjects();
- newRCL.genVirtualColumnNodes(resultSet, resultColumns);
- resultSet = (ResultSetNode) getNodeFactory().getNode(
- C_NodeTypes.PROJECT_RESTRICT_NODE,
- resultSet, // child
- newRCL, // result columns
- null, // restriction
- null, // restriction list
- null, // project subqueries
- null, // restrict subqueries
- null,
- getContextManager());
- resultColumns = newRCL;
-
- firstRC = (ResultColumn) resultColumns.elementAt(0);
- rightOperand = firstRC.getExpression();
-
- bcoNode = getNewJoinCondition(leftOperand, rightOperand);
-
- ValueNode andLeft = bcoNode;
-
- /* For NOT IN or ALL, and if either side of the comparison is nullable, and the
- * subquery can not be flattened (because of that), we need to add IS NULL node
- * on top of the nullables, such that the behavior is (beetle 5173):
- *
- * (1) If we have nulls in right operand, no row is returned.
- * (2) If subquery result is empty before applying join predicate, every
- * left row (including NULLs) is returned.
- * (3) Otherwise, return {all left row} - {NULLs}
- */
- if (isNOT_IN() || isALL())
- {
- boolean leftNullable = leftOperand.getTypeServices().isNullable();
- boolean rightNullable = rightOperand.getTypeServices().isNullable();
- if (leftNullable || rightNullable)
- {
- /* Create a normalized structure.
- */
- BooleanConstantNode falseNode = (BooleanConstantNode) getNodeFactory().getNode(
- C_NodeTypes.BOOLEAN_CONSTANT_NODE,
- Boolean.FALSE,
- getContextManager());
- OrNode newOr = (OrNode) getNodeFactory().getNode(
- C_NodeTypes.OR_NODE,
- bcoNode,
- falseNode,
- getContextManager());
- newOr.postBindFixup();
- andLeft = newOr;
-
- if (leftNullable)
- {
- UnaryComparisonOperatorNode leftIsNull = (UnaryComparisonOperatorNode)
- getNodeFactory().getNode(
- C_NodeTypes.IS_NULL_NODE,
- leftOperand,
- getContextManager());
- leftIsNull.bindComparisonOperator();
- newOr = (OrNode) getNodeFactory().getNode(
- C_NodeTypes.OR_NODE,
- leftIsNull,
- andLeft,
- getContextManager());
- newOr.postBindFixup();
- andLeft = newOr;
- }
- if (rightNullable)
- {
- UnaryComparisonOperatorNode rightIsNull = (UnaryComparisonOperatorNode)
- getNodeFactory().getNode(
- C_NodeTypes.IS_NULL_NODE,
- rightOperand,
- getContextManager());
- rightIsNull.bindComparisonOperator();
- newOr = (OrNode) getNodeFactory().getNode(
- C_NodeTypes.OR_NODE,
- rightIsNull,
- andLeft,
- getContextManager());
- newOr.postBindFixup();
- andLeft = newOr;
- }
- }
- }
-
- /* Place an AndNode above the <BinaryComparisonOperator> */
- andNode = (AndNode) getNodeFactory().getNode(
- C_NodeTypes.AND_NODE,
- andLeft,
- getTrueNode(),
- getContextManager());
-
- /* Build the referenced table map for the new predicate */
- tableMap = new JBitSet(numTables);
- andNode.postBindFixup();
-
- /* Put the AndNode under a Predicate */
- predicate = (Predicate) getNodeFactory().getNode(
- C_NodeTypes.PREDICATE,
- andNode,
- tableMap,
- getContextManager());
- predicate.categorize();
-
- /* Push the new Predicate to the subquery's list */
- resultSet = resultSet.addNewPredicate(predicate);
-
- /* Clean up the leftOperand and subquery ResultColumn */
- leftOperand = null;
- firstRC.setType(getTypeServices());
- firstRC.setExpression(getTrueNode());
-
- /* Add the IS [NOT] NULL above the SubqueryNode */
- switch (subqueryType)
- {
- case IN_SUBQUERY:
- case EQ_ANY_SUBQUERY:
- case NE_ANY_SUBQUERY:
- case LE_ANY_SUBQUERY:
- case LT_ANY_SUBQUERY:
- case GE_ANY_SUBQUERY:
- case GT_ANY_SUBQUERY:
- ucoNode = (UnaryComparisonOperatorNode)
- getNodeFactory().getNode(
- C_NodeTypes.IS_NOT_NULL_NODE,
- this,
- getContextManager());
- break;
-
- case NOT_IN_SUBQUERY:
- case EQ_ALL_SUBQUERY:
- case NE_ALL_SUBQUERY:
- case LE_ALL_SUBQUERY:
- case LT_ALL_SUBQUERY:
- case GE_ALL_SUBQUERY:
- case GT_ALL_SUBQUERY:
- ucoNode = (UnaryComparisonOperatorNode)
- getNodeFactory().getNode(
- C_NodeTypes.IS_NULL_NODE,
- this,
- getContextManager());
- break;
- }
- ucoNode.bindComparisonOperator();
- return ucoNode;
- }
-
- /**
- * Build a new join condition between the leftOperand
- * and the rightOperand. The comparison operator
- * is dependent on the subquery type.
- *
- * @param leftOperand The left operand for the new condition.
- * @param rightOperand The right operand for the new condition.
- *
- * @exception StandardException Thrown on error
- */
- private BinaryComparisonOperatorNode getNewJoinCondition(
- ValueNode leftOperand,
- ValueNode rightOperand)
- throws StandardException
- {
- BinaryComparisonOperatorNode bcoNode = null;
-
- /* NOTE: If we are an expression subquery that's getting
- * flattened then our subqueryType is EXPRESSION_SUBQUERY.
- * However, we can get the comparison type from the
- * parentComparisonOperator. In that case we dovetail on
- * the ANY subquery types.
- */
- int operatorType = subqueryType;
- if (subqueryType == EXPRESSION_SUBQUERY)
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(parentComparisonOperator != null,
- "parentComparisonOperator expected to be non-null");
- }
-
- int parentOperator = -1;
-
- if (parentComparisonOperator.isRelationalOperator())
- {
- RelationalOperator ro = (RelationalOperator)parentComparisonOperator;
- parentOperator = ro.getOperator();
- }
-
- if (parentOperator == RelationalOperator.EQUALS_RELOP)
- {
- operatorType = EQ_ANY_SUBQUERY;
- }
- else if (parentOperator == RelationalOperator.NOT_EQUALS_RELOP)
- {
- operatorType = NE_ANY_SUBQUERY;
- }
- else if (parentOperator == RelationalOperator.LESS_EQUALS_RELOP)
- {
- operatorType = LE_ANY_SUBQUERY;
- }
- else if (parentOperator == RelationalOperator.LESS_THAN_RELOP)
- {
- operatorType = LT_ANY_SUBQUERY;
- }
- else if (parentOperator == RelationalOperator.GREATER_EQUALS_RELOP)
- {
- operatorType = GE_ANY_SUBQUERY;
- }
- else if (parentOperator == RelationalOperator.GREATER_THAN_RELOP)
- {
- operatorType = GT_ANY_SUBQUERY;
- }
- }
-
- int bcoType = 0;
- int nodeType = 0;
-
- /* Build the <BinaryComparisonOperator> */
- switch (operatorType)
- {
- case IN_SUBQUERY:
- case EQ_ANY_SUBQUERY:
- case NOT_IN_SUBQUERY:
- case NE_ALL_SUBQUERY:
- nodeType = C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE;
- break;
-
- case NE_ANY_SUBQUERY:
- case EQ_ALL_SUBQUERY:
- nodeType = C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE;
- break;
-
- case LE_ANY_SUBQUERY:
- case GT_ALL_SUBQUERY:
- nodeType = C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE;
- break;
-
- case LT_ANY_SUBQUERY:
- case GE_ALL_SUBQUERY:
- nodeType = C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE;
- break;
-
- case GE_ANY_SUBQUERY:
- case LT_ALL_SUBQUERY:
- nodeType = C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE;
- break;
-
- case GT_ANY_SUBQUERY:
- case LE_ALL_SUBQUERY:
- nodeType = C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE;
- break;
-
- default:
- if (SanityManager.DEBUG)
- SanityManager.ASSERT(false,
- "subqueryType (" + subqueryType + ") is an unexpected type");
- }
-
- bcoNode = (BinaryComparisonOperatorNode)
- getNodeFactory().getNode(
- nodeType,
- leftOperand,
- rightOperand,
- getContextManager());
-
- bcoNode.bindComparisonOperator();
- return bcoNode;
- }
-
-
- /**
- * Eliminate NotNodes in the current query block. We traverse the tree,
- * inverting ANDs and ORs and eliminating NOTs as we go. We stop at
- * ComparisonOperators and boolean expressions. We invert
- * ComparisonOperators and replace boolean expressions with
- * boolean expression = false.
- * NOTE: Since we do not recurse under ComparisonOperators, there
- * still could be NotNodes left in the tree.
- *
- * @param underNotNode Whether or not we are under a NotNode.
- *
- *
- * @return The modified expression
- *
- * @exception StandardException Thrown on error
- */
- ValueNode eliminateNots(boolean underNotNode)
- throws StandardException
- {
- ValueNode result = this;
-
- if (underNotNode)
- {
- /* Negate the subqueryType. For expression subqueries
- * we simply return subquery = false
- */
- /* RESOLVE - This code needs to get cleaned up once there are
- * more subquery types. (Consider using arrays.)
- */
- switch (subqueryType)
- {
- case EXPRESSION_SUBQUERY:
- result = genEqualsFalseTree();
- break;
-
- case EXISTS_SUBQUERY:
- subqueryType = NOT_EXISTS_SUBQUERY;
- break;
-
- /* ANY subqueries */
- case IN_SUBQUERY:
- case EQ_ANY_SUBQUERY:
- subqueryType = NOT_IN_SUBQUERY;
- break;
-
- case NE_ANY_SUBQUERY:
- subqueryType = EQ_ALL_SUBQUERY;
- break;
-
- case GE_ANY_SUBQUERY:
- subqueryType = LT_ALL_SUBQUERY;
- break;
-
- case GT_ANY_SUBQUERY:
- subqueryType = LE_ALL_SUBQUERY;
- break;
-
- case LE_ANY_SUBQUERY:
- subqueryType = GT_ALL_SUBQUERY;
- break;
-
- case LT_ANY_SUBQUERY:
- subqueryType = GE_ALL_SUBQUERY;
- break;
-
- /* ALL subqueries - no need for NOT NOT_IN_SUBQUERY, since
- * NOT IN only comes into existence here.
- */
- case EQ_ALL_SUBQUERY:
- subqueryType = NE_ANY_SUBQUERY;
- break;
-
- case NE_ALL_SUBQUERY:
- subqueryType = EQ_ANY_SUBQUERY;
- break;
-
- case GE_ALL_SUBQUERY:
- subqueryType = LT_ANY_SUBQUERY;
- break;
-
- case GT_ALL_SUBQUERY:
- subqueryType = LE_ANY_SUBQUERY;
- break;
-
- case LE_ALL_SUBQUERY:
- subqueryType = GT_ANY_SUBQUERY;
- break;
-
- case LT_ALL_SUBQUERY:
- subqueryType = GE_ANY_SUBQUERY;
- break;
-
- default:
- if (SanityManager.DEBUG)
- SanityManager.ASSERT(false,
- "NOT is not supported for this time of subquery");
- }
- }
-
- /* Halt recursion here, as each query block is preprocessed separately */
- return result;
- }
-
- /**
- * Finish putting an expression into conjunctive normal
- * form. An expression tree in conjunctive normal form meets
- * the following criteria:
- * o If the expression tree is not null,
- * the top level will be a chain of AndNodes terminating
- * in a true BooleanConstantNode.
- * o The left child of an AndNode will never be an AndNode.
- * o Any right-linked chain that includes an AndNode will
- * be entirely composed of AndNodes terminated by a true BooleanConstantNode.
- * o The left child of an OrNode will never be an OrNode.
- * o Any right-linked chain that includes an OrNode will
- * be entirely composed of OrNodes terminated by a false BooleanConstantNode.
- * o ValueNodes other than AndNodes and OrNodes are considered
- * leaf nodes for purposes of expression normalization.
- * In other words, we won't do any normalization under
- * those nodes.
- *
- * In addition, we track whether or not we are under a top level AndNode.
- * SubqueryNodes need to know this for subquery flattening.
- *
- * @param underTopAndNode Whether or not we are under a top level AndNode.
- *
- *
- * @return The modified expression
- *
- * @exception StandardException Thrown on error
- */
- public ValueNode changeToCNF(boolean underTopAndNode)
- throws StandardException
- {
- /* Remember whether or not we are immediately under a top leve
- * AndNode. This is important for subquery flattening.
- * (We can only flatten subqueries under a top level AndNode.)
- */
- this.underTopAndNode = underTopAndNode;
-
- /* Halt recursion here, as each query block is preprocessed separately */
- return this;
- }
-
- /**
- * Categorize this predicate. Initially, this means
- * building a bit map of the referenced tables for each predicate.
- * If the source of this ColumnReference (at the next underlying level)
- * is not a ColumnReference or a VirtualColumnNode then this predicate
- * will not be pushed down.
- *
- * For example, in:
- * select * from (select 1 from s) a (x) where x = 1
- * we will not push down x = 1.
- * NOTE: It would be easy to handle the case of a constant, but if the
- * inner SELECT returns an arbitrary expression, then we would have to copy
- * that tree into the pushed predicate, and that tree could contain
- * subqueries and method calls.
- * RESOLVE - revisit this issue once we have views.
- *
- * @param referencedTabs JBitSet with bit map of referenced FromTables
- * @return boolean Whether or not source.expression is a ColumnReference
- * or a VirtualColumnNode.
- *
- * @exception StandardException Thrown on error
- */
- public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
- throws StandardException
- {
- /* We stop here when only considering simple predicates
- * as we don't consider method calls when looking
- * for null invariant predicates.
- */
- if (simplePredsOnly)
- {
- return false;
- }
-
- /* RESOLVE - We need to or in a bit map when there are correlation columns */
-
- /* We categorize a query block at a time, so stop the recursion here */
-
- /* Predicates with subqueries are not pushable for now */
-
- /*
- ** If we can materialize the subquery, then it is
- ** both invariant and non-correlated. And so it
- ** is pushable.
- */
- return isMaterializable();
-
- }
-
- /*
- ** Subquery is materializable if
- ** it is an expression subquery that
- ** has no correlations and is invariant.
- */
- boolean isMaterializable() throws StandardException
- {
- boolean retval = (subqueryType == EXPRESSION_SUBQUERY) &&
- !hasCorrelatedCRs() &&
- isInvariant();
- /* If we can materialize the subquery, then we set
- * the level of all of the tables to 0 so that we can
- * consider bulk fetch for them.
- */
- if (retval)
- {
- if (resultSet instanceof SelectNode)
- {
- SelectNode select = (SelectNode) resultSet;
- FromList fromList = select.getFromList();
- fromList.setLevel(0);
- }
- }
-
- return retval;
- }
-
- /**
- * Optimize this SubqueryNode.
- *
- * @param dataDictionary The DataDictionary to use for optimization
- * @param outerRows The optimizer's estimate of the number of
- * times this subquery will be executed.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
-
- public void optimize(DataDictionary dataDictionary, double outerRows)
- throws StandardException
- {
- /* RESOLVE - is there anything else that we need to do for this
- * node.
- */
-
- /* Optimize the underlying result set */
- resultSet = resultSet.optimize(dataDictionary, null, outerRows);
- }
-
- /**
- * Make any changes to the access paths, as decided by the optimizer.
- *
- * @exception StandardException Thrown on error
- */
- public void modifyAccessPaths() throws StandardException
- {
- resultSet = resultSet.modifyAccessPaths();
- }
-
- /**
- * Return the variant type for the underlying expression.
- * The variant type can be:
- * VARIANT - variant within a scan
- * (method calls and non-static field access)
- * SCAN_INVARIANT - invariant within a scan
- * (column references from outer tables)
- * QUERY_INVARIANT - invariant within the life of a query
- * (constant expressions)
- *
- * @return The variant type for the underlying expression.
- *
- * @exception StandardException Thrown on error
- */
- protected int getOrderableVariantType() throws StandardException
- {
- /*
- * If the subquery is variant, than return
- * VARIANT. Otherwise, if we have an expression
- * subquery and no correlated CRs we are going
- * to materialize it, so it is QUERY_INVARIANT.
- * Otherwise, SCAN_INVARIANT.
- */
- if (isInvariant())
- {
- if (!hasCorrelatedCRs() &&
- (subqueryType == EXPRESSION_SUBQUERY))
- {
- return Qualifier.QUERY_INVARIANT;
- }
- else
- {
- return Qualifier.SCAN_INVARIANT;
- }
- }
- else
- {
- return Qualifier.VARIANT;
- }
- }
-
- /**
- * Do code generation for this subquery.
- *
- * @param expressionBuilder The ExpressionClassBuilder for the class being built
- * @param mbex The method the expression will go into
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateExpression(
- ExpressionClassBuilder expressionBuilder,
- MethodBuilder mbex)
- throws StandardException
- {
- CompilerContext cc = getCompilerContext();
- String resultSetString;
-
- ///////////////////////////////////////////////////////////////////////////
- //
- // Subqueries should not appear in Filter expressions. We should get here
- // only if we're compiling a query. That means that our class builder
- // is an activation builder. If we ever allow subqueries in filters, we'll
- // have to revisit this code.
- //
- ///////////////////////////////////////////////////////////////////////////
-
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(expressionBuilder instanceof ActivationClassBuilder,
- "Expecting an ActivationClassBuilder");
- }
-
- ActivationClassBuilder acb = (ActivationClassBuilder) expressionBuilder;
- /* Reuse generated code, where possible */
-
- /* Generate the appropriate (Any or Once) ResultSet */
- if (subqueryType == EXPRESSION_SUBQUERY)
- {
- resultSetString = "getOnceResultSet";
- }
- else
- {
- resultSetString = "getAnyResultSet";
- }
-
- // Get cost estimate for underlying subquery
- CostEstimate costEstimate = resultSet.getFinalCostEstimate();
-
- /* Generate a new method. It's only used within the other
- * exprFuns, so it could be private. but since we don't
- * generate the right bytecodes to invoke private methods,
- * we just make it protected. This generated class won't
- * have any subclasses, certainly! (nat 12/97)
- */
- String subqueryTypeString =
- getTypeCompiler().interfaceName();
- MethodBuilder mb = acb.newGeneratedFun(subqueryTypeString, Modifier.PROTECTED);
-
- /* Declare the field to hold the suquery's ResultSet tree */
- LocalField rsFieldLF = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.NoPutResultSet);
-
- ResultSetNode subNode = null;
-
- if (!isMaterializable())
- {
- MethodBuilder executeMB = acb.getExecuteMethod();
- if (pushedNewPredicate && (! hasCorrelatedCRs()))
- {
- /* We try to materialize the subquery if it can fit in the memory. We
- * evaluate the subquery first. If the result set fits in the memory,
- * we replace the resultset with in-memory unions of row result sets.
- * We do this trick by replacing the child result with a new node --
- * MaterializeSubqueryNode, which essentially generates the suitable
- * code to materialize the subquery if possible. This may have big
- * performance improvement. See beetle 4373.
- */
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(resultSet instanceof ProjectRestrictNode,
- "resultSet expected to be a ProjectRestrictNode!");
- }
- subNode = ((ProjectRestrictNode) resultSet).getChildResult();
- LocalField subRS = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.NoPutResultSet);
- mb.getField(subRS);
- mb.conditionalIfNull();
-
- ResultSetNode materialSubNode = new MaterializeSubqueryNode(subRS);
- ((ProjectRestrictNode) resultSet).setChildResult(materialSubNode);
-
- /* Evaluate subquery resultset here first. Next time when we come to
- * this subquery it may be replaced by a bunch of unions of rows.
- */
- subNode.generate(acb, mb);
- mb.startElseCode();
- mb.getField(subRS);
- mb.completeConditional();
-
- mb.putField(subRS);
- mb.endStatement();
-
- executeMB.pushNull( ClassName.NoPutResultSet);
- executeMB.putField(subRS);
- executeMB.endStatement();
- }
-
- executeMB.pushNull( ClassName.NoPutResultSet);
- executeMB.putField(rsFieldLF);
- executeMB.endStatement();
-
- // now we fill in the body of the conditional
- mb.getField(rsFieldLF);
- mb.conditionalIfNull();
- }
-
- acb.pushGetResultSetFactoryExpression(mb);
-
- // start of args
- int nargs;
-
- /* Inside here is where subquery could already have been materialized. 4373
- */
- resultSet.generate(acb, mb);
-
- /* Get the next ResultSet #, so that we can number the subquery's
- * empty row ResultColumnList and Once/Any ResultSet.
- */
- int subqResultSetNumber = cc.getNextResultSetNumber();
-
- /* We will be reusing the RCL from the subquery's ResultSet for the
- * empty row function. We need to reset the resultSetNumber in the
- * RCL, before we generate that function. Now that we've called
- * generate() on the subquery's ResultSet, we can reset that
- * resultSetNumber.
- */
- resultSet.getResultColumns().setResultSetNumber(subqResultSetNumber);
-
- acb.pushThisAsActivation(mb);
-
- /* Generate code for empty row */
- resultSet.getResultColumns().generateNulls(acb, mb);
-
- /*
- * arg1: suqueryExpress - Expression for subquery's
- * ResultSet
- * arg2: Activation
- * arg3: Method to generate Row with null(s) if subquery
- * Result Set is empty
- */
- if (subqueryType == EXPRESSION_SUBQUERY)
- {
- int cardinalityCheck;
-
- /* No need to do sort if subquery began life as a distinct expression subquery.
- * (We simply check for a single unique value at execution time.)
- * No need for cardinality check if we know that underlying
- * ResultSet can contain at most 1 row.
- * RESOLVE - Not necessary if we know we
- * are getting a single row because of a unique index.
- */
- if (distinctExpression)
- {
- cardinalityCheck = OnceResultSet.UNIQUE_CARDINALITY_CHECK;
- }
- else if (resultSet.returnsAtMostOneRow())
- {
- cardinalityCheck = OnceResultSet.NO_CARDINALITY_CHECK;
- }
- else
- {
- cardinalityCheck = OnceResultSet.DO_CARDINALITY_CHECK;
- }
-
- /* arg4: int - whether or not cardinality check is required
- * DO_CARDINALITY_CHECK - required
- * NO_CARDINALITY_CHECK - not required
- * UNIQUE_CARDINALITY_CHECK - verify single
- * unique value
- */
- mb.push(cardinalityCheck);
- nargs = 9;
-
- } else {
- nargs = 8;
- }
-
- mb.push(subqResultSetNumber);
- mb.push(subqueryNumber);
- mb.push(pointOfAttachment);
- mb.push(costEstimate.rowCount());
- mb.push(costEstimate.getEstimatedCost());
-
- mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, resultSetString, ClassName.NoPutResultSet, nargs);
-
-
-
- /* Fill in the body of the method
- * generates the following.
- * (NOTE: the close() method only generated for
- * materialized subqueries. All other subqueries
- * closed by top result set in the query.):
- *
- * NoPutResultSet rsFieldX;
- * {
- * <Datatype interface> col;
- * ExecRow r;
- * rsFieldX = (rsFieldX == null) ? outerRSCall() : rsFieldX; // <== NONmaterialized specific
- * rsFieldX.openCore();
- * r = rsFieldX.getNextRowCore();
- * col = (<Datatype interface>) r.getColumn(1);
- * return col;
- * }
- *
- * MATERIALIZED:
- * NoPutResultSet rsFieldX;
- * {
- * <Datatype interface> col;
- * ExecRow r;
- * rsFieldX = outerRSCall();
- * rsFieldX.openCore();
- * r = rsFieldX.getNextRowCore();
- * col = (<Datatype interface>) r.getColumn(1);
- * rsFieldX.close(); // <== materialized specific
- * return col;
- * }
- * and adds it to exprFun
- */
-
- /* Generate the declarations */ // PUSHCOMPILE
- //VariableDeclaration colVar = mb.addVariableDeclaration(subqueryTypeString);
- //VariableDeclaration rVar = mb.addVariableDeclaration(ClassName.ExecRow);
-
- if (!isMaterializable())
- {
- /* put it back
- */
- if (pushedNewPredicate && (! hasCorrelatedCRs()))
- ((ProjectRestrictNode) resultSet).setChildResult(subNode);
-
- // now we fill in the body of the conditional
- mb.startElseCode();
- mb.getField(rsFieldLF);
- mb.completeConditional();
- }
-
- mb.putField(rsFieldLF);
- mb.endStatement();
-
- /* rs.openCore() */
- mb.getField(rsFieldLF);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "openCore", "void", 0);
-
- /* r = rs.next() */
- mb.getField(rsFieldLF);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getNextRowCore", ClassName.ExecRow, 0);
- //mb.putVariable(rVar);
- //mb.endStatement();
-
- /* col = (<Datatype interface>) r.getColumn(1) */
- //mb.getVariable(rVar);
- mb.push(1); // both the Row interface and columnId are 1-based
- mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "getColumn", ClassName.DataValueDescriptor, 1);
- mb.cast(subqueryTypeString);
- //mb.putVariable(colVar);
- //mb.endStatement();
-
- /* Only generate the close() method for materialized
- * subqueries. All others will be closed when the
- * close() method is called on the top ResultSet.
- */
- if (isMaterializable())
- {
- /* rs.close() */
- mb.getField(rsFieldLF);
- mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ResultSet, "close", "void", 0);
- }
-
- /* return col */
- //mb.getVariable(colVar);
- mb.methodReturn();
- mb.complete();
-
- /*
- ** If we have an expression subquery, then we
- ** can materialize it if it has no correlated
- ** column references and is invariant.
- */
- if (isMaterializable())
- {
- LocalField lf = generateMaterialization(acb, mb, subqueryTypeString);
- mbex.getField(lf);
-
- } else {
- /* Generate the call to the new method */
- mbex.pushThis();
- mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), subqueryTypeString, 0);
- }
- }
-
- /*
- ** Materialize the subquery in question. Given the expression
- ** that represents the subquery, this returns fieldX where
- ** fieldX is set up as follows:
- **
- ** private ... fieldX
- **
- ** execute()
- ** {
- ** fieldX = <subqueryExpression>
- ** ...
- ** }
- **
- ** So we wind up evaluating the subquery when we start
- ** execution. Obviously, it is absolutely necessary that
- ** the subquery is invariant and has no correlations
- ** for this to work.
- **
- ** Ideally we wouldn't evaluate the expression subquery
- ** until we know we need to, but because we are marking
- ** this expression subquery as pushable, we must evaluate
- ** it up front because it might wind up as a qualification,
- ** and we cannot execute a subquery in the store as a
- ** qualification because the store executes qualifications
- ** while holding a latch.
- **
- ** @param acb
- ** @param type
- ** @param subqueryExpression
- */
- private LocalField generateMaterialization(
- ActivationClassBuilder acb,
- MethodBuilder mbsq,
- String type)
- {
- MethodBuilder mb = acb.executeMethod;
-
- // declare field
- LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, type);
-
- /* Generate the call to the new method */
- mb.pushThis();
- mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mbsq.getName(), type, 0);
-
- // generate: field = value (value is on stack)
- mb.putField(field);
- mb.endStatement();
-
- return field;
- }
-
- /* Private methods on private variables */
- private BooleanConstantNode getTrueNode()
- throws StandardException
- {
- if (trueNode == null)
- {
- trueNode = (BooleanConstantNode) getNodeFactory().getNode(
- C_NodeTypes.BOOLEAN_CONSTANT_NODE,
- Boolean.TRUE,
- getContextManager());
- }
- return trueNode;
- }
-
- /**
- * Accept a visitor, and call v.visit()
- * on child nodes as necessary.
- *
- * @param v the visitor
- *
- * @exception StandardException on error
- */
- public Visitable accept(Visitor v)
- throws StandardException
- {
- Visitable returnNode = v.visit(this);
-
- /* shortcut if we've already done it
- */
- if ((v instanceof HasCorrelatedCRsVisitor) && doneCorrelationCheck)
- {
- ((HasCorrelatedCRsVisitor) v).setHasCorrelatedCRs(foundCorrelation);
- return returnNode;
- }
-
- if (v.skipChildren(this))
- {
- return returnNode;
- }
-
- if (resultSet != null && !v.stopTraversal())
- {
- resultSet = (ResultSetNode)resultSet.accept(v);
- }
-
- if (leftOperand != null && !v.stopTraversal())
- {
- leftOperand = (ValueNode)leftOperand.accept(v);
- }
- return returnNode;
- }
-
- private boolean isIN()
- {
- return subqueryType == IN_SUBQUERY;
- }
-
- private boolean isNOT_IN()
- {
- return subqueryType == NOT_IN_SUBQUERY;
- }
-
- private boolean isANY()
- {
- switch (subqueryType)
- {
- case EQ_ANY_SUBQUERY:
- case NE_ANY_SUBQUERY:
- case LE_ANY_SUBQUERY:
- case LT_ANY_SUBQUERY:
- case GE_ANY_SUBQUERY:
- case GT_ANY_SUBQUERY:
- return true;
-
- default:
- return false;
- }
- }
-
- private boolean isALL()
- {
- switch (subqueryType)
- {
- case EQ_ALL_SUBQUERY:
- case NE_ALL_SUBQUERY:
- case LE_ALL_SUBQUERY:
- case LT_ALL_SUBQUERY:
- case GE_ALL_SUBQUERY:
- case GT_ALL_SUBQUERY:
- return true;
-
- default:
- return false;
- }
- }
-
- private boolean isEXISTS()
- {
- return subqueryType == EXISTS_SUBQUERY;
- }
-
- private boolean isNOT_EXISTS()
- {
- return subqueryType == NOT_EXISTS_SUBQUERY;
- }
-
- /**
- * Convert this IN/ANY subquery, which is known to return at most 1 row,
- * to an equivalent expression subquery.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
- private void changeToCorrespondingExpressionType()
- throws StandardException
- {
- BinaryOperatorNode bcon = null;
-
- switch (subqueryType)
- {
- case EQ_ANY_SUBQUERY:
- case IN_SUBQUERY:
- bcon = (BinaryOperatorNode) getNodeFactory().getNode(
- C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,
- leftOperand,
- this,
- getContextManager());
- break;
-
- case NE_ANY_SUBQUERY:
- bcon = (BinaryOperatorNode) getNodeFactory().getNode(
- C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE,
- leftOperand,
- this,
- getContextManager());
- break;
-
- case LE_ANY_SUBQUERY:
- bcon = (BinaryOperatorNode) getNodeFactory().getNode(
- C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE,
- leftOperand,
- this,
- getContextManager());
- break;
-
- case LT_ANY_SUBQUERY:
- bcon = (BinaryOperatorNode) getNodeFactory().getNode(
- C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE,
- leftOperand,
- this,
- getContextManager());
- break;
-
- case GE_ANY_SUBQUERY:
- bcon = (BinaryOperatorNode) getNodeFactory().getNode(
- C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE,
- leftOperand,
- this,
- getContextManager());
- break;
-
- case GT_ANY_SUBQUERY:
- bcon = (BinaryOperatorNode) getNodeFactory().getNode(
- C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE,
- leftOperand,
- this,
- getContextManager());
- break;
- }
-
- // clean up the state of the tree to reflect a bound expression subquery
- subqueryType = EXPRESSION_SUBQUERY;
- setDataTypeServices(resultSet.getResultColumns());
-
- parentComparisonOperator = (BinaryComparisonOperatorNode) bcon;
- /* Set type info for the operator node */
- parentComparisonOperator.bindComparisonOperator();
- leftOperand = null;
- }
-
- private void setDataTypeServices(ResultColumnList resultColumns)
- throws StandardException
- {
- DataTypeDescriptor dts;
-
- /* Set the result type for this subquery (must be nullable).
- * Quantified predicates will return boolean.
- * However, the return type of the subquery's result list will
- * probably not be boolean at this point, because we do not
- * transform the subquery (other than EXISTS) into
- * (select true/false ...) until preprocess(). So, we force
- * the return type to boolean.
- */
- if (subqueryType == EXPRESSION_SUBQUERY)
- {
- dts = ((ResultColumn) resultColumns.elementAt(0)).getTypeServices();
- }
- else
- {
- dts = getTrueNode().getTypeServices();
- }
-
- /* If datatype of underlying resultSet is nullable, reuse it, otherwise
- * we need to generate a new one.
- */
- if (! dts.isNullable())
- {
- dts = new DataTypeDescriptor(dts, true);
- }
- setType(dts);
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.context.ContextManager;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+import org.apache.derby.iapi.sql.compile.CostEstimate;
+import org.apache.derby.iapi.sql.compile.Visitable;
+import org.apache.derby.iapi.sql.compile.Visitor;
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+
+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.types.DataTypeDescriptor;
+
+import org.apache.derby.iapi.sql.execute.ExecRow;
+
+import org.apache.derby.iapi.sql.Activation;
+import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.iapi.sql.Row;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.sql.ResultSet;
+import org.apache.derby.iapi.types.TypeId;
+
+import org.apache.derby.iapi.services.loader.GeneratedMethod;
+
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+import org.apache.derby.iapi.services.compiler.LocalField;
+
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.store.access.Qualifier;
+
+import java.lang.reflect.Modifier;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
+import org.apache.derby.impl.sql.execute.OnceResultSet;
+
+import org.apache.derby.iapi.util.JBitSet;
+import org.apache.derby.iapi.util.ReuseFactory;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * A SubqueryNode represents a subquery. Subqueries return values to their
+ * outer queries. An quantified subquery is one that appears under a quantified
+ * operator (like IN or EXISTS) - quantified subqueries can return more than
+ * one value per invocation. An expression subquery is one that is not directly
+ * under a quantified operator - expression subqueries are allowed to return
+ * at most one value per invocation (returning no value is considered to be
+ * equivalent to returning NULL).
+ *
+ * There are a large number of subquery types. Because of the large number of
+ * types, and the large amount of shared code, we have decided to have 1 SubqueryNode
+ * without any subclasses. The subquery type (and operator) is encoded in the
+ * subqueryType field.
+ *
+ * The query optimizer is responsible for optimizing subqueries, and also for
+ * transforming them so that code can be generated for them. The optimizer may
+ * eliminate some subqueries by transforming them into joins, or it may
+ * change the internal form of a subquery (for example, transforming
+ * 'where x in (select y from z where ...)' into
+ * 'where (select true from z where x = y and ...)').
+ *
+ * Note that aggregates present some additional issues. A transformation
+ * such as:
+ * <UL> where x in (SELECT <I>expression</I> FROM z) </UL>
+ * has to be treated specially if <I>expression</I> has an aggregate.
+ * We change it to:
+ * <UL> where x = (SELECT true FROM (SELECT MAX(x) FROM z) WHERE SQLCOL1 = y) </UL>
+ *
+ * @author Jeff Lichtman
+ */
+
+public class SubqueryNode extends ValueNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /*
+ ** This must be a single-column result set. If the subquery is
+ ** not quantified, it must also be a single-row result set - that is,
+ ** expression subqueries are allowed to return only a single value
+ ** per invocation.
+ ** NOTE: SubqueryNodes are used as an intermediate step within the parser
+ ** for building a derived table. Derived tables can be multi-column and
+ ** multi-table.
+ */
+ ResultSetNode resultSet;
+
+ /* Type of this subquery */
+ int subqueryType;
+
+ /* Whether or not this subquery is immediately under a top level AndNode.
+ * (Important for subquery flattening.)
+ */
+ boolean underTopAndNode;
+
+ /* Whether or not we've been preprocessed. (Only do the work once.) */
+ boolean preprocessed;
+
+ /* Whether or not this subquery began life as a distinct expression subquery */
+ boolean distinctExpression;
+
+ /* Since we do not have separate subquery operator nodes, the
+ * type of the subquery is stored in the subqueryType field. Most subquery
+ * types take a left operand (except for expression and exists). We could
+ * either add a leftOperand field here or subclass SubqueryNode for those
+ * types that take a left operand. We have decided to add the left operand
+ * here for now.
+ */
+ ValueNode leftOperand;
+ boolean pushedNewPredicate;
+
+ /* Expression subqueries on the right side of a BinaryComparisonOperatorNode
+ * will get passed a pointer to that node prior to preprocess(). This
+ * allows us to replace the entire comparison, if we want to, when
+ * flattening.
+ */
+ BinaryComparisonOperatorNode parentComparisonOperator;
+
+ /* Private fields (all references via private methods) -
+ * We reuse true BooleanConstantNodes within
+ * this class, creating them on the first reference.
+ */
+ private BooleanConstantNode trueNode;
+ /* Reuse generated code where possible */
+ //private Expression genResult;
+
+ /* Subquery # for this subquery */
+ private int subqueryNumber = -1;
+
+ /* ResultSet # for the point of attachment for this subquery */
+ private int pointOfAttachment = -1;
+
+ /*
+ ** Indicate whether we found a correlation or not.
+ ** And track whether we have checked yet.
+ */
+ private boolean foundCorrelation;
+ private boolean doneCorrelationCheck;
+
+ /*
+ ** Indicate whether we found an invariant node
+ ** below us or not. And track whether we have
+ ** checked yet.
+ */
+ private boolean foundVariant;
+ private boolean doneInvariantCheck;
+
+ /* Subquery types.
+ * NOTE: FROM_SUBQUERY only exists for a brief second in the parser. It
+ * should never appear in a query tree.
+ * NOTE: NOT EXISTS and NOT IN subquery types do not exist prior to NOT
+ * elimination during preprocessing. Prior to that, there is a separate
+ * NotNode above the SubqueryNode in the tree.
+ *
+ */
+ public final static int NOTIMPLEMENTED_SUBQUERY = -1;
+ public final static int FROM_SUBQUERY = 0;
+ public final static int IN_SUBQUERY = 1;
+ public final static int NOT_IN_SUBQUERY = 2;
+ public final static int EQ_ANY_SUBQUERY = 3;
+ public final static int EQ_ALL_SUBQUERY = 4;
+ public final static int NE_ANY_SUBQUERY = 5;
+ public final static int NE_ALL_SUBQUERY = 6;
+ public final static int GT_ANY_SUBQUERY = 7;
+ public final static int GT_ALL_SUBQUERY = 8;
+ public final static int GE_ANY_SUBQUERY = 9;
+ public final static int GE_ALL_SUBQUERY = 10;
+ public final static int LT_ANY_SUBQUERY = 11;
+ public final static int LT_ALL_SUBQUERY = 12;
+ public final static int LE_ANY_SUBQUERY = 13;
+ public final static int LE_ALL_SUBQUERY = 14;
+ public final static int EXISTS_SUBQUERY = 15;
+ public final static int NOT_EXISTS_SUBQUERY = 16;
+ public final static int EXPRESSION_SUBQUERY = 17;
+
+
+ /**
+ * Initializer.
+ *
+ * @param resultSet The ResultSetNode for the subquery
+ * @param subqueryType The type of the subquery
+ * @param leftOperand The left operand, if any, of the subquery
+ */
+
+ public void init(
+ Object resultSet,
+ Object subqueryType,
+ Object leftOperand)
+ {
+ this.resultSet = (ResultSetNode) resultSet;
+ this.subqueryType = ((Integer) subqueryType).intValue();
+
+ /* Subqueries are presumed not to be under a top level AndNode by
+ * default. This is because expression normalization only recurses
+ * under Ands and Ors, not under comparison operators, method calls,
+ * built-in functions, etc.
+ */
+ underTopAndNode = false;
+ this.leftOperand = (ValueNode) leftOperand;
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ return "subqueryType: " + subqueryType + "\n" +
+ "underTopAndNode: " + underTopAndNode + "\n" +
+ "subqueryNumber: " + subqueryNumber + "\n" +
+ "pointOfAttachment: " + pointOfAttachment + "\n" +
+ "preprocessed: " + preprocessed + "\n" +
+ "distinctExpression: " + distinctExpression + "\n" +
+ super.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Prints the sub-nodes of this object. See QueryTreeNode.java for
+ * how tree printing is supposed to work.
+ *
+ * @param depth The depth of this node in the tree
+ *
+ * @return Nothing
+ */
+
+ public void printSubNodes(int depth)
+ {
+ if (SanityManager.DEBUG)
+ {
+ super.printSubNodes(depth);
+
+ if (resultSet != null)
+ {
+ printLabel(depth, "resultSet: ");
+ resultSet.treePrint(depth + 1);
+ }
+
+ if (leftOperand != null)
+ {
+ printLabel(depth, "leftOperand: ");
+ leftOperand.treePrint(depth + 1);
+ }
+ }
+ }
+
+ /**
+ * Return the resultSet for this SubqueryNode.
+ *
+ * @return ResultSetNode underlying this SubqueryNode.
+ */
+ public ResultSetNode getResultSet()
+ {
+ return resultSet;
+ }
+
+ /**
+ * Return the type of this subquery.
+ *
+ * @return int Type of this subquery.
+ */
+ public int getSubqueryType()
+ {
+ return subqueryType;
+ }
+
+ /**
+ * Set the type of this subquery.
+ *
+ * @param Type of this subquery.
+ *
+ * @return None.
+ */
+ public void setSubqueryType(int subqueryType)
+ {
+ this.subqueryType = subqueryType;
+ }
+
+ /**
+ * Set the point of attachment of this subquery.
+ *
+ * @param pointOfAttachment The point of attachment of this subquery.
+ *
+ * @return None.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void setPointOfAttachment(int pointOfAttachment)
+ throws StandardException
+ {
+ /* Materialized subqueries always keep their point of
+ * attachment as -1.
+ */
+ if (! isMaterializable())
+ {
+ this.pointOfAttachment = pointOfAttachment;
+ }
+ }
+
+ /**
+ * Return whether or not this subquery is immediately under a top level
+ * AndNode.
+ *
+ * @return boolean Whether or not this subquery is immediately under a
+ * top level AndNode.
+ */
+ public boolean getUnderTopAndNode()
+ {
+ return underTopAndNode;
+ }
+
+ /**
+ * Get the ResultSet # for the point of attachment for this SubqueryNode.
+ *
+ * @return int The ResultSet # for the point of attachment
+ */
+ public int getPointOfAttachment()
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(pointOfAttachment >= 0,
+ "pointOfAttachment expected to be >= 0");
+ }
+ return pointOfAttachment;
+ }
+
+ /**
+ * Get whether or not this SubqueryNode has already been
+ * preprocessed.
+ *
+ * @return Whether or not this SubqueryNode has already been
+ * preprocessed.
+ */
+ boolean getPreprocessed()
+ {
+ return preprocessed;
+ }
+
+ /**
+ * Set the parent BCON. Useful when considering flattening
+ * expression subqueries.
+ *
+ * @param parent The parent BCON.
+ *
+ * @return Nothing.
+ */
+ void setParentComparisonOperator(BinaryComparisonOperatorNode parent)
+ {
+ parentComparisonOperator = parent;
+ }
+
+ /**
+ * Remap all ColumnReferences in this tree to be clones of the
+ * underlying expression.
+ *
+ * @return ValueNode The remapped expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ValueNode remapColumnReferencesToExpressions()
+ throws StandardException
+ {
+ /* We need to remap both the SELECT and Predicate lists
+ * since there may be correlated columns in either of them.
+ */
+ if (resultSet instanceof SelectNode)
+ {
+ ResultColumnList selectRCL = resultSet.getResultColumns();
+ SelectNode select = (SelectNode) resultSet;
+ PredicateList selectPL = select.getWherePredicates();
+
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(selectPL != null,
+ "selectPL expected to be non-null");
+ }
+ selectRCL.remapColumnReferencesToExpressions();
+ selectPL.remapColumnReferencesToExpressions();
+ }
+ return this;
+ }
+
+ /**
+ * Bind this expression. This means binding the sub-expressions,
+ * as well as figuring out what the return type is for this expression.
+ *
+ * @param fromList The FROM list for the query this
+ * expression is in, for binding columns.
+ * NOTE: fromList will be null if the subquery appears
+ * in a VALUES clause.
+ * @param subqueryList The subquery list being built as we find SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ ResultColumnList resultColumns;
+
+ //check if subquery is allowed in expression tree
+ checkReliability( CompilerContext.SUBQUERY_ILLEGAL, SQLState.LANG_SUBQUERY );
+
+ resultColumns = resultSet.getResultColumns();
+
+ /* The parser does not enforce the fact that a subquery can only return
+ * a single column, so we must check here.
+ */
+ if (resultColumns.size() != 1)
+ {
+ throw StandardException.newException(SQLState.LANG_NON_SINGLE_COLUMN_SUBQUERY);
+ }
+
+ /* Verify the usage of "*" in the select list:
+ * o Only valid in EXISTS subqueries
+ * o If the AllResultColumn is qualified, then we have to verify
+ * that the qualification is a valid exposed name.
+ * NOTE: The exposed name can come from an outer query block.
+ */
+ resultSet.verifySelectStarSubquery(fromList, subqueryType);
+
+ /* For an EXISTS subquery:
+ * o If the SELECT list is a "*", then we convert it to a true.
+ * (We need to do the conversion since we don't want the "*" to
+ * get expanded.)
+ * o We then must bind the expression under the SELECT list to
+ * verify that it is a valid expression. (We must do this as a
+ * separate step because we need to validate the expression and
+ * we need to handle EXISTS (select * ... union all select 1 ...)
+ * without getting a type compatability error.)
+ * o Finally, we convert the expression to a SELECT true.
+ */
+ if (subqueryType == EXISTS_SUBQUERY)
+ {
+ /* Transform the * into true (EXISTS). */
+ resultSet.setResultToBooleanTrueNode(true);
+ }
+
+ /* We need to bind the tables before we can bind the target list
+ * (for exists subqueries). However, we need to wait until after
+ * any *'s have been replaced, so that they don't get expanded.
+ */
+ CompilerContext cc = getCompilerContext();
+
+ resultSet = resultSet.bindNonVTITables(getDataDictionary(), fromList);
+ resultSet = resultSet.bindVTITables(fromList);
+
+ /* Set the subquery # for this SubqueryNode */
+ if (subqueryNumber == -1)
+ subqueryNumber = cc.getNextSubqueryNumber();
+
+ /* reject ? parameters in the select list of subqueries */
+ resultSet.rejectParameters();
+
+ if (subqueryType == EXISTS_SUBQUERY)
+ {
+ /* Bind the expression in the SELECT list */
+ resultSet.bindTargetExpressions(fromList);
+
+ /* Transform the ResultColumn into true.
+ * NOTE: This may be a 2nd instance of the same transformation for
+ * an EXISTS (select * ...), since we had to transform the
+ * AllResultColumn above, but we have to also handle
+ * EXISTS (select r from s ...)
+ */
+ resultSet.setResultToBooleanTrueNode(false);
+ }
+
+ /* bind the left operand, if there is one */
+ if (leftOperand != null)
+ {
+ leftOperand = leftOperand.bindExpression(fromList, subqueryList,
+ aggregateVector);
+ }
+
+ /* bind the expressions in the underlying subquery */
+ resultSet.bindExpressions(fromList);
+
+ resultSet.bindResultColumns(fromList);
+
+ /* We need to reset resultColumns since the underlying resultSet may
+ * be a UNION (and UnionNode.bindResultColumns() regens a new RCL).
+ */
+ resultColumns = resultSet.getResultColumns();
+
+ /*
+ * A ? parameter to the left of this subquery gets type of the
+ * subquery's sole column.
+ */
+ if (leftOperand != null && leftOperand.isParameterNode())
+ {
+ ((ParameterNode) leftOperand).setDescriptor(
+ ((ResultColumn) resultColumns.elementAt(0)).getTypeServices());
+ }
+
+ // Set the DataTypeServices
+ setDataTypeServices(resultColumns);
+
+ /* Add this subquery to the subquery list */
+ subqueryList.addSubqueryNode(this);
+
+ return this;
+ }
+
+ /**
+ * Preprocess an expression tree. We do a number of transformations
+ * here (including subqueries, IN lists, LIKE and BETWEEN) plus
+ * subquery flattening.
+ * NOTE: This is done before the outer ResultSetNode is preprocessed.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ *
+ * @return The modified expression
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ValueNode preprocess(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList)
+ throws StandardException
+ {
+ /* Only preprocess this node once. We may get called multiple times
+ * due to tree transformations.
+ */
+ if (preprocessed)
+ {
+ return this;
+ }
+ preprocessed = true;
+
+ boolean flattenable;
+ ValueNode topNode = this;
+
+ resultSet = resultSet.preprocess(numTables, null, (FromList) null);
+
+ // Eliminate any unnecessary DISTINCTs
+ if (resultSet instanceof SelectNode)
+ {
+ if (((SelectNode) resultSet).hasDistinct())
+ {
+ ((SelectNode) resultSet).clearDistinct();
+ /* We need to remember to check for single unique value
+ * at execution time for expression subqueries.
+ */
+ if (subqueryType == EXPRESSION_SUBQUERY)
+ {
+ distinctExpression = true;
+ }
+ }
+ }
+
+ /* Lame transformation - For IN/ANY subqueries, if
+ * result set is guaranteed to return at most 1 row
+ * and it is not correlated
+ * then convert the subquery into the matching expression
+ * subquery type. For example:
+ * c1 in (select min(c1) from t2)
+ * becomes:
+ * c1 = (select min(c1) from t2)
+ * (This actually showed up in an app that a potential customer
+ * was porting from SQL Server.)
+ * The transformed query can then be flattened if appropriate.
+ */
+ if ((isIN() || isANY()) &&
+ resultSet.returnsAtMostOneRow())
+ {
+ if (! hasCorrelatedCRs())
+ {
+ changeToCorrespondingExpressionType();
+ }
+ }
+
+ /* NOTE: Flattening occurs before the pushing of
+ * the predicate, since the pushing will add a node
+ * above the SubqueryNode.
+ */
+
+ /* Values subquery is flattenable if:
+ * o It is not under an OR.
+ * o It is an expression subquery on the right side
+ * of a BinaryComparisonOperatorNode.
+ */
+ flattenable = (resultSet instanceof RowResultSetNode) &&
+ underTopAndNode &&
+ parentComparisonOperator instanceof BinaryComparisonOperatorNode;
+ if (flattenable)
+ {
+ /* If we got this far and we are an expression subquery
+ * then we want to set leftOperand to be the left side
+ * of the comparison in case we pull the comparison into
+ * the flattened subquery.
+ */
+ leftOperand = parentComparisonOperator.getLeftOperand();
+ // Flatten the subquery
+ RowResultSetNode rrsn = (RowResultSetNode) resultSet;
+ FromList fl = new FromList();
+
+ // Remove ourselves from the outer subquery list
+ outerSubqueryList.removeElement(this);
+
+ /* We only need to add the table from the subquery into
+ * the outer from list if the subquery itself contains
+ * another subquery. Otherwise, it just becomes a constant.
+ */
+ if (rrsn.subquerys.size() != 0)
+ {
+ fl.addElement(rrsn);
+ outerFromList.destructiveAppend(fl);
+ }
+
+ /* Append the subquery's subquery list to the
+ * outer subquery list.
+ */
+ outerSubqueryList.destructiveAppend(rrsn.subquerys);
+
+ /* return the new join condition
+ * If we are flattening an EXISTS then there is no new join
+ * condition since there is no leftOperand. Simply return
+ * TRUE.
+ *
+ * NOTE: The outer where clause, etc. has already been normalized,
+ * so we simply return the BinaryComparisonOperatorNode above
+ * the new join condition.
+ */
+ ValueNode rightOperand;
+ rightOperand = ((ResultColumn) rrsn.getResultColumns().elementAt(0)).
+ getExpression();
+ return getNewJoinCondition(leftOperand, rightOperand);
+ }
+
+ /* Select subquery is flattenable if:
+ * o It is not under an OR.
+ * o The subquery type is IN, ANY or EXISTS or
+ * an expression subquery on the right side
+ * of a BinaryComparisonOperatorNode.
+ * o There are no aggregates in the select list
+ * o There is no group by clause
+ * o There is a uniqueness condition that ensures
+ * that the flattening of the subquery will not
+ * introduce duplicates into the result set.
+ *
+ * OR,
+ * o The subquery is NOT EXISTS, NOT IN, ALL (beetle 5173).
+ */
+ boolean flattenableNotExists = (isNOT_EXISTS() || canAllBeFlattened());
+
+ flattenable = (resultSet instanceof SelectNode) &&
+ underTopAndNode &&
+ (isIN() || isANY() || isEXISTS() || flattenableNotExists ||
+ parentComparisonOperator != null);
+
+ if (flattenable)
+ {
+ SelectNode select = (SelectNode) resultSet;
+ if ((select.getAggregateVector(IN_SELECT_LIST).size() == 0) &&
+ (! select.getGeneratedForGroupbyClause()))
+ {
+ ValueNode origLeftOperand = leftOperand;
+
+ /* Check for uniqueness condition. */
+ /* Is the column being returned by the subquery
+ * a candidate for an = condition?
+ */
+ boolean additionalEQ =
+ (subqueryType == IN_SUBQUERY) ||
+ (subqueryType == EQ_ANY_SUBQUERY);
+
+
+ additionalEQ = additionalEQ &&
+ ((leftOperand instanceof ConstantNode) ||
+ (leftOperand instanceof ColumnReference) ||
+
+ (leftOperand.isParameterNode()));
+ /* If we got this far and we are an expression subquery
+ * then we want to set leftOperand to be the left side
+ * of the comparison in case we pull the comparison into
+ * the flattened subquery.
+ */
+ if (parentComparisonOperator instanceof BinaryComparisonOperatorNode)
+ {
+ leftOperand = parentComparisonOperator.getLeftOperand();
+ }
+ /* Never flatten to normal join for NOT EXISTS.
+ */
+ if ((! flattenableNotExists) && select.uniqueSubquery(additionalEQ))
+ {
+ // Flatten the subquery
+ return flattenToNormalJoin(numTables,
+ outerFromList, outerSubqueryList,
+ outerPredicateList);
+ }
+ /* We can flatten into an EXISTS join if all of the above
+ * conditions except for a uniqueness condition are true
+ * and:
+ * o Subquery only has a single entry in its from list
+ * and that entry is a FromBaseTable
+ * o All predicates in the subquery's where clause are
+ * pushable.
+ * o The leftOperand, if non-null, is pushable.
+ * If the subquery meets these conditions then we will flatten
+ * the FBT into an EXISTS FBT, pushd the subquery's
+ * predicates down to the PRN above the EBT and
+ * mark the predicates to say that they cannot be pulled
+ * above the PRN. (The only way that we can guarantee correctness
+ * is if the predicates do not get pulled up. If they get pulled
+ * up then the single next logic for an EXISTS join does not work
+ * because that row may get disqualified at a higher level.)
+ */
+ else if ( (isIN() || isANY() || isEXISTS() || flattenableNotExists) &&
+ ((leftOperand == null) ? true :
+ leftOperand.categorize(new JBitSet(numTables), false)) &&
+ select.getWherePredicates().allPushable() &&
+ singleFromBaseTable(select.getFromList()))
+ {
+ return flattenToExistsJoin(numTables,
+ outerFromList, outerSubqueryList,
+ outerPredicateList, flattenableNotExists);
+ }
+
+ // restore leftOperand to its original value
+ leftOperand = origLeftOperand;
+ }
+ }
+
+ /* We transform the leftOperand and the select list for quantified
+ * predicates that have a leftOperand into a new predicate and push it
+ * down to the subquery after we preprocess the subquery's resultSet.
+ * We must do this after preprocessing the underlying subquery so that
+ * we know where to attach the new predicate.
+ * NOTE - If we pushed the predicate before preprocessing the underlying
+ * subquery, then the point of attachment would depend on the form of
+ * that subquery. (Where clause? Having clause?)
+ */
+ if (leftOperand != null)
+ {
+ topNode = pushNewPredicate(numTables);
+ pushedNewPredicate = true;
+ }
+ /* Since NOT EXISTS subquery is not flattened, now is good time to create
+ * an IS NULL node on top. Other cases are taken care of in pushNewPredicate.
+ */
+ else if (subqueryType == NOT_EXISTS_SUBQUERY)
+ {
+ topNode = genIsNullTree();
+ subqueryType = EXISTS_SUBQUERY;
+ }
+
+ /*
+ ** Do inVariant and correlated checks now. We
+ ** aren't going to use the results here, but they
+ ** have been stashed away by isInvariant() and hasCorrelatedCRs()
+ */
+ isInvariant();
+ hasCorrelatedCRs();
+
+ /* If parentComparisonOperator is non-null then we are an
+ * expression subquery that was considered to be a candidate
+ * for flattening, but we didn't get flattened. In that case
+ * we are the rightOperand of the parent. We need to update
+ * the parent's rightOperand with the new topNode and return
+ * the parent because the parent is letting us decide whether
+ * or not to replace the entire comparison, which we can do
+ * if we flatten. Otherwise we simply return the new top node.
+ */
+ if (parentComparisonOperator != null)
+ {
+ parentComparisonOperator.setRightOperand(topNode);
+ return parentComparisonOperator;
+ }
+
+ return topNode;
+ }
+
+ /**
+ * Does the from list from the subquery contain a
+ * single entry which is a FBT or a PRN/FBT.
+ *
+ * @param fromList The from list from the subquery
+ *
+ * @return Whether or not the from list from the subquery contains a
+ * single entry which is a FBT or a PRN/FBT.
+ */
+ private boolean singleFromBaseTable(FromList fromList)
+ {
+ boolean retCode = (fromList.size() == 1);
+
+ if (retCode)
+ {
+ FromTable ft = (FromTable) fromList.elementAt(0);
+
+ if (((ft instanceof ProjectRestrictNode) &&
+ ((ProjectRestrictNode) ft).getChildResult() instanceof FromBaseTable) ||
+ ft instanceof FromBaseTable)
+ {
+ }
+ else
+ {
+ retCode = false;
+ }
+ }
+
+ return retCode;
+ }
+
+ /**
+ * Can NOT IN, ALL be falttened to NOT EXISTS join? We can't or the flattening doesn't
+ * easily make sense if either side of the comparison is nullable. (beetle 5173)
+ *
+ * @return Whether or not the NOT IN or ALL subquery can be flattened.
+ */
+ private boolean canAllBeFlattened ()
+ {
+ boolean result = false;
+ if (isNOT_IN() || isALL())
+ {
+ ValueNode rightOperand = ((ResultColumn) resultSet.getResultColumns().elementAt(0)).
+ getExpression();
+ result = (! leftOperand.getTypeServices().isNullable() &&
+ ! rightOperand.getTypeServices().isNullable());
+ }
+ return result;
+ }
+
+ /**
+ * Flatten this subquery into the outer query block.
+ * At this point we are only flattening based on a uniqueness
+ * condition and only flattening non-aggregate subqueries.
+ * So, we promote the subquery's from list, as is, into
+ * the outer from list. For EXISTS subquerys, we return a
+ * TRUE. Otherwise we return a new comparison between
+ * the leftOperand and the expression in the subquery's
+ * SELECT list.
+ * RESOLVE - we will need to modify this logic to account
+ * for exists joins and aggregates as we support flattening
+ * for them.
+ *
+ * Anyway, here's what we do:
+ * o We remove ourself from the outer subquery list.
+ * o We decrement the nesting level for all tables
+ * in the subquery tree.
+ * o We append the subquery's from list to the outer
+ * from list.
+ * o We add the subquery's predicate list to the outer
+ * predicate list. (The subquery has already been
+ * preprocessed.)
+ * o We add the subquery's subquery list to the outer
+ * subquery list.
+ * o For EXISTS, we return a true.
+ * o Otherwise, we return a new comparison between the
+ * leftOperand and the expression in the inner select's
+ * RCL.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ *
+ * @return The modified expression
+ *
+ * @exception StandardException Thrown on error
+ */
+ private ValueNode flattenToNormalJoin(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList)
+ throws StandardException
+ {
+ SelectNode select = (SelectNode) resultSet;
+ FromList fl = select.getFromList();
+ int[] tableNumbers = fl.getTableNumbers();
+
+ // Remove ourselves from the outer subquery list
+ outerSubqueryList.removeElement(this);
+
+ /* Decrease the nesting level for all
+ * tables in the subquey tree.
+ */
+ select.decrementLevel(1);
+
+ /* Add the table(s) from the subquery into the outer from list */
+ outerFromList.destructiveAppend(fl);
+
+ /* Append the subquery's predicate list to the
+ * outer predicate list.
+ */
+ outerPredicateList.destructiveAppend(select.getWherePredicates());
+
+ /* Append the subquery's subquery list to the
+ * outer subquery list.
+ * NOTE: We must propagate any subqueries from both the
+ * SELECT list and WHERE clause of the subquery that's
+ * getting flattened.
+ */
+ outerSubqueryList.destructiveAppend(select.getWhereSubquerys());
+ outerSubqueryList.destructiveAppend(select.getSelectSubquerys());
+
+ /* return the new join condition
+ * If we are flattening an EXISTS then there is no new join
+ * condition since there is no leftOperand. Simply return
+ * TRUE.
+ *
+ * NOTE: The outer where clause, etc. has already been normalized,
+ * so we simply return the BinaryComparisonOperatorNode above
+ * the new join condition.
+ */
+ if (leftOperand == null)
+ {
+ return (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.BOOLEAN_CONSTANT_NODE,
+ Boolean.TRUE,
+ getContextManager());
+ }
+ else
+ {
+ ValueNode rightOperand;
+ rightOperand = ((ResultColumn) select.getResultColumns().elementAt(0)).
+ getExpression();
+ /* If the right operand is a CR, then we need to decrement
+ * its source level as part of flattening so that
+ * transitive closure will work correctly.
+ */
+ if (rightOperand instanceof ColumnReference)
+ {
+ ColumnReference cr = (ColumnReference) rightOperand;
+ int tableNumber = cr.getTableNumber();
+ for (int index = 0; index < tableNumbers.length; index++)
+ {
+ if (tableNumber == tableNumbers[index])
+ {
+ cr.setSourceLevel(
+ cr.getSourceLevel() - 1);
+ break;
+ }
+ }
+ }
+ return getNewJoinCondition(leftOperand, rightOperand);
+ }
+ }
+
+ /**
+ * Flatten this subquery into the outer query block
+ * as an exists join.
+ * At this point we are only flattening non-aggregate subqueries
+ * with a single FBT in the from list.
+ * So, we transform all FBTs in the from list into ExistBaseTables,
+ * update the dependency lists for each of the tables and then
+ * flatten the subquery.
+ * RESOLVE - we will need to modify this logic to account
+ * for aggregates as we support flattening
+ * for them.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ * @param flattenableNotExists Is it a flattening into a NOT EXISTS join
+ *
+ * @return The modified expression
+ *
+ * @exception StandardException Thrown on error
+ */
+ private ValueNode flattenToExistsJoin(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList,
+ boolean flattenableNotExists)
+ throws StandardException
+ {
+ SelectNode select = (SelectNode) resultSet;
+
+ // Replace the FromBaseTables in the from list with ExistBaseTables
+ select.getFromList().genExistsBaseTables(resultSet.getReferencedTableMap(),
+ outerFromList, flattenableNotExists);
+
+ /* NOTE: Because we are currently only flattening single table subqueries
+ * whose predicates are all pushable, we simply follow the rest of the
+ * flattening algorithm for unique subqueries. Should we decide to
+ * loosen these restrictions then we need to do more work such as:
+ *
+ * Mark all of the predicates from the subquery as non-pullable. They must
+ * not be pulled so that we can guarantee correctness. Otherwise, we could
+ * add or subtract rows from the result set.
+ *
+ * Remap all of the non-correlated CRs in the predicate list so that they
+ * point to the correct source. (We've chopped a level out of the RCL/VCN
+ * chain.) We then transfer those predicates to the PRN in the subquery's
+ * from list.
+ */
+
+ return flattenToNormalJoin(numTables, outerFromList,
+ outerSubqueryList, outerPredicateList);
+ }
+
+ /**
+ * Check to see if we have a Variant value below us.
+ * If so, return true. Caches the result so multiple
+ * calls are ok.
+ *
+ * @return boolean whether we have
+ *
+ * @exception StandardException Thrown on error
+ */
+ private boolean isInvariant() throws StandardException
+ {
+ if (doneInvariantCheck)
+ {
+ return !foundVariant;
+ }
+
+ doneInvariantCheck = true;
+ HasVariantValueNodeVisitor visitor = new HasVariantValueNodeVisitor();
+ resultSet.accept(visitor);
+ foundVariant = visitor.hasVariant();
+ return !foundVariant;
+ }
+
+ /**
+ * Check to see if this subquery has correlated
+ * column references. Only useful results if
+ * called AFTER binding (after CRs have been bound).
+ *
+ * @return whether the subquery has correlated column
+ * references.
+ * @exception StandardException Thrown on error
+ */
+ public boolean hasCorrelatedCRs() throws StandardException
+ {
+ if (doneCorrelationCheck)
+ {
+ return foundCorrelation;
+ }
+ doneCorrelationCheck = true;
+
+ ResultSetNode realSubquery = resultSet;
+ ResultColumnList oldRCL = null;
+
+ /* If we have pushed the new join predicate on top, we want to disregard it
+ * to see if anything under the predicate is correlated. If nothing correlated
+ * under the new join predicate, we could then materialize the subquery.
+ * See beetle 4373.
+ */
+ if (pushedNewPredicate)
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(resultSet instanceof ProjectRestrictNode,
+ "resultSet expected to be a ProjectRestrictNode!");
+ }
+
+ realSubquery = ((ProjectRestrictNode) resultSet).getChildResult();
+ oldRCL = realSubquery.getResultColumns();
+
+ /* Only first column matters.
+ */
+ if (oldRCL.size() > 1)
+ {
+ ResultColumnList newRCL = new ResultColumnList();
+ newRCL.addResultColumn(oldRCL.getResultColumn(1));
+ realSubquery.setResultColumns(newRCL);
+ }
+ }
+
+ HasCorrelatedCRsVisitor visitor = new HasCorrelatedCRsVisitor();
+ realSubquery.accept(visitor);
+ foundCorrelation = visitor.hasCorrelatedCRs();
+
+ if (pushedNewPredicate && (oldRCL.size() > 1))
+ {
+ realSubquery.setResultColumns(oldRCL);
+ }
+
+ return foundCorrelation;
+ }
+
+ /**
+ * Transform:
+ * expresion QuantifiedOperator (select x from ...)
+ * into
+ * (select true from .. where expression <BinaryComparisonOperator> x ...)
+ * IS [NOT] NULL
+ *
+ * or, if we have an aggregate:
+ * (select true from
+ * (select AGG(x) from ...)
+ * where expression <BinaryComparisonOperator> x ...)
+ * IS [NOT] NULL
+ *
+ *
+ * For ANY and IN subqueries:
+ * o We generate an IS NULL above the SubqueryNode and return the top of
+ * the new tree to the caller.
+ * o The operator in the new predicate that is added to the subquery
+ * will correspond to the operator that modifies the ANY.
+ * (eg, = for = ANY, with = for IN.)
+ * For ALL and NOT IN subqueries:
+ * o We generate an IS NOT NULL above the SubqueryNode and return the top of
+ * the new tree to the caller.
+ * o The operator in the new predicate that is added to the subquery
+ * will be a BinaryAllOperatorNode whose bcoNodeType corresponds to
+ * the negation of the operator that modifies the ALL.
+ * (eg, <> for = ALL, with <> for NOT IN.)
+ *
+ * NOTE: This method is called after the underlying subquery has been
+ * preprocessed, so we build a new Predicate, not just a new expression.
+ *
+ * @param numTables Number of tables in DML Statement
+ *
+ * @return UnaryComparisonOperatorNode An IS [NOT] NULL above the
+ * transformed subquery.
+ *
+ * @exception StandardException Thrown on error
+ */
+ private UnaryComparisonOperatorNode pushNewPredicate(
+ int numTables)
+ throws StandardException
+ {
+ AndNode andNode;
+ BinaryComparisonOperatorNode bcoNode = null;
+ JBitSet tableMap;
+ Predicate predicate;
+ ResultColumn firstRC;
+ ResultColumnList resultColumns;
+ UnaryComparisonOperatorNode ucoNode = null;
+ ValueNode oldWhereClause;
+ ValueNode rightOperand;
+
+ /* We have to ensure that the resultSet immediately under us has
+ * a PredicateList, otherwise we can't push the predicate down.
+ */
+ resultSet = resultSet.ensurePredicateList(numTables);
+
+ /* RESOLVE - once we understand how correlated columns will work,
+ * we probably want to mark leftOperand as a correlated column
+ */
+ resultColumns = resultSet.getResultColumns();
+
+ /*
+ ** Create a new PR node. Put it over the original subquery. resulSet
+ ** is now the new PR. We give the chance that things under the PR node
+ ** can be materialized. See beetle 4373.
+ */
+ ResultColumnList newRCL = resultColumns.copyListAndObjects();
+ newRCL.genVirtualColumnNodes(resultSet, resultColumns);
+ resultSet = (ResultSetNode) getNodeFactory().getNode(
+ C_NodeTypes.PROJECT_RESTRICT_NODE,
+ resultSet, // child
+ newRCL, // result columns
+ null, // restriction
+ null, // restriction list
+ null, // project subqueries
+ null, // restrict subqueries
+ null,
+ getContextManager());
+ resultColumns = newRCL;
+
+ firstRC = (ResultColumn) resultColumns.elementAt(0);
+ rightOperand = firstRC.getExpression();
+
+ bcoNode = getNewJoinCondition(leftOperand, rightOperand);
+
+ ValueNode andLeft = bcoNode;
+
+ /* For NOT IN or ALL, and if either side of the comparison is nullable, and the
+ * subquery can not be flattened (because of that), we need to add IS NULL node
+ * on top of the nullables, such that the behavior is (beetle 5173):
+ *
+ * (1) If we have nulls in right operand, no row is returned.
+ * (2) If subquery result is empty before applying join predicate, every
+ * left row (including NULLs) is returned.
+ * (3) Otherwise, return {all left row} - {NULLs}
+ */
+ if (isNOT_IN() || isALL())
+ {
+ boolean leftNullable = leftOperand.getTypeServices().isNullable();
+ boolean rightNullable = rightOperand.getTypeServices().isNullable();
+ if (leftNullable || rightNullable)
+ {
+ /* Create a normalized structure.
+ */
+ BooleanConstantNode falseNode = (BooleanConstantNode) getNodeFactory().getNode(
+ C_NodeTypes.BOOLEAN_CONSTANT_NODE,
+ Boolean.FALSE,
+ getContextManager());
+ OrNode newOr = (OrNode) getNodeFactory().getNode(
+ C_NodeTypes.OR_NODE,
+ bcoNode,
+ falseNode,
+ getContextManager());
+ newOr.postBindFixup();
+ andLeft = newOr;
+
+ if (leftNullable)
+ {
+ UnaryComparisonOperatorNode leftIsNull = (UnaryComparisonOperatorNode)
+ getNodeFactory().getNode(
+ C_NodeTypes.IS_NULL_NODE,
+ leftOperand,
+ getContextManager());
+ leftIsNull.bindComparisonOperator();
+ newOr = (OrNode) getNodeFactory().getNode(
+ C_NodeTypes.OR_NODE,
+ leftIsNull,
+ andLeft,
+ getContextManager());
+ newOr.postBindFixup();
+ andLeft = newOr;
+ }
+ if (rightNullable)
+ {
+ UnaryComparisonOperatorNode rightIsNull = (UnaryComparisonOperatorNode)
+ getNodeFactory().getNode(
+ C_NodeTypes.IS_NULL_NODE,
+ rightOperand,
+ getContextManager());
+ rightIsNull.bindComparisonOperator();
+ newOr = (OrNode) getNodeFactory().getNode(
+ C_NodeTypes.OR_NODE,
+ rightIsNull,
+ andLeft,
+ getContextManager());
+ newOr.postBindFixup();
+ andLeft = newOr;
+ }
+ }
+ }
+
+ /* Place an AndNode above the <BinaryComparisonOperator> */
+ andNode = (AndNode) getNodeFactory().getNode(
+ C_NodeTypes.AND_NODE,
+ andLeft,
+ getTrueNode(),
+ getContextManager());
+
+ /* Build the referenced table map for the new predicate */
+ tableMap = new JBitSet(numTables);
+ andNode.postBindFixup();
+
+ /* Put the AndNode under a Predicate */
+ predicate = (Predicate) getNodeFactory().getNode(
+ C_NodeTypes.PREDICATE,
+ andNode,
+ tableMap,
+ getContextManager());
+ predicate.categorize();
+
+ /* Push the new Predicate to the subquery's list */
+ resultSet = resultSet.addNewPredicate(predicate);
+
+ /* Clean up the leftOperand and subquery ResultColumn */
+ leftOperand = null;
+ firstRC.setType(getTypeServices());
+ firstRC.setExpression(getTrueNode());
+
+ /* Add the IS [NOT] NULL above the SubqueryNode */
+ switch (subqueryType)
+ {
+ case IN_SUBQUERY:
+ case EQ_ANY_SUBQUERY:
+ case NE_ANY_SUBQUERY:
+ case LE_ANY_SUBQUERY:
+ case LT_ANY_SUBQUERY:
+ case GE_ANY_SUBQUERY:
+ case GT_ANY_SUBQUERY:
+ ucoNode = (UnaryComparisonOperatorNode)
+ getNodeFactory().getNode(
+ C_NodeTypes.IS_NOT_NULL_NODE,
+ this,
+ getContextManager());
+ break;
+
+ case NOT_IN_SUBQUERY:
+ case EQ_ALL_SUBQUERY:
+ case NE_ALL_SUBQUERY:
+ case LE_ALL_SUBQUERY:
+ case LT_ALL_SUBQUERY:
+ case GE_ALL_SUBQUERY:
+ case GT_ALL_SUBQUERY:
+ ucoNode = (UnaryComparisonOperatorNode)
+ getNodeFactory().getNode(
+ C_NodeTypes.IS_NULL_NODE,
+ this,
+ getContextManager());
+ break;
+ }
+ ucoNode.bindComparisonOperator();
+ return ucoNode;
+ }
+
+ /**
+ * Build a new join condition between the leftOperand
+ * and the rightOperand. The comparison operator
+ * is dependent on the subquery type.
+ *
+ * @param leftOperand The left operand for the new condition.
+ * @param rightOperand The right operand for the new condition.
+ *
+ * @exception StandardException Thrown on error
+ */
+ private BinaryComparisonOperatorNode getNewJoinCondition(
+ ValueNode leftOperand,
+ ValueNode rightOperand)
+ throws StandardException
+ {
+ BinaryComparisonOperatorNode bcoNode = null;
+
+ /* NOTE: If we are an expression subquery that's getting
+ * flattened then our subqueryType is EXPRESSION_SUBQUERY.
+ * However, we can get the comparison type from the
+ * parentComparisonOperator. In that case we dovetail on
+ * the ANY subquery types.
+ */
+ int operatorType = subqueryType;
+ if (subqueryType == EXPRESSION_SUBQUERY)
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(parentComparisonOperator != null,
+ "parentComparisonOperator expected to be non-null");
+ }
+
+ int parentOperator = -1;
+
+ if (parentComparisonOperator.isRelationalOperator())
+ {
+ RelationalOperator ro = (RelationalOperator)parentComparisonOperator;
+ parentOperator = ro.getOperator();
+ }
+
+ if (parentOperator == RelationalOperator.EQUALS_RELOP)
+ {
+ operatorType = EQ_ANY_SUBQUERY;
+ }
+ else if (parentOperator == RelationalOperator.NOT_EQUALS_RELOP)
+ {
+ operatorType = NE_ANY_SUBQUERY;
+ }
+ else if (parentOperator == RelationalOperator.LESS_EQUALS_RELOP)
+ {
+ operatorType = LE_ANY_SUBQUERY;
+ }
+ else if (parentOperator == RelationalOperator.LESS_THAN_RELOP)
+ {
+ operatorType = LT_ANY_SUBQUERY;
+ }
+ else if (parentOperator == RelationalOperator.GREATER_EQUALS_RELOP)
+ {
+ operatorType = GE_ANY_SUBQUERY;
+ }
+ else if (parentOperator == RelationalOperator.GREATER_THAN_RELOP)
+ {
+ operatorType = GT_ANY_SUBQUERY;
+ }
+ }
+
+ int bcoType = 0;
+ int nodeType = 0;
+
+ /* Build the <BinaryComparisonOperator> */
+ switch (operatorType)
+ {
+ case IN_SUBQUERY:
+ case EQ_ANY_SUBQUERY:
+ case NOT_IN_SUBQUERY:
+ case NE_ALL_SUBQUERY:
+ nodeType = C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE;
+ break;
+
+ case NE_ANY_SUBQUERY:
+ case EQ_ALL_SUBQUERY:
+ nodeType = C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE;
+ break;
+
+ case LE_ANY_SUBQUERY:
+ case GT_ALL_SUBQUERY:
+ nodeType = C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE;
+ break;
+
+ case LT_ANY_SUBQUERY:
+ case GE_ALL_SUBQUERY:
+ nodeType = C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE;
+ break;
+
+ case GE_ANY_SUBQUERY:
+ case LT_ALL_SUBQUERY:
+ nodeType = C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE;
+ break;
+
+ case GT_ANY_SUBQUERY:
+ case LE_ALL_SUBQUERY:
+ nodeType = C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE;
+ break;
+
+ default:
+ if (SanityManager.DEBUG)
+ SanityManager.ASSERT(false,
+ "subqueryType (" + subqueryType + ") is an unexpected type");
+ }
+
+ bcoNode = (BinaryComparisonOperatorNode)
+ getNodeFactory().getNode(
+ nodeType,
+ leftOperand,
+ rightOperand,
+ getContextManager());
+
+ bcoNode.bindComparisonOperator();
+ return bcoNode;
+ }
+
+
+ /**
+ * Eliminate NotNodes in the current query block. We traverse the tree,
+ * inverting ANDs and ORs and eliminating NOTs as we go. We stop at
+ * ComparisonOperators and boolean expressions. We invert
+ * ComparisonOperators and replace boolean expressions with
+ * boolean expression = false.
+ * NOTE: Since we do not recurse under ComparisonOperators, there
+ * still could be NotNodes left in the tree.
+ *
+ * @param underNotNode Whether or not we are under a NotNode.
+ *
+ *
+ * @return The modified expression
+ *
+ * @exception StandardException Thrown on error
+ */
+ ValueNode eliminateNots(boolean underNotNode)
+ throws StandardException
+ {
+ ValueNode result = this;
+
+ if (underNotNode)
+ {
+ /* Negate the subqueryType. For expression subqueries
+ * we simply return subquery = false
+ */
+ /* RESOLVE - This code needs to get cleaned up once there are
+ * more subquery types. (Consider using arrays.)
+ */
+ switch (subqueryType)
+ {
+ case EXPRESSION_SUBQUERY:
+ result = genEqualsFalseTree();
+ break;
+
+ case EXISTS_SUBQUERY:
+ subqueryType = NOT_EXISTS_SUBQUERY;
+ break;
+
+ /* ANY subqueries */
+ case IN_SUBQUERY:
+ case EQ_ANY_SUBQUERY:
+ subqueryType = NOT_IN_SUBQUERY;
+ break;
+
+ case NE_ANY_SUBQUERY:
+ subqueryType = EQ_ALL_SUBQUERY;
+ break;
+
+ case GE_ANY_SUBQUERY:
+ subqueryType = LT_ALL_SUBQUERY;
+ break;
+
+ case GT_ANY_SUBQUERY:
+ subqueryType = LE_ALL_SUBQUERY;
+ break;
+
+ case LE_ANY_SUBQUERY:
+ subqueryType = GT_ALL_SUBQUERY;
+ break;
+
+ case LT_ANY_SUBQUERY:
+ subqueryType = GE_ALL_SUBQUERY;
+ break;
+
+ /* ALL subqueries - no need for NOT NOT_IN_SUBQUERY, since
+ * NOT IN only comes into existence here.
+ */
+ case EQ_ALL_SUBQUERY:
+ subqueryType = NE_ANY_SUBQUERY;
+ break;
+
+ case NE_ALL_SUBQUERY:
+ subqueryType = EQ_ANY_SUBQUERY;
+ break;
+
+ case GE_ALL_SUBQUERY:
+ subqueryType = LT_ANY_SUBQUERY;
+ break;
+
+ case GT_ALL_SUBQUERY:
+ subqueryType = LE_ANY_SUBQUERY;
+ break;
+
+ case LE_ALL_SUBQUERY:
+ subqueryType = GT_ANY_SUBQUERY;
+ break;
+
+ case LT_ALL_SUBQUERY:
+ subqueryType = GE_ANY_SUBQUERY;
+ break;
+
+ default:
+ if (SanityManager.DEBUG)
+ SanityManager.ASSERT(false,
+ "NOT is not supported for this time of subquery");
+ }
+ }
+
+ /* Halt recursion here, as each query block is preprocessed separately */
+ return result;
+ }
+
+ /**
+ * Finish putting an expression into conjunctive normal
+ * form. An expression tree in conjunctive normal form meets
+ * the following criteria:
+ * o If the expression tree is not null,
+ * the top level will be a chain of AndNodes terminating
+ * in a true BooleanConstantNode.
+ * o The left child of an AndNode will never be an AndNode.
+ * o Any right-linked chain that includes an AndNode will
+ * be entirely composed of AndNodes terminated by a true BooleanConstantNode.
+ * o The left child of an OrNode will never be an OrNode.
+ * o Any right-linked chain that includes an OrNode will
+ * be entirely composed of OrNodes terminated by a false BooleanConstantNode.
+ * o ValueNodes other than AndNodes and OrNodes are considered
+ * leaf nodes for purposes of expression normalization.
+ * In other words, we won't do any normalization under
+ * those nodes.
+ *
+ * In addition, we track whether or not we are under a top level AndNode.
+ * SubqueryNodes need to know this for subquery flattening.
+ *
+ * @param underTopAndNode Whether or not we are under a top level AndNode.
+ *
+ *
+ * @return The modified expression
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ValueNode changeToCNF(boolean underTopAndNode)
+ throws StandardException
+ {
+ /* Remember whether or not we are immediately under a top leve
+ * AndNode. This is important for subquery flattening.
+ * (We can only flatten subqueries under a top level AndNode.)
+ */
+ this.underTopAndNode = underTopAndNode;
+
+ /* Halt recursion here, as each query block is preprocessed separately */
+ return this;
+ }
+
+ /**
+ * Categorize this predicate. Initially, this means
+ * building a bit map of the referenced tables for each predicate.
+ * If the source of this ColumnReference (at the next underlying level)
+ * is not a ColumnReference or a VirtualColumnNode then this predicate
+ * will not be pushed down.
+ *
+ * For example, in:
+ * select * from (select 1 from s) a (x) where x = 1
+ * we will not push down x = 1.
+ * NOTE: It would be easy to handle the case of a constant, but if the
+ * inner SELECT returns an arbitrary expression, then we would have to copy
+ * that tree into the pushed predicate, and that tree could contain
+ * subqueries and method calls.
+ * RESOLVE - revisit this issue once we have views.
+ *
+ * @param referencedTabs JBitSet with bit map of referenced FromTables
+ * @return boolean Whether or not source.expression is a ColumnReference
+ * or a VirtualColumnNode.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
+ throws StandardException
+ {
+ /* We stop here when only considering simple predicates
+ * as we don't consider method calls when looking
+ * for null invariant predicates.
+ */
+ if (simplePredsOnly)
+ {
+ return false;
+ }
+
+ /* RESOLVE - We need to or in a bit map when there are correlation columns */
+
+ /* We categorize a query block at a time, so stop the recursion here */
+
+ /* Predicates with subqueries are not pushable for now */
+
+ /*
+ ** If we can materialize the subquery, then it is
+ ** both invariant and non-correlated. And so it
+ ** is pushable.
+ */
+ return isMaterializable();
+
+ }
+
+ /*
+ ** Subquery is materializable if
+ ** it is an expression subquery that
+ ** has no correlations and is invariant.
+ */
+ boolean isMaterializable() throws StandardException
+ {
+ boolean retval = (subqueryType == EXPRESSION_SUBQUERY) &&
+ !hasCorrelatedCRs() &&
+ isInvariant();
+ /* If we can materialize the subquery, then we set
+ * the level of all of the tables to 0 so that we can
+ * consider bulk fetch for them.
+ */
+ if (retval)
+ {
+ if (resultSet instanceof SelectNode)
+ {
+ SelectNode select = (SelectNode) resultSet;
+ FromList fromList = select.getFromList();
+ fromList.setLevel(0);
+ }
+ }
+
+ return retval;
+ }
+
+ /**
+ * Optimize this SubqueryNode.
+ *
+ * @param dataDictionary The DataDictionary to use for optimization
+ * @param outerRows The optimizer's estimate of the number of
+ * times this subquery will be executed.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void optimize(DataDictionary dataDictionary, double outerRows)
+ throws StandardException
+ {
+ /* RESOLVE - is there anything else that we need to do for this
+ * node.
+ */
+
+ /* Optimize the underlying result set */
+ resultSet = resultSet.optimize(dataDictionary, null, outerRows);
+ }
+
+ /**
+ * Make any changes to the access paths, as decided by the optimizer.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void modifyAccessPaths() throws StandardException
+ {
+ resultSet = resultSet.modifyAccessPaths();
+ }
+
+ /**
+ * Return the variant type for the underlying expression.
+ * The variant type can be:
+ * VARIANT - variant within a scan
+ * (method calls and non-static field access)
+ * SCAN_INVARIANT - invariant within a scan
+ * (column references from outer tables)
+ * QUERY_INVARIANT - invariant within the life of a query
+ * (constant expressions)
+ *
+ * @return The variant type for the underlying expression.
+ *
+ * @exception StandardException Thrown on error
+ */
+ protected int getOrderableVariantType() throws StandardException
+ {
+ /*
+ * If the subquery is variant, than return
+ * VARIANT. Otherwise, if we have an expression
+ * subquery and no correlated CRs we are going
+ * to materialize it, so it is QUERY_INVARIANT.
+ * Otherwise, SCAN_INVARIANT.
+ */
+ if (isInvariant())
+ {
+ if (!hasCorrelatedCRs() &&
+ (subqueryType == EXPRESSION_SUBQUERY))
+ {
+ return Qualifier.QUERY_INVARIANT;
+ }
+ else
+ {
+ return Qualifier.SCAN_INVARIANT;
+ }
+ }
+ else
+ {
+ return Qualifier.VARIANT;
+ }
+ }
+
+ /**
+ * Do code generation for this subquery.
+ *
+ * @param expressionBuilder The ExpressionClassBuilder for the class being built
+ * @param mbex The method the expression will go into
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateExpression(
+ ExpressionClassBuilder expressionBuilder,
+ MethodBuilder mbex)
+ throws StandardException
+ {
+ CompilerContext cc = getCompilerContext();
+ String resultSetString;
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // Subqueries should not appear in Filter expressions. We should get here
+ // only if we're compiling a query. That means that our class builder
+ // is an activation builder. If we ever allow subqueries in filters, we'll
+ // have to revisit this code.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(expressionBuilder instanceof ActivationClassBuilder,
+ "Expecting an ActivationClassBuilder");
+ }
+
+ ActivationClassBuilder acb = (ActivationClassBuilder) expressionBuilder;
+ /* Reuse generated code, where possible */
+
+ /* Generate the appropriate (Any or Once) ResultSet */
+ if (subqueryType == EXPRESSION_SUBQUERY)
+ {
+ resultSetString = "getOnceResultSet";
+ }
+ else
+ {
+ resultSetString = "getAnyResultSet";
+ }
+
+ // Get cost estimate for underlying subquery
+ CostEstimate costEstimate = resultSet.getFinalCostEstimate();
+
+ /* Generate a new method. It's only used within the other
+ * exprFuns, so it could be private. but since we don't
+ * generate the right bytecodes to invoke private methods,
+ * we just make it protected. This generated class won't
+ * have any subclasses, certainly! (nat 12/97)
+ */
+ String subqueryTypeString =
+ getTypeCompiler().interfaceName();
+ MethodBuilder mb = acb.newGeneratedFun(subqueryTypeString, Modifier.PROTECTED);
+
+ /* Declare the field to hold the suquery's ResultSet tree */
+ LocalField rsFieldLF = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.NoPutResultSet);
+
+ ResultSetNode subNode = null;
+
+ if (!isMaterializable())
+ {
+ MethodBuilder executeMB = acb.getExecuteMethod();
+ if (pushedNewPredicate && (! hasCorrelatedCRs()))
+ {
+ /* We try to materialize the subquery if it can fit in the memory. We
+ * evaluate the subquery first. If the result set fits in the memory,
+ * we replace the resultset with in-memory unions of row result sets.
+ * We do this trick by replacing the child result with a new node --
+ * MaterializeSubqueryNode, which essentially generates the suitable
+ * code to materialize the subquery if possible. This may have big
+ * performance improvement. See beetle 4373.
+ */
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT(resultSet instanceof ProjectRestrictNode,
+ "resultSet expected to be a ProjectRestrictNode!");
+ }
+ subNode = ((ProjectRestrictNode) resultSet).getChildResult();
+ LocalField subRS = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.NoPutResultSet);
+ mb.getField(subRS);
+ mb.conditionalIfNull();
+
+ ResultSetNode materialSubNode = new MaterializeSubqueryNode(subRS);
+ ((ProjectRestrictNode) resultSet).setChildResult(materialSubNode);
+
+ /* Evaluate subquery resultset here first. Next time when we come to
+ * this subquery it may be replaced by a bunch of unions of rows.
+ */
+ subNode.generate(acb, mb);
+ mb.startElseCode();
+ mb.getField(subRS);
+ mb.completeConditional();
+
+ mb.putField(subRS);
+ mb.endStatement();
+
+ executeMB.pushNull( ClassName.NoPutResultSet);
+ executeMB.putField(subRS);
+ executeMB.endStatement();
+ }
+
+ executeMB.pushNull( ClassName.NoPutResultSet);
+ executeMB.putField(rsFieldLF);
+ executeMB.endStatement();
+
+ // now we fill in the body of the conditional
+ mb.getField(rsFieldLF);
+ mb.conditionalIfNull();
+ }
+
+ acb.pushGetResultSetFactoryExpression(mb);
+
+ // start of args
+ int nargs;
+
+ /* Inside here is where subquery could already have been materialized. 4373
+ */
+ resultSet.generate(acb, mb);
+
+ /* Get the next ResultSet #, so that we can number the subquery's
+ * empty row ResultColumnList and Once/Any ResultSet.
+ */
+ int subqResultSetNumber = cc.getNextResultSetNumber();
+
+ /* We will be reusing the RCL from the subquery's ResultSet for the
+ * empty row function. We need to reset the resultSetNumber in the
+ * RCL, before we generate that function. Now that we've called
+ * generate() on the subquery's ResultSet, we can reset that
+ * resultSetNumber.
+ */
+ resultSet.getResultColumns().setResultSetNumber(subqResultSetNumber);
+
+ acb.pushThisAsActivation(mb);
+
+ /* Generate code for empty row */
+ resultSet.getResultColumns().generateNulls(acb, mb);
+
+ /*
+ * arg1: suqueryExpress - Expression for subquery's
+ * ResultSet
+ * arg2: Activation
+ * arg3: Method to generate Row with null(s) if subquery
+ * Result Set is empty
+ */
+ if (subqueryType == EXPRESSION_SUBQUERY)
+ {
+ int cardinalityCheck;
+
+ /* No need to do sort if subquery began life as a distinct expression subquery.
+ * (We simply check for a single unique value at execution time.)
+ * No need for cardinality check if we know that underlying
+ * ResultSet can contain at most 1 row.
+ * RESOLVE - Not necessary if we know we
+ * are getting a single row because of a unique index.
+ */
+ if (distinctExpression)
+ {
+ cardinalityCheck = OnceResultSet.UNIQUE_CARDINALITY_CHECK;
+ }
+ else if (resultSet.returnsAtMostOneRow())
+ {
+ cardinalityCheck = OnceResultSet.NO_CARDINALITY_CHECK;
+ }
+ else
+ {
+ cardinalityCheck = OnceResultSet.DO_CARDINALITY_CHECK;
+ }
+
+ /* arg4: int - whether or not cardinality check is required
+ * DO_CARDINALITY_CHECK - required
+ * NO_CARDINALITY_CHECK - not required
+ * UNIQUE_CARDINALITY_CHECK - verify single
+ * unique value
+ */
+ mb.push(cardinalityCheck);
+ nargs = 9;
+
+ } else {
+ nargs = 8;
+ }
+
+ mb.push(subqResultSetNumber);
+ mb.push(subqueryNumber);
+ mb.push(pointOfAttachment);
+ mb.push(costEstimate.rowCount());
+ mb.push(costEstimate.getEstimatedCost());
+
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, resultSetString, ClassName.NoPutResultSet, nargs);
+
+
+
+ /* Fill in the body of the method
+ * generates the following.
+ * (NOTE: the close() method only generated for
+ * materialized subqueries. All other subqueries
+ * closed by top result set in the query.):
+ *
+ * NoPutResultSet rsFieldX;
+ * {
+ * <Datatype interface> col;
+ * ExecRow r;
+ * rsFieldX = (rsFieldX == null) ? outerRSCall() : rsFieldX; // <== NONmaterialized specific
+ * rsFieldX.openCore();
+ * r = rsFieldX.getNextRowCore();
+ * col = (<Datatype interface>) r.getColumn(1);
+ * return col;
+ * }
+ *
+ * MATERIALIZED:
+ * NoPutResultSet rsFieldX;
+ * {
+ * <Datatype interface> col;
+ * ExecRow r;
+ * rsFieldX = outerRSCall();
+ * rsFieldX.openCore();
+ * r = rsFieldX.getNextRowCore();
+ * col = (<Datatype interface>) r.getColumn(1);
+ * rsFieldX.close(); // <== materialized specific
+ * return col;
+ * }
+ * and adds it to exprFun
+ */
+
+ /* Generate the declarations */ // PUSHCOMPILE
+ //VariableDeclaration colVar = mb.addVariableDeclaration(subqueryTypeString);
+ //VariableDeclaration rVar = mb.addVariableDeclaration(ClassName.ExecRow);
+
+ if (!isMaterializable())
+ {
+ /* put it back
+ */
+ if (pushedNewPredicate && (! hasCorrelatedCRs()))
+ ((ProjectRestrictNode) resultSet).setChildResult(subNode);
+
+ // now we fill in the body of the conditional
+ mb.startElseCode();
+ mb.getField(rsFieldLF);
+ mb.completeConditional();
+ }
+
+ mb.putField(rsFieldLF);
+ mb.endStatement();
+
+ /* rs.openCore() */
+ mb.getField(rsFieldLF);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "openCore", "void", 0);
+
+ /* r = rs.next() */
+ mb.getField(rsFieldLF);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getNextRowCore", ClassName.ExecRow, 0);
+ //mb.putVariable(rVar);
+ //mb.endStatement();
+
+ /* col = (<Datatype interface>) r.getColumn(1) */
+ //mb.getVariable(rVar);
+ mb.push(1); // both the Row interface and columnId are 1-based
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "getColumn", ClassName.DataValueDescriptor, 1);
+ mb.cast(subqueryTypeString);
+ //mb.putVariable(colVar);
+ //mb.endStatement();
+
+ /* Only generate the close() method for materialized
+ * subqueries. All others will be closed when the
+ * close() method is called on the top ResultSet.
+ */
+ if (isMaterializable())
+ {
+ /* rs.close() */
+ mb.getField(rsFieldLF);
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ResultSet, "close", "void", 0);
+ }
+
+ /* return col */
+ //mb.getVariable(colVar);
+ mb.methodReturn();
+ mb.complete();
+
+ /*
+ ** If we have an expression subquery, then we
+ ** can materialize it if it has no correlated
+ ** column references and is invariant.
+ */
+ if (isMaterializable())
+ {
+ LocalField lf = generateMaterialization(acb, mb, subqueryTypeString);
+ mbex.getField(lf);
+
+ } else {
+ /* Generate the call to the new method */
+ mbex.pushThis();
+ mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), subqueryTypeString, 0);
+ }
+ }
+
+ /*
+ ** Materialize the subquery in question. Given the expression
+ ** that represents the subquery, this returns fieldX where
+ ** fieldX is set up as follows:
+ **
+ ** private ... fieldX
+ **
+ ** execute()
+ ** {
+ ** fieldX = <subqueryExpression>
+ ** ...
+ ** }
+ **
+ ** So we wind up evaluating the subquery when we start
+ ** execution. Obviously, it is absolutely necessary that
+ ** the subquery is invariant and has no correlations
+ ** for this to work.
+ **
+ ** Ideally we wouldn't evaluate the expression subquery
+ ** until we know we need to, but because we are marking
+ ** this expression subquery as pushable, we must evaluate
+ ** it up front because it might wind up as a qualification,
+ ** and we cannot execute a subquery in the store as a
+ ** qualification because the store executes qualifications
+ ** while holding a latch.
+ **
+ ** @param acb
+ ** @param type
+ ** @param subqueryExpression
+ */
+ private LocalField generateMaterialization(
+ ActivationClassBuilder acb,
+ MethodBuilder mbsq,
+ String type)
+ {
+ MethodBuilder mb = acb.executeMethod;
+
+ // declare field
+ LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, type);
+
+ /* Generate the call to the new method */
+ mb.pushThis();
+ mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mbsq.getName(), type, 0);
+
+ // generate: field = value (value is on stack)
+ mb.putField(field);
+ mb.endStatement();
+
+ return field;
+ }
+
+ /* Private methods on private variables */
+ private BooleanConstantNode getTrueNode()
+ throws StandardException
+ {
+ if (trueNode == null)
+ {
+ trueNode = (BooleanConstantNode) getNodeFactory().getNode(
+ C_NodeTypes.BOOLEAN_CONSTANT_NODE,
+ Boolean.TRUE,
+ getContextManager());
+ }
+ return trueNode;
+ }
+
+ /**
+ * Accept a visitor, and call v.visit()
+ * on child nodes as necessary.
+ *
+ * @param v the visitor
+ *
+ * @exception StandardException on error
+ */
+ public Visitable accept(Visitor v)
+ throws StandardException
+ {
+ Visitable returnNode = v.visit(this);
+
+ /* shortcut if we've already done it
+ */
+ if ((v instanceof HasCorrelatedCRsVisitor) && doneCorrelationCheck)
+ {
+ ((HasCorrelatedCRsVisitor) v).setHasCorrelatedCRs(foundCorrelation);
+ return returnNode;
+ }
+
+ if (v.skipChildren(this))
+ {
+ return returnNode;
+ }
+
+ if (resultSet != null && !v.stopTraversal())
+ {
+ resultSet = (ResultSetNode)resultSet.accept(v);
+ }
+
+ if (leftOperand != null && !v.stopTraversal())
+ {
+ leftOperand = (ValueNode)leftOperand.accept(v);
+ }
+ return returnNode;
+ }
+
+ private boolean isIN()
+ {
+ return subqueryType == IN_SUBQUERY;
+ }
+
+ private boolean isNOT_IN()
+ {
+ return subqueryType == NOT_IN_SUBQUERY;
+ }
+
+ private boolean isANY()
+ {
+ switch (subqueryType)
+ {
+ case EQ_ANY_SUBQUERY:
+ case NE_ANY_SUBQUERY:
+ case LE_ANY_SUBQUERY:
+ case LT_ANY_SUBQUERY:
+ case GE_ANY_SUBQUERY:
+ case GT_ANY_SUBQUERY:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private boolean isALL()
+ {
+ switch (subqueryType)
+ {
+ case EQ_ALL_SUBQUERY:
+ case NE_ALL_SUBQUERY:
+ case LE_ALL_SUBQUERY:
+ case LT_ALL_SUBQUERY:
+ case GE_ALL_SUBQUERY:
+ case GT_ALL_SUBQUERY:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private boolean isEXISTS()
+ {
+ return subqueryType == EXISTS_SUBQUERY;
+ }
+
+ private boolean isNOT_EXISTS()
+ {
+ return subqueryType == NOT_EXISTS_SUBQUERY;
+ }
+
+ /**
+ * Convert this IN/ANY subquery, which is known to return at most 1 row,
+ * to an equivalent expression subquery.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+ private void changeToCorrespondingExpressionType()
+ throws StandardException
+ {
+ BinaryOperatorNode bcon = null;
+
+ switch (subqueryType)
+ {
+ case EQ_ANY_SUBQUERY:
+ case IN_SUBQUERY:
+ bcon = (BinaryOperatorNode) getNodeFactory().getNode(
+ C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,
+ leftOperand,
+ this,
+ getContextManager());
+ break;
+
+ case NE_ANY_SUBQUERY:
+ bcon = (BinaryOperatorNode) getNodeFactory().getNode(
+ C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE,
+ leftOperand,
+ this,
+ getContextManager());
+ break;
+
+ case LE_ANY_SUBQUERY:
+ bcon = (BinaryOperatorNode) getNodeFactory().getNode(
+ C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE,
+ leftOperand,
+ this,
+ getContextManager());
+ break;
+
+ case LT_ANY_SUBQUERY:
+ bcon = (BinaryOperatorNode) getNodeFactory().getNode(
+ C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE,
+ leftOperand,
+ this,
+ getContextManager());
+ break;
+
+ case GE_ANY_SUBQUERY:
+ bcon = (BinaryOperatorNode) getNodeFactory().getNode(
+ C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE,
+ leftOperand,
+ this,
+ getContextManager());
+ break;
+
+ case GT_ANY_SUBQUERY:
+ bcon = (BinaryOperatorNode) getNodeFactory().getNode(
+ C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE,
+ leftOperand,
+ this,
+ getContextManager());
+ break;
+ }
+
+ // clean up the state of the tree to reflect a bound expression subquery
+ subqueryType = EXPRESSION_SUBQUERY;
+ setDataTypeServices(resultSet.getResultColumns());
+
+ parentComparisonOperator = (BinaryComparisonOperatorNode) bcon;
+ /* Set type info for the operator node */
+ parentComparisonOperator.bindComparisonOperator();
+ leftOperand = null;
+ }
+
+ private void setDataTypeServices(ResultColumnList resultColumns)
+ throws StandardException
+ {
+ DataTypeDescriptor dts;
+
+ /* Set the result type for this subquery (must be nullable).
+ * Quantified predicates will return boolean.
+ * However, the return type of the subquery's result list will
+ * probably not be boolean at this point, because we do not
+ * transform the subquery (other than EXISTS) into
+ * (select true/false ...) until preprocess(). So, we force
+ * the return type to boolean.
+ */
+ if (subqueryType == EXPRESSION_SUBQUERY)
+ {
+ dts = ((ResultColumn) resultColumns.elementAt(0)).getTypeServices();
+ }
+ else
+ {
+ dts = getTrueNode().getTypeServices();
+ }
+
+ /* If datatype of underlying resultSet is nullable, reuse it, otherwise
+ * we need to generate a new one.
+ */
+ if (! dts.isNullable())
+ {
+ dts = new DataTypeDescriptor(dts, true);
+ }
+ setType(dts);
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SumAvgAggregateDefinition.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SumAvgAggregateDefinition.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SumAvgAggregateDefinition.java Fri Sep 24 10:33:20 2004
@@ -1,146 +1,146 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 2001, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-import org.apache.derby.iapi.services.context.ContextService;
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.impl.sql.execute.SumAggregator;
-import org.apache.derby.impl.sql.execute.AvgAggregator;
-
-import org.apache.derby.catalog.TypeDescriptor;
-import org.apache.derby.iapi.types.TypeId;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
-
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-
-import org.apache.derby.iapi.error.StandardException;
-import org.apache.derby.iapi.reference.ClassName;
-
-/**
- * Defintion for the SUM()/AVG() aggregates.
- *
- * @author jamie
- */
-public class SumAvgAggregateDefinition
- implements AggregateDefinition
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2001_2004;
- private boolean isSum;
- /**
- * Niladic constructor. Does nothing. For ease
- * Of use, only.
- */
- public SumAvgAggregateDefinition() { super(); }
-
- /**
- * Determines the result datatype. Accept NumberDataValues
- * only.
- * <P>
- * <I>Note</I>: In the future you should be able to do
- * a sum user data types. One option would be to run
- * sum on anything that implements plus(). In which
- * case avg() would need divide().
- *
- * @param the input type, either a user type or a java.lang object
- * @param implementsInterface the interface it implements
- *
- * @return the output Class (null if cannot operate on
- * value expression of this type.
- */
- public final TypeDescriptor getAggregator(TypeDescriptor inputType,
- StringBuffer aggregatorClass)
- {
- try
- {
- LanguageConnectionContext lcc = (LanguageConnectionContext)
- ContextService.getContext(LanguageConnectionContext.CONTEXT_ID);
-
- DataTypeDescriptor dts = new DataTypeDescriptor( (DataTypeDescriptor)inputType, inputType.isNullable());
- TypeId compType = dts.getTypeId();
-
- CompilerContext cc = (CompilerContext)
- ContextService.getContext(CompilerContext.CONTEXT_ID);
- TypeCompilerFactory tcf = cc.getTypeCompilerFactory();
- TypeCompiler tc = tcf.getTypeCompiler(compType);
-
- /*
- ** If the class implements NumberDataValue, then we
- ** are in business. Return type is same as input
- ** type.
- */
- if (compType.isNumericTypeId())
- {
- aggregatorClass.append(getAggregatorClassName());
-
- DataTypeDescriptor outDts = tc.resolveArithmeticOperation(
- dts, dts, getOperator());
- /*
- ** SUM and AVG may return null
- */
- outDts.setNullability(true);
- return outDts;
- }
- }
- catch (StandardException e)
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.THROWASSERT("Unexpected exception " + e);
- }
- }
-
- return null;
- }
-
- /**
- * Return the aggregator class.
- *
- * @return SumAggregator.CLASS_NAME/AvgAggregator.CLASS_NAME
- */
- private String getAggregatorClassName()
- {
- if ( isSum )
- return ClassName.SumAggregator;
- else
- return ClassName.AvgAggregator;
- }
-
- /**
- * Return the arithmetic operator corresponding
- * to this operation.
- *
- * @return TypeCompiler.SUM_OP /TypeCompiler.AVG_OP
- */
- protected String getOperator()
- {
- if ( isSum )
- return TypeCompiler.SUM_OP;
- else
- return TypeCompiler.AVG_OP;
- }
-
- /**
- * This is set by the parser.
- */
- public final void setSumOrAvg(boolean isSum)
- {
- this.isSum = isSum;
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 2001, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.impl.sql.execute.SumAggregator;
+import org.apache.derby.impl.sql.execute.AvgAggregator;
+
+import org.apache.derby.catalog.TypeDescriptor;
+import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import org.apache.derby.iapi.sql.compile.TypeCompiler;
+import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
+
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.reference.ClassName;
+
+/**
+ * Defintion for the SUM()/AVG() aggregates.
+ *
+ * @author jamie
+ */
+public class SumAvgAggregateDefinition
+ implements AggregateDefinition
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2001_2004;
+ private boolean isSum;
+ /**
+ * Niladic constructor. Does nothing. For ease
+ * Of use, only.
+ */
+ public SumAvgAggregateDefinition() { super(); }
+
+ /**
+ * Determines the result datatype. Accept NumberDataValues
+ * only.
+ * <P>
+ * <I>Note</I>: In the future you should be able to do
+ * a sum user data types. One option would be to run
+ * sum on anything that implements plus(). In which
+ * case avg() would need divide().
+ *
+ * @param the input type, either a user type or a java.lang object
+ * @param implementsInterface the interface it implements
+ *
+ * @return the output Class (null if cannot operate on
+ * value expression of this type.
+ */
+ public final TypeDescriptor getAggregator(TypeDescriptor inputType,
+ StringBuffer aggregatorClass)
+ {
+ try
+ {
+ LanguageConnectionContext lcc = (LanguageConnectionContext)
+ ContextService.getContext(LanguageConnectionContext.CONTEXT_ID);
+
+ DataTypeDescriptor dts = new DataTypeDescriptor( (DataTypeDescriptor)inputType, inputType.isNullable());
+ TypeId compType = dts.getTypeId();
+
+ CompilerContext cc = (CompilerContext)
+ ContextService.getContext(CompilerContext.CONTEXT_ID);
+ TypeCompilerFactory tcf = cc.getTypeCompilerFactory();
+ TypeCompiler tc = tcf.getTypeCompiler(compType);
+
+ /*
+ ** If the class implements NumberDataValue, then we
+ ** are in business. Return type is same as input
+ ** type.
+ */
+ if (compType.isNumericTypeId())
+ {
+ aggregatorClass.append(getAggregatorClassName());
+
+ DataTypeDescriptor outDts = tc.resolveArithmeticOperation(
+ dts, dts, getOperator());
+ /*
+ ** SUM and AVG may return null
+ */
+ outDts.setNullability(true);
+ return outDts;
+ }
+ }
+ catch (StandardException e)
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.THROWASSERT("Unexpected exception " + e);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the aggregator class.
+ *
+ * @return SumAggregator.CLASS_NAME/AvgAggregator.CLASS_NAME
+ */
+ private String getAggregatorClassName()
+ {
+ if ( isSum )
+ return ClassName.SumAggregator;
+ else
+ return ClassName.AvgAggregator;
+ }
+
+ /**
+ * Return the arithmetic operator corresponding
+ * to this operation.
+ *
+ * @return TypeCompiler.SUM_OP /TypeCompiler.AVG_OP
+ */
+ protected String getOperator()
+ {
+ if ( isSum )
+ return TypeCompiler.SUM_OP;
+ else
+ return TypeCompiler.AVG_OP;
+ }
+
+ /**
+ * This is set by the parser.
+ */
+ public final void setSumOrAvg(boolean isSum)
+ {
+ this.isSum = isSum;
+ }
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java Fri Sep 24 10:33:20 2004
@@ -1,977 +1,977 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-import org.apache.derby.iapi.sql.compile.C_NodeTypes;
-
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
-import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
-import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
-
-import org.apache.derby.iapi.sql.depend.DependencyManager;
-import org.apache.derby.iapi.sql.depend.ProviderInfo;
-import org.apache.derby.iapi.sql.depend.ProviderList;
-
-import org.apache.derby.iapi.reference.SQLState;
-
-import org.apache.derby.impl.sql.execute.ColumnInfo;
-import org.apache.derby.impl.sql.execute.ConstraintInfo;
-import org.apache.derby.impl.sql.execute.ConstraintConstantAction;
-import org.apache.derby.impl.sql.execute.IndexConstantAction;
-
-import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;
-
-import org.apache.derby.catalog.UUID;
-
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * A TableElementList represents the list of columns and other table elements
- * such as constraints in a CREATE TABLE or ALTER TABLE statement.
- *
- * @author Jeff Lichtman
- */
-
-public class TableElementList extends QueryTreeNodeVector
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- int numColumns;
- TableDescriptor td;
-
- /**
- * Add a TableElementNode to this TableElementList
- *
- * @param tableElement The TableElementNode to add to this list
- *
- * @return Nothing
- */
-
- public void addTableElement(TableElementNode tableElement)
- {
- addElement(tableElement);
- if ((tableElement instanceof ColumnDefinitionNode) ||
- tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
- {
- numColumns++;
- }
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- StringBuffer buffer = new StringBuffer("");
-
- for (int index = 0; index < size(); index++)
- {
- buffer.append(elementAt(index).toString()).append("\n");
- }
-
- return buffer.toString();
- }
- else
- {
- return "";
- }
- }
-
- /**
- * Validate this TableElementList. This includes checking for
- * duplicate columns names, and checking that user types really exist.
- *
- * @param ddlStmt DDLStatementNode which contains this list
- * @param dd DataDictionary to use
- * @param td TableDescriptor for table, if existing table.
- *
- * @return None
- *
- * @exception StandardException Thrown on error
- */
- void validate(DDLStatementNode ddlStmt,
- DataDictionary dd,
- TableDescriptor td)
- throws StandardException
- {
- this.td = td;
- int numAutoCols = 0;
-
- int size = size();
- Hashtable columnHT = new Hashtable(size + 2, (float) .999);
- Hashtable constraintHT = new Hashtable(size + 2, (float) .999);
- //all the primary key/unique key constraints for this table
- Vector constraintsVector = new Vector();
-
- //special case for alter table (td is not null in case of alter table)
- if (td != null)
- {
- //In case of alter table, get the already existing primary key and unique
- //key constraints for this table. And then we will compare them with new
- //primary key/unique key constraint column lists.
- ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
- ConstraintDescriptor cd;
-
- if (cdl != null) //table does have some pre-existing constraints defined on it
- {
- for (int i=0; i<cdl.size();i++)
- {
- cd = cdl.elementAt(i);
- //if the constraint type is not primary key or unique key, ignore it.
- if (cd.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT ||
- cd.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)
- constraintsVector.addElement(cd);
- }
- }
- }
-
- int tableType = TableDescriptor.BASE_TABLE_TYPE;
- if (ddlStmt instanceof CreateTableNode)
- tableType = ((CreateTableNode)ddlStmt).tableType;
-
- for (int index = 0; index < size; index++)
- {
- TableElementNode tableElement = (TableElementNode) elementAt(index);
-
- if (tableElement instanceof ColumnDefinitionNode)
- {
- ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index);
- if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE &&
- (cdn.getDataTypeServices().getTypeId().isLongConcatableTypeId() ||
- cdn.getDataTypeServices().getTypeId().isUserDefinedTypeId()))
- {
- throw StandardException.newException(SQLState.LANG_LONG_DATA_TYPE_NOT_ALLOWED, cdn.getColumnName());
- }
- checkForDuplicateColumns(ddlStmt, columnHT, cdn.getColumnName());
- cdn.checkUserType(td);
- cdn.bindAndValidateDefault(dd, td);
-
- cdn.validateAutoincrement(dd, td, tableType);
-
- if (tableElement instanceof ModifyColumnNode)
- {
- ModifyColumnNode mcdn = (ModifyColumnNode)cdn;
- mcdn.checkExistingConstraints(td);
- } else if (cdn.isAutoincrementColumn())
- numAutoCols ++;
- }
- else if (tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
- {
- String colName = tableElement.getName();
- if (td.getColumnDescriptor(colName) == null)
- {
- throw StandardException.newException(
- SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
- colName,
- td.getQualifiedName());
- }
- break;
- }
-
- /* The rest of this method deals with validating constraints */
- if (! (tableElement.hasConstraint()))
- {
- continue;
- }
-
- ConstraintDefinitionNode cdn = (ConstraintDefinitionNode) tableElement;
-
- cdn.bind(ddlStmt, dd);
-
- //if constraint is primary key or unique key, add it to the vector
- if (cdn.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT ||
- cdn.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)
- {
- /* In case of create table, the vector can have only ConstraintDefinitionNode
- * elements. In case of alter table, it can have both ConstraintDefinitionNode
- * (for new constraints) and ConstraintDescriptor(for pre-existing constraints).
- */
-
- Object destConstraint;
- String destName = null;
- String[] destColumnNames = null;
-
- for (int i=0; i<constraintsVector.size();i++)
- {
-
- destConstraint = constraintsVector.elementAt(i);
- if (destConstraint instanceof ConstraintDefinitionNode)
- {
- ConstraintDefinitionNode destCDN = (ConstraintDefinitionNode)destConstraint;
- destName = destCDN.getConstraintMoniker();
- destColumnNames = destCDN.getColumnList().getColumnNames();
- }
- else if (destConstraint instanceof ConstraintDescriptor)
- {
- //will come here only for pre-existing constraints in case of alter table
- ConstraintDescriptor destCD = (ConstraintDescriptor)destConstraint;
- destName = destCD.getConstraintName();
- destColumnNames = destCD.getColumnDescriptors().getColumnNames();
- }
- //check if there are multiple constraints with same set of columns
- if (columnsMatch(cdn.getColumnList().getColumnNames(), destColumnNames))
- throw StandardException.newException(SQLState.LANG_MULTIPLE_CONSTRAINTS_WITH_SAME_COLUMNS,
- cdn.getConstraintMoniker(), destName);
- }
- constraintsVector.addElement(cdn);
- }
-
- /* Make sure that there are no duplicate constraint names in the list */
- if (cdn instanceof ConstraintDefinitionNode)
- checkForDuplicateConstraintNames(ddlStmt, constraintHT, cdn.getConstraintMoniker());
-
- /* Make sure that the constraint we are trying to drop exists */
- if (cdn.getConstraintType() == DataDictionary.DROP_CONSTRAINT)
- {
- /*
- ** If no schema descriptor, then must be an invalid
- ** schema name.
- */
-
- String dropConstraintName = cdn.getConstraintMoniker();
-
- if (dropConstraintName != null) {
-
- String dropSchemaName = cdn.getDropSchemaName();
-
- SchemaDescriptor sd = dropSchemaName == null ? td.getSchemaDescriptor() :
- getSchemaDescriptor(dropSchemaName);
-
- ConstraintDescriptor cd =
- dd.getConstraintDescriptorByName(
- td, sd, dropConstraintName,
- false);
- if (cd == null)
- {
- throw StandardException.newException(SQLState.LANG_DROP_NON_EXISTENT_CONSTRAINT,
- (sd.getSchemaName() + "."+ dropConstraintName),
- td.getQualifiedName());
- }
- /* Statement is dependendent on the ConstraintDescriptor */
- getCompilerContext().createDependency(cd);
- }
- }
-
- /* For primary/unique/unique keys, verify that the constraint's column
- * list contains valid columns and does not contain any duplicates
- * (Also, all columns in a primary key will be set to non-null,
- but only in Cloudscape mode. SQL and DB2 require explict NOT NULL.
- */
- if (cdn.hasPrimaryKeyConstraint() ||
- cdn.hasForeignKeyConstraint() ||
- cdn.hasUniqueKeyConstraint())
- {
- verifyUniqueColumnList(ddlStmt, cdn);
- /* Raise error if primary or unique key columns can be nullable. */
- if (cdn.hasPrimaryKeyConstraint() || cdn.hasUniqueKeyConstraint())
- {
- setColumnListToNotNull(cdn, td);
- }
- }
- }
-
- /* Can have only one autoincrement column in DB2 mode */
- if (numAutoCols > 1)
- throw StandardException.newException(SQLState.LANG_MULTIPLE_AUTOINCREMENT_COLUMNS);
-
- }
-
- /**
- * Count the number of constraints of the specified type.
- *
- * @param constraintType The constraint type to search for.
- *
- * @return int The number of constraints of the specified type.
- */
- public int countConstraints(int constraintType)
- {
- int numConstraints = 0;
- int size = size();
-
- for (int index = 0; index < size; index++)
- {
- ConstraintDefinitionNode cdn;
- TableElementNode element = (TableElementNode) elementAt(index);
-
- if (! (element instanceof ConstraintDefinitionNode))
- {
- continue;
- }
-
- cdn = (ConstraintDefinitionNode) element;
-
- if (constraintType == cdn.getConstraintType())
- {
- numConstraints++;
- }
- }
-
- return numConstraints;
- }
-
- /**
- * Count the number of columns.
- *
- * @return int The number of columns.
- */
- public int countNumberOfColumns()
- {
- return numColumns;
- }
-
- /**
- * Fill in the ColumnInfo[] for this table element list.
- *
- * @param colInfos The ColumnInfo[] to be filled in.
- *
- * @return int The number of constraints in the create table.
- */
- public int genColumnInfos(ColumnInfo[] colInfos)
- {
- int numConstraints = 0;
- int size = size();
-
- for (int index = 0; index < size; index++)
- {
- if (((TableElementNode) elementAt(index)).getElementType() == TableElementNode.AT_DROP_COLUMN)
- {
- colInfos[index] = new ColumnInfo(
- ((TableElementNode) elementAt(index)).getName(),
- null, null, null, null, null,
- ColumnInfo.DROP, 0, 0);
- break;
- }
-
- if (! (elementAt(index) instanceof ColumnDefinitionNode))
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT( elementAt(index) instanceof ConstraintDefinitionNode,
- "elementAt(index) expected to be instanceof " +
- "ConstraintDefinitionNode");
- }
-
- /* Remember how many constraints that we've seen */
- numConstraints++;
- continue;
- }
-
- ColumnDefinitionNode coldef = (ColumnDefinitionNode) elementAt(index);
-
- colInfos[index - numConstraints] =
- new ColumnInfo(coldef.getColumnName(),
- coldef.getDataTypeServices(),
- coldef.getDefaultValue(),
- coldef.getDefaultInfo(),
- (UUID) null,
- coldef.getOldDefaultUUID(),
- coldef.getAction(),
- (coldef.isAutoincrementColumn() ?
- coldef.getAutoincrementStart() : 0),
- (coldef.isAutoincrementColumn() ?
- coldef.getAutoincrementIncrement() : 0));
-
- /* Remember how many constraints that we've seen */
- if (coldef.hasConstraint())
- {
- numConstraints++;
- }
- }
-
- return numConstraints;
- }
- /**
- * Append goobered up ResultColumns to the table's RCL.
- * This is useful for binding check constraints for CREATE and ALTER TABLE.
- *
- * @param table The table in question.
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown on error
- */
- public void appendNewColumnsToRCL(FromBaseTable table)
- throws StandardException
- {
- int size = size();
- ResultColumnList rcl = table.getResultColumns();
- TableName exposedName = table.getTableName();
-
- for (int index = 0; index < size; index++)
- {
- if (elementAt(index) instanceof ColumnDefinitionNode)
- {
- ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index);
- ResultColumn resultColumn;
- ValueNode valueNode;
-
- /* Build a ResultColumn/BaseColumnNode pair for the column */
- valueNode = (ValueNode) getNodeFactory().getNode(
- C_NodeTypes.BASE_COLUMN_NODE,
- cdn.getColumnName(),
- exposedName,
- cdn.getDataTypeServices(),
- getContextManager());
-
- resultColumn = (ResultColumn) getNodeFactory().getNode(
- C_NodeTypes.RESULT_COLUMN,
- cdn.getDataTypeServices(),
- valueNode,
- getContextManager());
- resultColumn.setName(cdn.getColumnName());
- rcl.addElement(resultColumn);
- }
- }
- }
-
- /**
- * Bind and validate all of the check constraints in this list against
- * the specified FromList.
- *
- * @param FromList The FromList in question.
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown on error
- */
- void bindAndValidateCheckConstraints(FromList fromList)
- throws StandardException
- {
- CompilerContext cc;
- FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
- int size = size();
-
- cc = getCompilerContext();
-
- Vector aggregateVector = new Vector();
-
- for (int index = 0; index < size; index++)
- {
- ConstraintDefinitionNode cdn;
- TableElementNode element = (TableElementNode) elementAt(index);
- ValueNode checkTree;
-
- if (! (element instanceof ConstraintDefinitionNode))
- {
- continue;
- }
-
- cdn = (ConstraintDefinitionNode) element;
-
- if (cdn.getConstraintType() != DataDictionary.CHECK_CONSTRAINT)
- {
- continue;
- }
-
- checkTree = cdn.getCheckCondition();
-
- // bind the check condition
- // verify that it evaluates to a boolean
- final int previousReliability = cc.getReliability();
- try
- {
- /* Each check constraint can have its own set of dependencies.
- * These dependencies need to be shared with the prepared
- * statement as well. We create a new auxiliary provider list
- * for the check constraint, "push" it on the compiler context
- * by swapping it with the current auxiliary provider list
- * and the "pop" it when we're done by restoring the old
- * auxiliary provider list.
- */
- ProviderList apl = new ProviderList();
-
- ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
- cc.setCurrentAuxiliaryProviderList(apl);
-
- // Tell the compiler context to only allow deterministic nodes
- cc.setReliability( CompilerContext.CHECK_CONSTRAINT );
- checkTree = checkTree.bindExpression(fromList, (SubqueryList) null,
- aggregateVector);
-
- // no aggregates, please
- if (aggregateVector.size() != 0)
- {
- throw StandardException.newException(SQLState.LANG_INVALID_CHECK_CONSTRAINT, cdn.getConstraintText());
- }
-
- checkTree = checkTree.checkIsBoolean();
- cdn.setCheckCondition(checkTree);
-
- /* Save the APL off in the constraint node */
- if (apl.size() > 0)
- {
- cdn.setAuxiliaryProviderList(apl);
- }
-
- // Restore the previous AuxiliaryProviderList
- cc.setCurrentAuxiliaryProviderList(prevAPL);
- }
- finally
- {
- cc.setReliability(previousReliability);
- }
-
- /* We have a valid check constraint, now build an array of
- * 1-based columnIds that the constraint references.
- */
- ResultColumnList rcl = table.getResultColumns();
- int numReferenced = rcl.countReferencedColumns();
- int[] checkColumnReferences = new int[numReferenced];
-
- rcl.recordColumnReferences(checkColumnReferences, 1);
- cdn.setCheckColumnReferences(checkColumnReferences);
-
- /* Now we build a list with only the referenced columns and
- * copy it to the cdn. Thus we can build the array of
- * column names for the referenced columns during generate().
- */
- ResultColumnList refRCL =
- (ResultColumnList) getNodeFactory().getNode(
- C_NodeTypes.RESULT_COLUMN_LIST,
- getContextManager());
- rcl.copyReferencedColumnsToNewList(refRCL);
-
- /* A column check constraint can only refer to that column. If this is a
- * column constraint, we should have an RCL with that column
- */
- if (cdn.getColumnList() != null)
- {
- String colName = ((ResultColumn)(cdn.getColumnList().elementAt(0))).getName();
- if (numReferenced > 1 ||
- !colName.equals(((ResultColumn)(refRCL.elementAt(0))).getName()))
- throw StandardException.newException(SQLState.LANG_DB2_INVALID_CHECK_CONSTRAINT, colName);
-
- }
- cdn.setColumnList(refRCL);
-
- /* Clear the column references in the RCL so each check constraint
- * starts with a clean list.
- */
- rcl.clearColumnReferences();
- }
- }
-
- /**
- * Fill in the ConstraintConstantAction[] for this create/alter table.
- *
- * @param conActions The ConstraintConstantAction[] to be filled in.
- * @param tableName The name of the Table being created.
- * @param sd The schema for that table.
- * @param dd The DataDictionary
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown on failure
- */
- void genConstraintActions(
- ConstraintConstantAction[] conActions,
- String tableName,
- SchemaDescriptor tableSd,
- DataDictionary dd)
- throws StandardException
- {
- int size = size();
- int conActionIndex = 0;
- for (int index = 0; index < size; index++)
- {
- String[] columnNames = null;
- String generatedConstraintName;
- TableElementNode ten = (TableElementNode) elementAt(index);
- IndexConstantAction indexAction = null;
-
- if (! ten.hasConstraint())
- {
- continue;
- }
-
- if (ten instanceof ColumnDefinitionNode)
- {
- continue;
- }
-
- ConstraintDefinitionNode constraintDN = (ConstraintDefinitionNode) ten;
-
- if (constraintDN.getColumnList() != null)
- {
- columnNames = new String[constraintDN.getColumnList().size()];
- constraintDN.getColumnList().exportNames(columnNames);
- }
-
- int constraintType = constraintDN.getConstraintType();
- String constraintText = constraintDN.getConstraintText();
-
- /*
- ** If the constraint is not named (e.g.
- ** create table x (x int primary key)), then
- ** the constraintSd is the same as the table.
- */
- String constraintName = constraintDN.getConstraintMoniker();
-
- /* At execution time, we will generate a unique name for the backing
- * index (for CREATE CONSTRAINT) and we will look up the conglomerate
- * name (for DROP CONSTRAINT).
- */
- if (constraintDN.requiresBackingIndex())
- {
- indexAction = genIndexAction(constraintDN.requiresUniqueIndex(),
- null, constraintDN,
- columnNames, true, tableSd, tableName,
- constraintType, dd);
- }
-
- if (constraintType == DataDictionary.DROP_CONSTRAINT)
- {
- conActions[conActionIndex] =
- getGenericConstantActionFactory().
- getDropConstraintConstantAction(
- constraintName,
- constraintDN.getDropSchemaName(), /// FiX
- tableName,
- td.getUUID(),
- tableSd.getSchemaName(),
- indexAction,
- constraintDN.getDropBehavior(),
- constraintDN.getVerifyType());
- }
- else
- {
- ProviderList apl = constraintDN.getAuxiliaryProviderList();
- ConstraintInfo refInfo = null;
- ProviderInfo[] providerInfos = null;
-
- if (constraintDN instanceof FKConstraintDefinitionNode)
- {
- refInfo = ((FKConstraintDefinitionNode)constraintDN).getReferencedConstraintInfo();
- }
-
- /* Create the ProviderInfos, if the constraint is dependent on any Providers */
- if (apl != null && apl.size() > 0)
- {
- /* Get all the dependencies for the current statement and transfer
- * them to this view.
- */
- DependencyManager dm = dd.getDependencyManager();
- providerInfos = dm.getPersistentProviderInfos(apl);
- }
- else
- {
- providerInfos = new ProviderInfo[0];
- }
-
- conActions[conActionIndex++] =
- getGenericConstantActionFactory().
- getCreateConstraintConstantAction(
- constraintName,
- constraintType,
- tableName,
- ((td != null) ? td.getUUID() : (UUID) null),
- tableSd.getSchemaName(),
- columnNames,
- indexAction,
- constraintText,
- true, // enabled
- refInfo,
- providerInfos);
- }
- }
- }
-
- //check if one array is same as another
- private boolean columnsMatch(String[] columnNames1, String[] columnNames2)
- throws StandardException
- {
- int srcCount, srcSize, destCount,destSize;
- boolean match = true;
-
- if (columnNames1.length != columnNames2.length)
- return false;
-
- srcSize = columnNames1.length;
- destSize = columnNames2.length;
-
- for (srcCount = 0; srcCount < srcSize; srcCount++)
- {
- match = false;
- for (destCount = 0; destCount < destSize; destCount++) {
- if (columnNames1[srcCount].equals(columnNames2[destCount])) {
- match = true;
- break;
- }
- }
- if (match == false)
- return false;
- }
-
- return true;
- }
-
- private IndexConstantAction genIndexAction(
- boolean isUnique,
- String indexName,
- ConstraintDefinitionNode cdn,
- String[] columnNames,
- boolean isConstraint,
- SchemaDescriptor sd,
- String tableName,
- int constraintType,
- DataDictionary dd)
- throws StandardException
- {
- if ( indexName == null ) { indexName = cdn.getBackingIndexName(dd); }
-
- if (constraintType == DataDictionary.DROP_CONSTRAINT)
- {
- return getGenericConstantActionFactory().getDropIndexConstantAction(
- null,
- indexName,
- tableName,
- sd.getSchemaName(),
- td.getUUID(),
- td.getHeapConglomerateId());
- }
- else
- {
- boolean[] isAscending = new boolean[columnNames.length];
- for (int i = 0; i < isAscending.length; i++)
- isAscending[i] = true;
- return getGenericConstantActionFactory().getCreateIndexConstantAction(
- isUnique,
- "BTREE", // indexType
- sd.getSchemaName(),
- indexName,
- tableName,
- ((td != null) ? td.getUUID() : (UUID) null),
- 0, // conglomId
- columnNames,
- isAscending,
- isConstraint,
- cdn.getBackingIndexUUID(),
- cdn.getProperties());
- }
- }
-
- /**
- * Check to make sure that there are no duplicate column names
- * in the list. (The comparison here is case sensitive.
- * The work of converting column names that are not quoted
- * identifiers to upper case is handled by the parser.)
- * RESOLVE: This check will also be performed by alter table.
- *
- * @param ddlStmt DDLStatementNode which contains this list
- * @param ht Hashtable for enforcing uniqueness.
- * @param colName Column name to check for.
- *
- * @return None
- *
- * @exception StandardException Thrown on error
- */
- private void checkForDuplicateColumns(DDLStatementNode ddlStmt,
- Hashtable ht,
- String colName)
- throws StandardException
- {
- Object object = ht.put(colName, colName);
- if (object != null)
- {
- /* RESOLVE - different error messages for create and alter table */
- if (ddlStmt instanceof CreateTableNode)
- {
- throw StandardException.newException(SQLState.LANG_DUPLICATE_COLUMN_NAME_CREATE, colName);
- }
- }
- }
-
- /**
- * Check to make sure that there are no duplicate constraint names
- * in the list. (The comparison here is case sensitive.
- * The work of converting column names that are not quoted
- * identifiers to upper case is handled by the parser.)
- * RESOLVE: This check will also be performed by alter table.
- *
- * @param ddlStmt DDLStatementNode which contains this list
- * @param outer The element to check against. Only check
- * TableElements that come after this one, since this
- * one has been checked against the TableElements
- * before it.
- *
- * @return None
- *
- * @exception StandardException Thrown on error
- */
- private void checkForDuplicateConstraintNames(DDLStatementNode ddlStmt,
- Hashtable ht,
- String constraintName)
- throws StandardException
- {
- if (constraintName == null)
- return;
-
- Object object = ht.put(constraintName, constraintName);
- if (object != null) {
-
- /* RESOLVE - different error messages for create and alter table */
- if (ddlStmt instanceof CreateTableNode)
- {
- /* RESOLVE - new error message */
- throw StandardException.newException(SQLState.LANG_DUPLICATE_CONSTRAINT_NAME_CREATE,
- constraintName);
- }
- }
- }
-
- /**
- * Verify that a primary/unique table constraint has a valid column list.
- * (All columns in table and no duplicates.)
- *
- * @param ddlStmt The outer DDLStatementNode
- * @param cdn The ConstraintDefinitionNode
- *
- * @return Nothing.
- *
- * @exception StandardException Thrown if the column list is invalid
- */
- private void verifyUniqueColumnList(DDLStatementNode ddlStmt,
- ConstraintDefinitionNode cdn)
- throws StandardException
- {
- String invalidColName;
-
- /* Verify that every column in the list appears in the table's list of columns */
- if (ddlStmt instanceof CreateTableNode)
- {
- invalidColName = cdn.getColumnList().verifyCreateConstraintColumnList(this);
- if (invalidColName != null)
- {
- throw StandardException.newException(SQLState.LANG_INVALID_CREATE_CONSTRAINT_COLUMN_LIST,
- ddlStmt.getRelativeName(),
- invalidColName);
- }
- }
- else
- {
- /* RESOLVE - alter table will need to get table descriptor */
- }
-
- /* Check the uniqueness of the column names within the list */
- invalidColName = cdn.getColumnList().verifyUniqueNames(false);
- if (invalidColName != null)
- {
- throw StandardException.newException(SQLState.LANG_DUPLICATE_CONSTRAINT_COLUMN_NAME, invalidColName);
- }
- }
-
- /**
- * Set all columns in that appear in a primary/unique key constraint in a create
- * table statement to NOT NULL in Cloudscape mode and raises an error in DB2 mode.
- *
- * @param cdn The ConstraintDefinitionNode
- * @param td TableDescriptor for the table
- *
- * @return Nothing.
- */
- private void setColumnListToNotNull(ConstraintDefinitionNode cdn, TableDescriptor td)
- throws StandardException
- {
- ResultColumnList rcl = cdn.getColumnList();
- int rclSize = rcl.size();
- for (int index = 0; index < rclSize; index++)
- {
- String colName = ((ResultColumn) rcl.elementAt(index)).getName();
-
- /* For ALTER TABLE ADD CONSTRAINT, make sure columns are not nullable for
- * primary and unique constraints.
- */
- if (td != null && cdn instanceof ConstraintDefinitionNode)
- {
- ColumnDescriptor cd = td.getColumnDescriptor(colName);
- if (cd != null && cd.getType().isNullable())
- throw StandardException.newException(SQLState.LANG_DB2_ADD_UNIQUE_OR_PRIMARY_KEY_ON_NULL_COLS, colName);
- }
-
- setColumnToNotNull(colName);
- }
- }
-
- /**
- * Set a column that appears in a primary/unique key constraint in
- * a create table statement to NOT NULL (but only in Cloudscape mode).
- *
- * @param colName The column name
- *
- * @return Nothing.
- */
- private void setColumnToNotNull(String colName) throws StandardException
- {
- int size = size();
-
- for (int index = 0; index < size; index++)
- {
- TableElementNode tableElement = (TableElementNode) elementAt(index);
-
- if (tableElement instanceof ColumnDefinitionNode)
- {
- ColumnDefinitionNode cdn = (ColumnDefinitionNode) tableElement;
- if (colName.equals(cdn.getColumnName()))
- {
- DataTypeDescriptor dtd = cdn.getDataTypeServices();
-
- if (dtd.isNullable())
- throw StandardException.newException(SQLState.LANG_DB2_ADD_UNIQUE_OR_PRIMARY_KEY_ON_NULL_COLS, colName);
- }
- }
- }
- }
-
- /**
- * Determine whether or not the parameter matches a column name in this list.
- *
- * @param colName The column name to search for.
- *
- * @return boolean Whether or not a match is found.
- */
- public boolean containsColumnName(String colName)
- {
- int size = size();
- for (int index = 0; index < size; index++)
- {
- TableElementNode tableElement = (TableElementNode) elementAt(index);
-
- if (tableElement instanceof ColumnDefinitionNode)
- {
- if (colName.equals(((ColumnDefinitionNode) tableElement).getName()))
- {
- return true;
- }
- }
- }
-
- return false;
- }
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
+
+import org.apache.derby.iapi.sql.depend.DependencyManager;
+import org.apache.derby.iapi.sql.depend.ProviderInfo;
+import org.apache.derby.iapi.sql.depend.ProviderList;
+
+import org.apache.derby.iapi.reference.SQLState;
+
+import org.apache.derby.impl.sql.execute.ColumnInfo;
+import org.apache.derby.impl.sql.execute.ConstraintInfo;
+import org.apache.derby.impl.sql.execute.ConstraintConstantAction;
+import org.apache.derby.impl.sql.execute.IndexConstantAction;
+
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;
+
+import org.apache.derby.catalog.UUID;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * A TableElementList represents the list of columns and other table elements
+ * such as constraints in a CREATE TABLE or ALTER TABLE statement.
+ *
+ * @author Jeff Lichtman
+ */
+
+public class TableElementList extends QueryTreeNodeVector
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ int numColumns;
+ TableDescriptor td;
+
+ /**
+ * Add a TableElementNode to this TableElementList
+ *
+ * @param tableElement The TableElementNode to add to this list
+ *
+ * @return Nothing
+ */
+
+ public void addTableElement(TableElementNode tableElement)
+ {
+ addElement(tableElement);
+ if ((tableElement instanceof ColumnDefinitionNode) ||
+ tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
+ {
+ numColumns++;
+ }
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ StringBuffer buffer = new StringBuffer("");
+
+ for (int index = 0; index < size(); index++)
+ {
+ buffer.append(elementAt(index).toString()).append("\n");
+ }
+
+ return buffer.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Validate this TableElementList. This includes checking for
+ * duplicate columns names, and checking that user types really exist.
+ *
+ * @param ddlStmt DDLStatementNode which contains this list
+ * @param dd DataDictionary to use
+ * @param td TableDescriptor for table, if existing table.
+ *
+ * @return None
+ *
+ * @exception StandardException Thrown on error
+ */
+ void validate(DDLStatementNode ddlStmt,
+ DataDictionary dd,
+ TableDescriptor td)
+ throws StandardException
+ {
+ this.td = td;
+ int numAutoCols = 0;
+
+ int size = size();
+ Hashtable columnHT = new Hashtable(size + 2, (float) .999);
+ Hashtable constraintHT = new Hashtable(size + 2, (float) .999);
+ //all the primary key/unique key constraints for this table
+ Vector constraintsVector = new Vector();
+
+ //special case for alter table (td is not null in case of alter table)
+ if (td != null)
+ {
+ //In case of alter table, get the already existing primary key and unique
+ //key constraints for this table. And then we will compare them with new
+ //primary key/unique key constraint column lists.
+ ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
+ ConstraintDescriptor cd;
+
+ if (cdl != null) //table does have some pre-existing constraints defined on it
+ {
+ for (int i=0; i<cdl.size();i++)
+ {
+ cd = cdl.elementAt(i);
+ //if the constraint type is not primary key or unique key, ignore it.
+ if (cd.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT ||
+ cd.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)
+ constraintsVector.addElement(cd);
+ }
+ }
+ }
+
+ int tableType = TableDescriptor.BASE_TABLE_TYPE;
+ if (ddlStmt instanceof CreateTableNode)
+ tableType = ((CreateTableNode)ddlStmt).tableType;
+
+ for (int index = 0; index < size; index++)
+ {
+ TableElementNode tableElement = (TableElementNode) elementAt(index);
+
+ if (tableElement instanceof ColumnDefinitionNode)
+ {
+ ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index);
+ if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE &&
+ (cdn.getDataTypeServices().getTypeId().isLongConcatableTypeId() ||
+ cdn.getDataTypeServices().getTypeId().isUserDefinedTypeId()))
+ {
+ throw StandardException.newException(SQLState.LANG_LONG_DATA_TYPE_NOT_ALLOWED, cdn.getColumnName());
+ }
+ checkForDuplicateColumns(ddlStmt, columnHT, cdn.getColumnName());
+ cdn.checkUserType(td);
+ cdn.bindAndValidateDefault(dd, td);
+
+ cdn.validateAutoincrement(dd, td, tableType);
+
+ if (tableElement instanceof ModifyColumnNode)
+ {
+ ModifyColumnNode mcdn = (ModifyColumnNode)cdn;
+ mcdn.checkExistingConstraints(td);
+ } else if (cdn.isAutoincrementColumn())
+ numAutoCols ++;
+ }
+ else if (tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
+ {
+ String colName = tableElement.getName();
+ if (td.getColumnDescriptor(colName) == null)
+ {
+ throw StandardException.newException(
+ SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
+ colName,
+ td.getQualifiedName());
+ }
+ break;
+ }
+
+ /* The rest of this method deals with validating constraints */
+ if (! (tableElement.hasConstraint()))
+ {
+ continue;
+ }
+
+ ConstraintDefinitionNode cdn = (ConstraintDefinitionNode) tableElement;
+
+ cdn.bind(ddlStmt, dd);
+
+ //if constraint is primary key or unique key, add it to the vector
+ if (cdn.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT ||
+ cdn.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)
+ {
+ /* In case of create table, the vector can have only ConstraintDefinitionNode
+ * elements. In case of alter table, it can have both ConstraintDefinitionNode
+ * (for new constraints) and ConstraintDescriptor(for pre-existing constraints).
+ */
+
+ Object destConstraint;
+ String destName = null;
+ String[] destColumnNames = null;
+
+ for (int i=0; i<constraintsVector.size();i++)
+ {
+
+ destConstraint = constraintsVector.elementAt(i);
+ if (destConstraint instanceof ConstraintDefinitionNode)
+ {
+ ConstraintDefinitionNode destCDN = (ConstraintDefinitionNode)destConstraint;
+ destName = destCDN.getConstraintMoniker();
+ destColumnNames = destCDN.getColumnList().getColumnNames();
+ }
+ else if (destConstraint instanceof ConstraintDescriptor)
+ {
+ //will come here only for pre-existing constraints in case of alter table
+ ConstraintDescriptor destCD = (ConstraintDescriptor)destConstraint;
+ destName = destCD.getConstraintName();
+ destColumnNames = destCD.getColumnDescriptors().getColumnNames();
+ }
+ //check if there are multiple constraints with same set of columns
+ if (columnsMatch(cdn.getColumnList().getColumnNames(), destColumnNames))
+ throw StandardException.newException(SQLState.LANG_MULTIPLE_CONSTRAINTS_WITH_SAME_COLUMNS,
+ cdn.getConstraintMoniker(), destName);
+ }
+ constraintsVector.addElement(cdn);
+ }
+
+ /* Make sure that there are no duplicate constraint names in the list */
+ if (cdn instanceof ConstraintDefinitionNode)
+ checkForDuplicateConstraintNames(ddlStmt, constraintHT, cdn.getConstraintMoniker());
+
+ /* Make sure that the constraint we are trying to drop exists */
+ if (cdn.getConstraintType() == DataDictionary.DROP_CONSTRAINT)
+ {
+ /*
+ ** If no schema descriptor, then must be an invalid
+ ** schema name.
+ */
+
+ String dropConstraintName = cdn.getConstraintMoniker();
+
+ if (dropConstraintName != null) {
+
+ String dropSchemaName = cdn.getDropSchemaName();
+
+ SchemaDescriptor sd = dropSchemaName == null ? td.getSchemaDescriptor() :
+ getSchemaDescriptor(dropSchemaName);
+
+ ConstraintDescriptor cd =
+ dd.getConstraintDescriptorByName(
+ td, sd, dropConstraintName,
+ false);
+ if (cd == null)
+ {
+ throw StandardException.newException(SQLState.LANG_DROP_NON_EXISTENT_CONSTRAINT,
+ (sd.getSchemaName() + "."+ dropConstraintName),
+ td.getQualifiedName());
+ }
+ /* Statement is dependendent on the ConstraintDescriptor */
+ getCompilerContext().createDependency(cd);
+ }
+ }
+
+ /* For primary/unique/unique keys, verify that the constraint's column
+ * list contains valid columns and does not contain any duplicates
+ * (Also, all columns in a primary key will be set to non-null,
+ but only in Cloudscape mode. SQL and DB2 require explict NOT NULL.
+ */
+ if (cdn.hasPrimaryKeyConstraint() ||
+ cdn.hasForeignKeyConstraint() ||
+ cdn.hasUniqueKeyConstraint())
+ {
+ verifyUniqueColumnList(ddlStmt, cdn);
+ /* Raise error if primary or unique key columns can be nullable. */
+ if (cdn.hasPrimaryKeyConstraint() || cdn.hasUniqueKeyConstraint())
+ {
+ setColumnListToNotNull(cdn, td);
+ }
+ }
+ }
+
+ /* Can have only one autoincrement column in DB2 mode */
+ if (numAutoCols > 1)
+ throw StandardException.newException(SQLState.LANG_MULTIPLE_AUTOINCREMENT_COLUMNS);
+
+ }
+
+ /**
+ * Count the number of constraints of the specified type.
+ *
+ * @param constraintType The constraint type to search for.
+ *
+ * @return int The number of constraints of the specified type.
+ */
+ public int countConstraints(int constraintType)
+ {
+ int numConstraints = 0;
+ int size = size();
+
+ for (int index = 0; index < size; index++)
+ {
+ ConstraintDefinitionNode cdn;
+ TableElementNode element = (TableElementNode) elementAt(index);
+
+ if (! (element instanceof ConstraintDefinitionNode))
+ {
+ continue;
+ }
+
+ cdn = (ConstraintDefinitionNode) element;
+
+ if (constraintType == cdn.getConstraintType())
+ {
+ numConstraints++;
+ }
+ }
+
+ return numConstraints;
+ }
+
+ /**
+ * Count the number of columns.
+ *
+ * @return int The number of columns.
+ */
+ public int countNumberOfColumns()
+ {
+ return numColumns;
+ }
+
+ /**
+ * Fill in the ColumnInfo[] for this table element list.
+ *
+ * @param colInfos The ColumnInfo[] to be filled in.
+ *
+ * @return int The number of constraints in the create table.
+ */
+ public int genColumnInfos(ColumnInfo[] colInfos)
+ {
+ int numConstraints = 0;
+ int size = size();
+
+ for (int index = 0; index < size; index++)
+ {
+ if (((TableElementNode) elementAt(index)).getElementType() == TableElementNode.AT_DROP_COLUMN)
+ {
+ colInfos[index] = new ColumnInfo(
+ ((TableElementNode) elementAt(index)).getName(),
+ null, null, null, null, null,
+ ColumnInfo.DROP, 0, 0);
+ break;
+ }
+
+ if (! (elementAt(index) instanceof ColumnDefinitionNode))
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT( elementAt(index) instanceof ConstraintDefinitionNode,
+ "elementAt(index) expected to be instanceof " +
+ "ConstraintDefinitionNode");
+ }
+
+ /* Remember how many constraints that we've seen */
+ numConstraints++;
+ continue;
+ }
+
+ ColumnDefinitionNode coldef = (ColumnDefinitionNode) elementAt(index);
+
+ colInfos[index - numConstraints] =
+ new ColumnInfo(coldef.getColumnName(),
+ coldef.getDataTypeServices(),
+ coldef.getDefaultValue(),
+ coldef.getDefaultInfo(),
+ (UUID) null,
+ coldef.getOldDefaultUUID(),
+ coldef.getAction(),
+ (coldef.isAutoincrementColumn() ?
+ coldef.getAutoincrementStart() : 0),
+ (coldef.isAutoincrementColumn() ?
+ coldef.getAutoincrementIncrement() : 0));
+
+ /* Remember how many constraints that we've seen */
+ if (coldef.hasConstraint())
+ {
+ numConstraints++;
+ }
+ }
+
+ return numConstraints;
+ }
+ /**
+ * Append goobered up ResultColumns to the table's RCL.
+ * This is useful for binding check constraints for CREATE and ALTER TABLE.
+ *
+ * @param table The table in question.
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void appendNewColumnsToRCL(FromBaseTable table)
+ throws StandardException
+ {
+ int size = size();
+ ResultColumnList rcl = table.getResultColumns();
+ TableName exposedName = table.getTableName();
+
+ for (int index = 0; index < size; index++)
+ {
+ if (elementAt(index) instanceof ColumnDefinitionNode)
+ {
+ ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index);
+ ResultColumn resultColumn;
+ ValueNode valueNode;
+
+ /* Build a ResultColumn/BaseColumnNode pair for the column */
+ valueNode = (ValueNode) getNodeFactory().getNode(
+ C_NodeTypes.BASE_COLUMN_NODE,
+ cdn.getColumnName(),
+ exposedName,
+ cdn.getDataTypeServices(),
+ getContextManager());
+
+ resultColumn = (ResultColumn) getNodeFactory().getNode(
+ C_NodeTypes.RESULT_COLUMN,
+ cdn.getDataTypeServices(),
+ valueNode,
+ getContextManager());
+ resultColumn.setName(cdn.getColumnName());
+ rcl.addElement(resultColumn);
+ }
+ }
+ }
+
+ /**
+ * Bind and validate all of the check constraints in this list against
+ * the specified FromList.
+ *
+ * @param FromList The FromList in question.
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown on error
+ */
+ void bindAndValidateCheckConstraints(FromList fromList)
+ throws StandardException
+ {
+ CompilerContext cc;
+ FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
+ int size = size();
+
+ cc = getCompilerContext();
+
+ Vector aggregateVector = new Vector();
+
+ for (int index = 0; index < size; index++)
+ {
+ ConstraintDefinitionNode cdn;
+ TableElementNode element = (TableElementNode) elementAt(index);
+ ValueNode checkTree;
+
+ if (! (element instanceof ConstraintDefinitionNode))
+ {
+ continue;
+ }
+
+ cdn = (ConstraintDefinitionNode) element;
+
+ if (cdn.getConstraintType() != DataDictionary.CHECK_CONSTRAINT)
+ {
+ continue;
+ }
+
+ checkTree = cdn.getCheckCondition();
+
+ // bind the check condition
+ // verify that it evaluates to a boolean
+ final int previousReliability = cc.getReliability();
+ try
+ {
+ /* Each check constraint can have its own set of dependencies.
+ * These dependencies need to be shared with the prepared
+ * statement as well. We create a new auxiliary provider list
+ * for the check constraint, "push" it on the compiler context
+ * by swapping it with the current auxiliary provider list
+ * and the "pop" it when we're done by restoring the old
+ * auxiliary provider list.
+ */
+ ProviderList apl = new ProviderList();
+
+ ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
+ cc.setCurrentAuxiliaryProviderList(apl);
+
+ // Tell the compiler context to only allow deterministic nodes
+ cc.setReliability( CompilerContext.CHECK_CONSTRAINT );
+ checkTree = checkTree.bindExpression(fromList, (SubqueryList) null,
+ aggregateVector);
+
+ // no aggregates, please
+ if (aggregateVector.size() != 0)
+ {
+ throw StandardException.newException(SQLState.LANG_INVALID_CHECK_CONSTRAINT, cdn.getConstraintText());
+ }
+
+ checkTree = checkTree.checkIsBoolean();
+ cdn.setCheckCondition(checkTree);
+
+ /* Save the APL off in the constraint node */
+ if (apl.size() > 0)
+ {
+ cdn.setAuxiliaryProviderList(apl);
+ }
+
+ // Restore the previous AuxiliaryProviderList
+ cc.setCurrentAuxiliaryProviderList(prevAPL);
+ }
+ finally
+ {
+ cc.setReliability(previousReliability);
+ }
+
+ /* We have a valid check constraint, now build an array of
+ * 1-based columnIds that the constraint references.
+ */
+ ResultColumnList rcl = table.getResultColumns();
+ int numReferenced = rcl.countReferencedColumns();
+ int[] checkColumnReferences = new int[numReferenced];
+
+ rcl.recordColumnReferences(checkColumnReferences, 1);
+ cdn.setCheckColumnReferences(checkColumnReferences);
+
+ /* Now we build a list with only the referenced columns and
+ * copy it to the cdn. Thus we can build the array of
+ * column names for the referenced columns during generate().
+ */
+ ResultColumnList refRCL =
+ (ResultColumnList) getNodeFactory().getNode(
+ C_NodeTypes.RESULT_COLUMN_LIST,
+ getContextManager());
+ rcl.copyReferencedColumnsToNewList(refRCL);
+
+ /* A column check constraint can only refer to that column. If this is a
+ * column constraint, we should have an RCL with that column
+ */
+ if (cdn.getColumnList() != null)
+ {
+ String colName = ((ResultColumn)(cdn.getColumnList().elementAt(0))).getName();
+ if (numReferenced > 1 ||
+ !colName.equals(((ResultColumn)(refRCL.elementAt(0))).getName()))
+ throw StandardException.newException(SQLState.LANG_DB2_INVALID_CHECK_CONSTRAINT, colName);
+
+ }
+ cdn.setColumnList(refRCL);
+
+ /* Clear the column references in the RCL so each check constraint
+ * starts with a clean list.
+ */
+ rcl.clearColumnReferences();
+ }
+ }
+
+ /**
+ * Fill in the ConstraintConstantAction[] for this create/alter table.
+ *
+ * @param conActions The ConstraintConstantAction[] to be filled in.
+ * @param tableName The name of the Table being created.
+ * @param sd The schema for that table.
+ * @param dd The DataDictionary
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown on failure
+ */
+ void genConstraintActions(
+ ConstraintConstantAction[] conActions,
+ String tableName,
+ SchemaDescriptor tableSd,
+ DataDictionary dd)
+ throws StandardException
+ {
+ int size = size();
+ int conActionIndex = 0;
+ for (int index = 0; index < size; index++)
+ {
+ String[] columnNames = null;
+ String generatedConstraintName;
+ TableElementNode ten = (TableElementNode) elementAt(index);
+ IndexConstantAction indexAction = null;
+
+ if (! ten.hasConstraint())
+ {
+ continue;
+ }
+
+ if (ten instanceof ColumnDefinitionNode)
+ {
+ continue;
+ }
+
+ ConstraintDefinitionNode constraintDN = (ConstraintDefinitionNode) ten;
+
+ if (constraintDN.getColumnList() != null)
+ {
+ columnNames = new String[constraintDN.getColumnList().size()];
+ constraintDN.getColumnList().exportNames(columnNames);
+ }
+
+ int constraintType = constraintDN.getConstraintType();
+ String constraintText = constraintDN.getConstraintText();
+
+ /*
+ ** If the constraint is not named (e.g.
+ ** create table x (x int primary key)), then
+ ** the constraintSd is the same as the table.
+ */
+ String constraintName = constraintDN.getConstraintMoniker();
+
+ /* At execution time, we will generate a unique name for the backing
+ * index (for CREATE CONSTRAINT) and we will look up the conglomerate
+ * name (for DROP CONSTRAINT).
+ */
+ if (constraintDN.requiresBackingIndex())
+ {
+ indexAction = genIndexAction(constraintDN.requiresUniqueIndex(),
+ null, constraintDN,
+ columnNames, true, tableSd, tableName,
+ constraintType, dd);
+ }
+
+ if (constraintType == DataDictionary.DROP_CONSTRAINT)
+ {
+ conActions[conActionIndex] =
+ getGenericConstantActionFactory().
+ getDropConstraintConstantAction(
+ constraintName,
+ constraintDN.getDropSchemaName(), /// FiX
+ tableName,
+ td.getUUID(),
+ tableSd.getSchemaName(),
+ indexAction,
+ constraintDN.getDropBehavior(),
+ constraintDN.getVerifyType());
+ }
+ else
+ {
+ ProviderList apl = constraintDN.getAuxiliaryProviderList();
+ ConstraintInfo refInfo = null;
+ ProviderInfo[] providerInfos = null;
+
+ if (constraintDN instanceof FKConstraintDefinitionNode)
+ {
+ refInfo = ((FKConstraintDefinitionNode)constraintDN).getReferencedConstraintInfo();
+ }
+
+ /* Create the ProviderInfos, if the constraint is dependent on any Providers */
+ if (apl != null && apl.size() > 0)
+ {
+ /* Get all the dependencies for the current statement and transfer
+ * them to this view.
+ */
+ DependencyManager dm = dd.getDependencyManager();
+ providerInfos = dm.getPersistentProviderInfos(apl);
+ }
+ else
+ {
+ providerInfos = new ProviderInfo[0];
+ }
+
+ conActions[conActionIndex++] =
+ getGenericConstantActionFactory().
+ getCreateConstraintConstantAction(
+ constraintName,
+ constraintType,
+ tableName,
+ ((td != null) ? td.getUUID() : (UUID) null),
+ tableSd.getSchemaName(),
+ columnNames,
+ indexAction,
+ constraintText,
+ true, // enabled
+ refInfo,
+ providerInfos);
+ }
+ }
+ }
+
+ //check if one array is same as another
+ private boolean columnsMatch(String[] columnNames1, String[] columnNames2)
+ throws StandardException
+ {
+ int srcCount, srcSize, destCount,destSize;
+ boolean match = true;
+
+ if (columnNames1.length != columnNames2.length)
+ return false;
+
+ srcSize = columnNames1.length;
+ destSize = columnNames2.length;
+
+ for (srcCount = 0; srcCount < srcSize; srcCount++)
+ {
+ match = false;
+ for (destCount = 0; destCount < destSize; destCount++) {
+ if (columnNames1[srcCount].equals(columnNames2[destCount])) {
+ match = true;
+ break;
+ }
+ }
+ if (match == false)
+ return false;
+ }
+
+ return true;
+ }
+
+ private IndexConstantAction genIndexAction(
+ boolean isUnique,
+ String indexName,
+ ConstraintDefinitionNode cdn,
+ String[] columnNames,
+ boolean isConstraint,
+ SchemaDescriptor sd,
+ String tableName,
+ int constraintType,
+ DataDictionary dd)
+ throws StandardException
+ {
+ if ( indexName == null ) { indexName = cdn.getBackingIndexName(dd); }
+
+ if (constraintType == DataDictionary.DROP_CONSTRAINT)
+ {
+ return getGenericConstantActionFactory().getDropIndexConstantAction(
+ null,
+ indexName,
+ tableName,
+ sd.getSchemaName(),
+ td.getUUID(),
+ td.getHeapConglomerateId());
+ }
+ else
+ {
+ boolean[] isAscending = new boolean[columnNames.length];
+ for (int i = 0; i < isAscending.length; i++)
+ isAscending[i] = true;
+ return getGenericConstantActionFactory().getCreateIndexConstantAction(
+ isUnique,
+ "BTREE", // indexType
+ sd.getSchemaName(),
+ indexName,
+ tableName,
+ ((td != null) ? td.getUUID() : (UUID) null),
+ 0, // conglomId
+ columnNames,
+ isAscending,
+ isConstraint,
+ cdn.getBackingIndexUUID(),
+ cdn.getProperties());
+ }
+ }
+
+ /**
+ * Check to make sure that there are no duplicate column names
+ * in the list. (The comparison here is case sensitive.
+ * The work of converting column names that are not quoted
+ * identifiers to upper case is handled by the parser.)
+ * RESOLVE: This check will also be performed by alter table.
+ *
+ * @param ddlStmt DDLStatementNode which contains this list
+ * @param ht Hashtable for enforcing uniqueness.
+ * @param colName Column name to check for.
+ *
+ * @return None
+ *
+ * @exception StandardException Thrown on error
+ */
+ private void checkForDuplicateColumns(DDLStatementNode ddlStmt,
+ Hashtable ht,
+ String colName)
+ throws StandardException
+ {
+ Object object = ht.put(colName, colName);
+ if (object != null)
+ {
+ /* RESOLVE - different error messages for create and alter table */
+ if (ddlStmt instanceof CreateTableNode)
+ {
+ throw StandardException.newException(SQLState.LANG_DUPLICATE_COLUMN_NAME_CREATE, colName);
+ }
+ }
+ }
+
+ /**
+ * Check to make sure that there are no duplicate constraint names
+ * in the list. (The comparison here is case sensitive.
+ * The work of converting column names that are not quoted
+ * identifiers to upper case is handled by the parser.)
+ * RESOLVE: This check will also be performed by alter table.
+ *
+ * @param ddlStmt DDLStatementNode which contains this list
+ * @param outer The element to check against. Only check
+ * TableElements that come after this one, since this
+ * one has been checked against the TableElements
+ * before it.
+ *
+ * @return None
+ *
+ * @exception StandardException Thrown on error
+ */
+ private void checkForDuplicateConstraintNames(DDLStatementNode ddlStmt,
+ Hashtable ht,
+ String constraintName)
+ throws StandardException
+ {
+ if (constraintName == null)
+ return;
+
+ Object object = ht.put(constraintName, constraintName);
+ if (object != null) {
+
+ /* RESOLVE - different error messages for create and alter table */
+ if (ddlStmt instanceof CreateTableNode)
+ {
+ /* RESOLVE - new error message */
+ throw StandardException.newException(SQLState.LANG_DUPLICATE_CONSTRAINT_NAME_CREATE,
+ constraintName);
+ }
+ }
+ }
+
+ /**
+ * Verify that a primary/unique table constraint has a valid column list.
+ * (All columns in table and no duplicates.)
+ *
+ * @param ddlStmt The outer DDLStatementNode
+ * @param cdn The ConstraintDefinitionNode
+ *
+ * @return Nothing.
+ *
+ * @exception StandardException Thrown if the column list is invalid
+ */
+ private void verifyUniqueColumnList(DDLStatementNode ddlStmt,
+ ConstraintDefinitionNode cdn)
+ throws StandardException
+ {
+ String invalidColName;
+
+ /* Verify that every column in the list appears in the table's list of columns */
+ if (ddlStmt instanceof CreateTableNode)
+ {
+ invalidColName = cdn.getColumnList().verifyCreateConstraintColumnList(this);
+ if (invalidColName != null)
+ {
+ throw StandardException.newException(SQLState.LANG_INVALID_CREATE_CONSTRAINT_COLUMN_LIST,
+ ddlStmt.getRelativeName(),
+ invalidColName);
+ }
+ }
+ else
+ {
+ /* RESOLVE - alter table will need to get table descriptor */
+ }
+
+ /* Check the uniqueness of the column names within the list */
+ invalidColName = cdn.getColumnList().verifyUniqueNames(false);
+ if (invalidColName != null)
+ {
+ throw StandardException.newException(SQLState.LANG_DUPLICATE_CONSTRAINT_COLUMN_NAME, invalidColName);
+ }
+ }
+
+ /**
+ * Set all columns in that appear in a primary/unique key constraint in a create
+ * table statement to NOT NULL in Cloudscape mode and raises an error in DB2 mode.
+ *
+ * @param cdn The ConstraintDefinitionNode
+ * @param td TableDescriptor for the table
+ *
+ * @return Nothing.
+ */
+ private void setColumnListToNotNull(ConstraintDefinitionNode cdn, TableDescriptor td)
+ throws StandardException
+ {
+ ResultColumnList rcl = cdn.getColumnList();
+ int rclSize = rcl.size();
+ for (int index = 0; index < rclSize; index++)
+ {
+ String colName = ((ResultColumn) rcl.elementAt(index)).getName();
+
+ /* For ALTER TABLE ADD CONSTRAINT, make sure columns are not nullable for
+ * primary and unique constraints.
+ */
+ if (td != null && cdn instanceof ConstraintDefinitionNode)
+ {
+ ColumnDescriptor cd = td.getColumnDescriptor(colName);
+ if (cd != null && cd.getType().isNullable())
+ throw StandardException.newException(SQLState.LANG_DB2_ADD_UNIQUE_OR_PRIMARY_KEY_ON_NULL_COLS, colName);
+ }
+
+ setColumnToNotNull(colName);
+ }
+ }
+
+ /**
+ * Set a column that appears in a primary/unique key constraint in
+ * a create table statement to NOT NULL (but only in Cloudscape mode).
+ *
+ * @param colName The column name
+ *
+ * @return Nothing.
+ */
+ private void setColumnToNotNull(String colName) throws StandardException
+ {
+ int size = size();
+
+ for (int index = 0; index < size; index++)
+ {
+ TableElementNode tableElement = (TableElementNode) elementAt(index);
+
+ if (tableElement instanceof ColumnDefinitionNode)
+ {
+ ColumnDefinitionNode cdn = (ColumnDefinitionNode) tableElement;
+ if (colName.equals(cdn.getColumnName()))
+ {
+ DataTypeDescriptor dtd = cdn.getDataTypeServices();
+
+ if (dtd.isNullable())
+ throw StandardException.newException(SQLState.LANG_DB2_ADD_UNIQUE_OR_PRIMARY_KEY_ON_NULL_COLS, colName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Determine whether or not the parameter matches a column name in this list.
+ *
+ * @param colName The column name to search for.
+ *
+ * @return boolean Whether or not a match is found.
+ */
+ public boolean containsColumnName(String colName)
+ {
+ int size = size();
+ for (int index = 0; index < size; index++)
+ {
+ TableElementNode tableElement = (TableElementNode) elementAt(index);
+
+ if (tableElement instanceof ColumnDefinitionNode)
+ {
+ if (colName.equals(((ColumnDefinitionNode) tableElement).getName()))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
+
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java Fri Sep 24 10:33:20 2004
@@ -1,182 +1,182 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-/**
- * A TableElementNode is an item in a TableElementList, and represents
- * a single table element such as a column or constraint in a CREATE TABLE
- * or ALTER TABLE statement.
- *
- * @author Jeff Lichtman
- */
-
-public class TableElementNode extends QueryTreeNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /////////////////////////////////////////////////////////////////////////
- //
- // CONSTANTS
- //
- /////////////////////////////////////////////////////////////////////////
-
- public static final int AT_UNKNOWN = 0;
- public static final int AT_ADD_FOREIGN_KEY_CONSTRAINT = 1;
- public static final int AT_ADD_PRIMARY_KEY_CONSTRAINT = 2;
- public static final int AT_ADD_UNIQUE_CONSTRAINT = 3;
- public static final int AT_ADD_CHECK_CONSTRAINT = 4;
- public static final int AT_DROP_CONSTRAINT = 5;
- public static final int AT_MODIFY_COLUMN = 6;
- public static final int AT_DROP_COLUMN = 7;
-
-
- /////////////////////////////////////////////////////////////////////////
- //
- // STATE
- //
- /////////////////////////////////////////////////////////////////////////
-
- String name;
- int elementType; // simple element nodes can share this class,
- // eg., drop column and rename table/column/index
- // etc., no need for more classes, an effort to
- // minimize footprint
-
- /////////////////////////////////////////////////////////////////////////
- //
- // BEHAVIOR
- //
- /////////////////////////////////////////////////////////////////////////
-
- /**
- * Initializer for a TableElementNode
- *
- * @param name The name of the table element, if any
- */
-
- public void init(Object name)
- {
- this.name = (String) name;
- }
-
- /**
- * Initializer for a TableElementNode
- *
- * @param name The name of the table element, if any
- */
-
- public void init(Object name, Object elementType)
- {
- this.name = (String) name;
- this.elementType = ((Integer) elementType).intValue();
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- return "name: " + name + "\n" +
- super.toString();
- }
- else
- {
- return "";
- }
- }
-
- /**
- * Does this element have a primary key constraint.
- *
- * @return boolean Whether or not this element has a primary key constraint
- */
- boolean hasPrimaryKeyConstraint()
- {
- return false;
- }
-
- /**
- * Does this element have a unique key constraint.
- *
- * @return boolean Whether or not this element has a unique key constraint
- */
- boolean hasUniqueKeyConstraint()
- {
- return false;
- }
-
- /**
- * Does this element have a foreign key constraint.
- *
- * @return boolean Whether or not this element has a foreign key constraint
- */
- boolean hasForeignKeyConstraint()
- {
- return false;
- }
-
- /**
- * Does this element have a check constraint.
- *
- * @return boolean Whether or not this element has a check constraint
- */
- boolean hasCheckConstraint()
- {
- return false;
- }
-
- /**
- * Does this element have a constraint on it.
- *
- * @return boolean Whether or not this element has a constraint on it
- */
- boolean hasConstraint()
- {
- return false;
- }
-
- /**
- * Get the name from this node.
- *
- * @return String The name.
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Get the type of this table element.
- *
- * @return one of the constants at the front of this file
- */
- int getElementType()
- {
- if ( hasForeignKeyConstraint() ) { return AT_ADD_FOREIGN_KEY_CONSTRAINT; }
- else if ( hasPrimaryKeyConstraint() ) { return AT_ADD_PRIMARY_KEY_CONSTRAINT; }
- else if ( hasUniqueKeyConstraint() ) { return AT_ADD_UNIQUE_CONSTRAINT; }
- else if ( hasCheckConstraint() ) { return AT_ADD_CHECK_CONSTRAINT; }
- else if ( this instanceof ConstraintDefinitionNode ) { return AT_DROP_CONSTRAINT; }
- else if ( this instanceof ModifyColumnNode ) { return AT_MODIFY_COLUMN; }
- else { return elementType; }
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+/**
+ * A TableElementNode is an item in a TableElementList, and represents
+ * a single table element such as a column or constraint in a CREATE TABLE
+ * or ALTER TABLE statement.
+ *
+ * @author Jeff Lichtman
+ */
+
+public class TableElementNode extends QueryTreeNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // CONSTANTS
+ //
+ /////////////////////////////////////////////////////////////////////////
+
+ public static final int AT_UNKNOWN = 0;
+ public static final int AT_ADD_FOREIGN_KEY_CONSTRAINT = 1;
+ public static final int AT_ADD_PRIMARY_KEY_CONSTRAINT = 2;
+ public static final int AT_ADD_UNIQUE_CONSTRAINT = 3;
+ public static final int AT_ADD_CHECK_CONSTRAINT = 4;
+ public static final int AT_DROP_CONSTRAINT = 5;
+ public static final int AT_MODIFY_COLUMN = 6;
+ public static final int AT_DROP_COLUMN = 7;
+
+
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // STATE
+ //
+ /////////////////////////////////////////////////////////////////////////
+
+ String name;
+ int elementType; // simple element nodes can share this class,
+ // eg., drop column and rename table/column/index
+ // etc., no need for more classes, an effort to
+ // minimize footprint
+
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // BEHAVIOR
+ //
+ /////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Initializer for a TableElementNode
+ *
+ * @param name The name of the table element, if any
+ */
+
+ public void init(Object name)
+ {
+ this.name = (String) name;
+ }
+
+ /**
+ * Initializer for a TableElementNode
+ *
+ * @param name The name of the table element, if any
+ */
+
+ public void init(Object name, Object elementType)
+ {
+ this.name = (String) name;
+ this.elementType = ((Integer) elementType).intValue();
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ return "name: " + name + "\n" +
+ super.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Does this element have a primary key constraint.
+ *
+ * @return boolean Whether or not this element has a primary key constraint
+ */
+ boolean hasPrimaryKeyConstraint()
+ {
+ return false;
+ }
+
+ /**
+ * Does this element have a unique key constraint.
+ *
+ * @return boolean Whether or not this element has a unique key constraint
+ */
+ boolean hasUniqueKeyConstraint()
+ {
+ return false;
+ }
+
+ /**
+ * Does this element have a foreign key constraint.
+ *
+ * @return boolean Whether or not this element has a foreign key constraint
+ */
+ boolean hasForeignKeyConstraint()
+ {
+ return false;
+ }
+
+ /**
+ * Does this element have a check constraint.
+ *
+ * @return boolean Whether or not this element has a check constraint
+ */
+ boolean hasCheckConstraint()
+ {
+ return false;
+ }
+
+ /**
+ * Does this element have a constraint on it.
+ *
+ * @return boolean Whether or not this element has a constraint on it
+ */
+ boolean hasConstraint()
+ {
+ return false;
+ }
+
+ /**
+ * Get the name from this node.
+ *
+ * @return String The name.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Get the type of this table element.
+ *
+ * @return one of the constants at the front of this file
+ */
+ int getElementType()
+ {
+ if ( hasForeignKeyConstraint() ) { return AT_ADD_FOREIGN_KEY_CONSTRAINT; }
+ else if ( hasPrimaryKeyConstraint() ) { return AT_ADD_PRIMARY_KEY_CONSTRAINT; }
+ else if ( hasUniqueKeyConstraint() ) { return AT_ADD_UNIQUE_CONSTRAINT; }
+ else if ( hasCheckConstraint() ) { return AT_ADD_CHECK_CONSTRAINT; }
+ else if ( this instanceof ConstraintDefinitionNode ) { return AT_DROP_CONSTRAINT; }
+ else if ( this instanceof ModifyColumnNode ) { return AT_MODIFY_COLUMN; }
+ else { return elementType; }
+ }
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableName.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableName.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableName.java Fri Sep 24 10:33:20 2004
@@ -1,285 +1,285 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.reference.Property;
-import org.apache.derby.iapi.reference.SQLState;
-
-/**
- * A TableName represents a qualified name, externally represented as a schema name
- * and an object name separated by a dot. This class is mis-named: it is used to
- * represent the names of other object types in addition to tables.
- *
- * @author Jerry Brenner
- */
-
-public class TableName extends QueryTreeNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /* Both schemaName and tableName can be null, however, if
- ** tableName is null then schemaName must also be null.
- */
- String tableName;
- String schemaName;
-
- /*
- ** These fields are used to track the being and end
- ** offset of the token from which the TableName came.
- ** These are always set to legitimate values in the
- ** parser. If a tableName has been generated elsewhere,
- ** they may not be set. -1 means unset.
- */
- private int tokBeginOffset = -1;
- private int tokEndOffset = -1;
-
- /**
- * Initializer for when you have both the table and schema names.
- *
- * @param schemaName The name of the schema being referenced
- * @param tableName The name of the table being referenced
- */
-
- public void init(Object schemaName, Object tableName)
- {
- this.schemaName = (String) schemaName;
- this.tableName = (String) tableName;
- }
-
- /**
- * Initializer for when you have both the table and schema names.
- *
- * @param schemaName The name of the schema being referenced
- * @param tableName The name of the table being referenced
- * @param tokBeginOffset begin position of token for the table name
- * identifier from parser. pass in -1 if unknown
- * @param tokEndOffset end position of token for the table name
- * identifier from parser. pass in -1 if unknown
- */
- public void init
- (
- Object schemaName,
- Object tableName,
- Object tokBeginOffset,
- Object tokEndOffset
- )
- {
- this.schemaName = (String) schemaName;
- this.tableName = (String) tableName;
- this.tokBeginOffset = ((Integer) tokBeginOffset).intValue();
- this.tokEndOffset = ((Integer) tokEndOffset).intValue();
- }
-
- /**
- * Get the table name (without the schema name).
- *
- * @return Table name as a String
- */
-
- public String getTableName()
- {
- return tableName;
- }
-
- /**
- * Get the schema name.
- *
- * @return Schema name as a String
- */
-
- public String getSchemaName()
- {
- return schemaName;
- }
-
- /**
- * Get the begin offset of the parser token for the table name
- * Will only be set when the TableName was generated by the
- * parser.
- *
- * @return the begin offset of the token. -1 means unknown
- */
- public int getTokenBeginOffset()
- {
- return tokBeginOffset;
- }
-
- /**
- * Get the end offset of the parser token for the table name.
- * Will only be set when the TableName was generated by the
- * parser.
- *
- * @return the end offset of the token. -1 means unknown
- */
- public int getTokenEndOffset()
- {
- return tokEndOffset;
- }
-
- /**
- * Set the schema name.
- *
- * @param schemaName Schema name as a String
- *
- * @return Nothing.
- */
-
- public void setSchemaName(String schemaName)
- {
- this.schemaName = schemaName;
- }
-
- /**
- * Get the full table name (with the schema name, if explicitly
- * specified).
- *
- * @return Full table name as a String
- */
-
- public String getFullTableName()
- {
- if (schemaName != null)
- return schemaName + "." + tableName;
- else
- return tableName;
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- return getFullTableName();
- }
-
- /**
- * 2 TableNames are equal if their both their schemaNames and tableNames are
- * equal, or if this node's full table name is null (which happens when a
- * SELECT * is expanded). Also, only check table names if the schema
- * name(s) are null.
- *
- * @param otherTableName The other TableName.
- *
- * @return boolean Whether or not the 2 TableNames are equal.
- */
- public boolean equals(TableName otherTableName)
- {
- String fullTableName = getFullTableName();
- if (fullTableName == null)
- {
- return true;
- }
- else if ((schemaName == null) ||
- (otherTableName.getSchemaName() == null))
- {
- return tableName.equals(otherTableName.getTableName());
- }
- else
- {
- return fullTableName.equals(otherTableName.getFullTableName());
- }
- }
-
- /**
- * 2 TableNames are equal if their both their schemaNames and tableNames are
- * equal, or if this node's full table name is null (which happens when a
- * SELECT * is expanded). Also, only check table names if the schema
- * name(s) are null.
- *
- * @param otherSchemaName The other TableName.
- * @param otherTableName The other TableName.
- *
- * @return boolean Whether or not the 2 TableNames are equal.
- */
- public boolean equals(String otherSchemaName, String otherTableName)
- {
- String fullTableName = getFullTableName();
- if (fullTableName == null)
- {
- return true;
- }
- else if ((schemaName == null) ||
- (otherSchemaName == null))
- {
- return tableName.equals(otherTableName);
- }
- else
- {
- return fullTableName.equals(otherSchemaName+"."+otherTableName);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////
- //
- // BIND METHODS
- //
- ///////////////////////////////////////////////////////////////////////
-
- /**
- * Bind this TableName. This means filling in the schema name if it
- * wasn't specified.
- *
- * @param dataDictionary Data dictionary to bind against.
- *
- * @exception StandardException Thrown on error
- */
- public void bind( DataDictionary dataDictionary )
- throws StandardException
- {
- schemaName = getSchemaDescriptor(schemaName).getSchemaName();
- }
-
- ///////////////////////////////////////////////////////////////////////
- //
- // OBJECT INTERFACE
- //
- ///////////////////////////////////////////////////////////////////////
-
- /**
- * Returns a hashcode for this tableName. This allows us to use TableNames
- * as keys in hash lists.
- *
- * @return hashcode for this tablename
- */
- public int hashCode()
- {
- return getFullTableName().hashCode();
- }
-
- /**
- * Compares two TableNames. Needed for hashing logic to work.
- *
- * @param other other tableName
- */
- public boolean equals( Object other )
- {
- if ( !( other instanceof TableName ) ) { return false; }
-
- TableName that = (TableName) other;
-
- return this.getFullTableName().equals( that.getFullTableName() );
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.reference.Property;
+import org.apache.derby.iapi.reference.SQLState;
+
+/**
+ * A TableName represents a qualified name, externally represented as a schema name
+ * and an object name separated by a dot. This class is mis-named: it is used to
+ * represent the names of other object types in addition to tables.
+ *
+ * @author Jerry Brenner
+ */
+
+public class TableName extends QueryTreeNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /* Both schemaName and tableName can be null, however, if
+ ** tableName is null then schemaName must also be null.
+ */
+ String tableName;
+ String schemaName;
+
+ /*
+ ** These fields are used to track the being and end
+ ** offset of the token from which the TableName came.
+ ** These are always set to legitimate values in the
+ ** parser. If a tableName has been generated elsewhere,
+ ** they may not be set. -1 means unset.
+ */
+ private int tokBeginOffset = -1;
+ private int tokEndOffset = -1;
+
+ /**
+ * Initializer for when you have both the table and schema names.
+ *
+ * @param schemaName The name of the schema being referenced
+ * @param tableName The name of the table being referenced
+ */
+
+ public void init(Object schemaName, Object tableName)
+ {
+ this.schemaName = (String) schemaName;
+ this.tableName = (String) tableName;
+ }
+
+ /**
+ * Initializer for when you have both the table and schema names.
+ *
+ * @param schemaName The name of the schema being referenced
+ * @param tableName The name of the table being referenced
+ * @param tokBeginOffset begin position of token for the table name
+ * identifier from parser. pass in -1 if unknown
+ * @param tokEndOffset end position of token for the table name
+ * identifier from parser. pass in -1 if unknown
+ */
+ public void init
+ (
+ Object schemaName,
+ Object tableName,
+ Object tokBeginOffset,
+ Object tokEndOffset
+ )
+ {
+ this.schemaName = (String) schemaName;
+ this.tableName = (String) tableName;
+ this.tokBeginOffset = ((Integer) tokBeginOffset).intValue();
+ this.tokEndOffset = ((Integer) tokEndOffset).intValue();
+ }
+
+ /**
+ * Get the table name (without the schema name).
+ *
+ * @return Table name as a String
+ */
+
+ public String getTableName()
+ {
+ return tableName;
+ }
+
+ /**
+ * Get the schema name.
+ *
+ * @return Schema name as a String
+ */
+
+ public String getSchemaName()
+ {
+ return schemaName;
+ }
+
+ /**
+ * Get the begin offset of the parser token for the table name
+ * Will only be set when the TableName was generated by the
+ * parser.
+ *
+ * @return the begin offset of the token. -1 means unknown
+ */
+ public int getTokenBeginOffset()
+ {
+ return tokBeginOffset;
+ }
+
+ /**
+ * Get the end offset of the parser token for the table name.
+ * Will only be set when the TableName was generated by the
+ * parser.
+ *
+ * @return the end offset of the token. -1 means unknown
+ */
+ public int getTokenEndOffset()
+ {
+ return tokEndOffset;
+ }
+
+ /**
+ * Set the schema name.
+ *
+ * @param schemaName Schema name as a String
+ *
+ * @return Nothing.
+ */
+
+ public void setSchemaName(String schemaName)
+ {
+ this.schemaName = schemaName;
+ }
+
+ /**
+ * Get the full table name (with the schema name, if explicitly
+ * specified).
+ *
+ * @return Full table name as a String
+ */
+
+ public String getFullTableName()
+ {
+ if (schemaName != null)
+ return schemaName + "." + tableName;
+ else
+ return tableName;
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ return getFullTableName();
+ }
+
+ /**
+ * 2 TableNames are equal if their both their schemaNames and tableNames are
+ * equal, or if this node's full table name is null (which happens when a
+ * SELECT * is expanded). Also, only check table names if the schema
+ * name(s) are null.
+ *
+ * @param otherTableName The other TableName.
+ *
+ * @return boolean Whether or not the 2 TableNames are equal.
+ */
+ public boolean equals(TableName otherTableName)
+ {
+ String fullTableName = getFullTableName();
+ if (fullTableName == null)
+ {
+ return true;
+ }
+ else if ((schemaName == null) ||
+ (otherTableName.getSchemaName() == null))
+ {
+ return tableName.equals(otherTableName.getTableName());
+ }
+ else
+ {
+ return fullTableName.equals(otherTableName.getFullTableName());
+ }
+ }
+
+ /**
+ * 2 TableNames are equal if their both their schemaNames and tableNames are
+ * equal, or if this node's full table name is null (which happens when a
+ * SELECT * is expanded). Also, only check table names if the schema
+ * name(s) are null.
+ *
+ * @param otherSchemaName The other TableName.
+ * @param otherTableName The other TableName.
+ *
+ * @return boolean Whether or not the 2 TableNames are equal.
+ */
+ public boolean equals(String otherSchemaName, String otherTableName)
+ {
+ String fullTableName = getFullTableName();
+ if (fullTableName == null)
+ {
+ return true;
+ }
+ else if ((schemaName == null) ||
+ (otherSchemaName == null))
+ {
+ return tableName.equals(otherTableName);
+ }
+ else
+ {
+ return fullTableName.equals(otherSchemaName+"."+otherTableName);
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // BIND METHODS
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+ /**
+ * Bind this TableName. This means filling in the schema name if it
+ * wasn't specified.
+ *
+ * @param dataDictionary Data dictionary to bind against.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void bind( DataDictionary dataDictionary )
+ throws StandardException
+ {
+ schemaName = getSchemaDescriptor(schemaName).getSchemaName();
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ //
+ // OBJECT INTERFACE
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+ /**
+ * Returns a hashcode for this tableName. This allows us to use TableNames
+ * as keys in hash lists.
+ *
+ * @return hashcode for this tablename
+ */
+ public int hashCode()
+ {
+ return getFullTableName().hashCode();
+ }
+
+ /**
+ * Compares two TableNames. Needed for hashing logic to work.
+ *
+ * @param other other tableName
+ */
+ public boolean equals( Object other )
+ {
+ if ( !( other instanceof TableName ) ) { return false; }
+
+ TableName that = (TableName) other;
+
+ return this.getFullTableName().equals( that.getFullTableName() );
+ }
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableOperatorNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableOperatorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableOperatorNode.java Fri Sep 24 10:33:20 2004
@@ -1,877 +1,877 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.context.ContextManager;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-import org.apache.derby.iapi.sql.compile.Optimizable;
-import org.apache.derby.iapi.sql.compile.Visitable;
-import org.apache.derby.iapi.sql.compile.Visitor;
-import org.apache.derby.iapi.sql.compile.Optimizer;
-import org.apache.derby.iapi.sql.compile.OptimizableList;
-import org.apache.derby.iapi.sql.compile.CostEstimate;
-import org.apache.derby.iapi.sql.compile.OptimizerFactory;
-import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
-import org.apache.derby.iapi.sql.compile.C_NodeTypes;
-
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
-
-import org.apache.derby.iapi.util.JBitSet;
-
-import java.util.Properties;
-
-/**
- * A TableOperatorNode represents a relational operator like UNION, INTERSECT,
- * JOIN, etc. that takes two tables as parameters and returns a table. The
- * parameters it takes are represented as ResultSetNodes.
- *
- * Currently, all known table operators are binary operators, so there are no
- * subclasses of this node type called "BinaryTableOperatorNode" and
- * "UnaryTableOperatorNode".
- *
- * @author Jeff Lichtman
- */
-
-public abstract class TableOperatorNode extends FromTable
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- boolean nestedInParens;
- ResultSetNode leftResultSet;
- ResultSetNode rightResultSet;
- Optimizer leftOptimizer;
- Optimizer rightOptimizer;
- private boolean leftModifyAccessPathsDone;
- private boolean rightModifyAccessPathsDone;
-
- /**
- * Initializer for a TableOperatorNode.
- *
- * @param leftResultSet The ResultSetNode on the left side of this node
- * @param rightResultSet The ResultSetNode on the right side of this node
- * @param tableProperties Properties list associated with the table
- *
- * @exception StandardException Thrown on error
- */
- public void init(Object leftResultSet,
- Object rightResultSet,
- Object tableProperties)
- throws StandardException
- {
- /* correlationName is always null */
- init(null, tableProperties);
- this.leftResultSet = (ResultSetNode) leftResultSet;
- this.rightResultSet = (ResultSetNode) rightResultSet;
- }
-
- /**
- * @see Optimizable#modifyAccessPath
- *
- * @exception StandardException Thrown on error
- */
- public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException
- {
- boolean callModifyAccessPaths = false;
-
- if (leftResultSet instanceof FromTable)
- {
- if (leftOptimizer != null)
- leftOptimizer.modifyAccessPaths();
- else
- {
- leftResultSet =
- (ResultSetNode)
- ((FromTable) leftResultSet).modifyAccessPath(outerTables);
- }
- leftModifyAccessPathsDone = true;
- }
- else
- {
- callModifyAccessPaths = true;
- }
-
- if (rightResultSet instanceof FromTable)
- {
- if (rightOptimizer != null)
- rightOptimizer.modifyAccessPaths();
- else
- {
- rightResultSet =
- (ResultSetNode)
- ((FromTable) rightResultSet).modifyAccessPath(outerTables);
- }
- rightModifyAccessPathsDone = true;
- }
- else
- {
- callModifyAccessPaths = true;
- }
-
- if (callModifyAccessPaths)
- {
- return (Optimizable) modifyAccessPaths();
- }
- return this;
- }
-
- /** @see Optimizable#verifyProperties
- * @exception StandardException Thrown on error
- */
- public void verifyProperties(DataDictionary dDictionary)
- throws StandardException
- {
- if (leftResultSet instanceof Optimizable)
- {
- ((Optimizable) leftResultSet).verifyProperties(dDictionary);
- }
- if (rightResultSet instanceof Optimizable)
- {
- ((Optimizable) rightResultSet).verifyProperties(dDictionary);
- }
-
- super.verifyProperties(dDictionary);
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- return "nestedInParens: " + nestedInParens + "\n" +
- leftResultSet.toString() + "\n" +
- rightResultSet.toString() + "\n" +
- super.toString();
- }
- else
- {
- return "";
- }
- }
-
- /**
- * Prints the sub-nodes of this object. See QueryTreeNode.java for
- * how tree printing is supposed to work.
- *
- * @param depth The depth of this node in the tree
- *
- * @return Nothing
- */
-
- public void printSubNodes(int depth)
- {
- if (SanityManager.DEBUG)
- {
- super.printSubNodes(depth);
-
- if (leftResultSet != null)
- {
- printLabel(depth, "leftResultSet: ");
- leftResultSet.printSubNodes(depth + 1);
- }
-
- if (rightResultSet != null)
- {
- printLabel(depth, "rightResultSet: ");
- rightResultSet.printSubNodes(depth + 1);
- }
- }
- }
-
- /**
- * Get the leftResultSet from this node.
- *
- * @return ResultSetNode The leftResultSet from this node.
- */
- public ResultSetNode getLeftResultSet()
- {
- return leftResultSet;
- }
-
- /**
- * Get the rightResultSet from this node.
- *
- * @return ResultSetNode The rightResultSet from this node.
- */
- public ResultSetNode getRightResultSet()
- {
- return rightResultSet;
- }
-
- public ResultSetNode getLeftmostResultSet()
- {
- if (leftResultSet instanceof TableOperatorNode)
- {
- return ((TableOperatorNode) leftResultSet).getLeftmostResultSet();
- }
- else
- {
- return leftResultSet;
- }
- }
-
- public void setLeftmostResultSet(ResultSetNode newLeftResultSet)
- {
- if (leftResultSet instanceof TableOperatorNode)
- {
- ((TableOperatorNode) leftResultSet).setLeftmostResultSet(newLeftResultSet);
- }
- else
- {
- this.leftResultSet = newLeftResultSet;
- }
- }
-
- /**
- * Set the (query block) level (0-based) for this FromTable.
- *
- * @param level The query block level for this FromTable.
- *
- * @return Nothing
- */
- public void setLevel(int level)
- {
- super.setLevel(level);
- if (leftResultSet instanceof FromTable)
- {
- ((FromTable) leftResultSet).setLevel(level);
- }
- if (rightResultSet instanceof FromTable)
- {
- ((FromTable) rightResultSet).setLevel(level);
- }
- }
-
- /**
- * Return the exposed name for this table, which is the name that
- * can be used to refer to this table in the rest of the query.
- *
- * @return The exposed name for this table.
- */
-
- public String getExposedName()
- {
- return null;
- }
-
- /**
- * Mark whether or not this node is nested in parens. (Useful to parser
- * since some trees get created left deep and others right deep.)
- *
- * @param nestedInParens Whether or not this node is nested in parens.
- *
- * @return Nothing.
- */
- public void setNestedInParens(boolean nestedInParens)
- {
- this.nestedInParens = nestedInParens;
- }
-
- /**
- * Return whether or not the table operator for this node was
- * nested in parens in the query. (Useful to parser
- * since some trees get created left deep and others right deep.)
- *
- * @return boolean Whether or not this node was nested in parens.
- */
- public boolean getNestedInParens()
- {
- return nestedInParens;
- }
-
-
- /**
- * Bind the non VTI tables in this TableOperatorNode. This means getting
- * their TableDescriptors from the DataDictionary.
- * We will build an unbound RCL for this node. This RCL must be
- * "bound by hand" after the underlying left and right RCLs
- * are bound.
- *
- * @param dataDictionary The DataDictionary to use for binding
- * @param fromListParam FromList to use/append to.
- *
- * @return ResultSetNode Returns this.
- *
- * @exception StandardException Thrown on error
- */
-
- public ResultSetNode bindNonVTITables(DataDictionary dataDictionary,
- FromList fromListParam)
- throws StandardException
- {
- leftResultSet = leftResultSet.bindNonVTITables(dataDictionary, fromListParam);
- rightResultSet = rightResultSet.bindNonVTITables(dataDictionary, fromListParam);
- /* Assign the tableNumber */
- if (tableNumber == -1) // allow re-bind, in which case use old number
- tableNumber = getCompilerContext().getNextTableNumber();
-
- return this;
- }
-
- /**
- * Bind the VTI tables in this TableOperatorNode. This means getting
- * their TableDescriptors from the DataDictionary.
- * We will build an unbound RCL for this node. This RCL must be
- * "bound by hand" after the underlying left and right RCLs
- * are bound.
- *
- * @param fromListParam FromList to use/append to.
- *
- * @return ResultSetNode Returns this.
- *
- * @exception StandardException Thrown on error
- */
-
- public ResultSetNode bindVTITables(FromList fromListParam)
- throws StandardException
- {
- leftResultSet = leftResultSet.bindVTITables(fromListParam);
- rightResultSet = rightResultSet.bindVTITables(fromListParam);
-
- return this;
- }
-
- /**
- * Bind the expressions under this TableOperatorNode. This means
- * binding the sub-expressions, as well as figuring out what the
- * return type is for each expression.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
-
- public void bindExpressions(FromList fromListParam)
- throws StandardException
- {
- /*
- ** Parameters not allowed in select list of either side of union,
- ** except when the union is for a table constructor.
- */
- if ( ! (this instanceof UnionNode) ||
- ! ((UnionNode) this).tableConstructor())
- {
- leftResultSet.rejectParameters();
- rightResultSet.rejectParameters();
- }
-
- leftResultSet.bindExpressions(fromListParam);
- rightResultSet.bindExpressions(fromListParam);
- }
-
- /**
- * Check for (and reject) ? parameters directly under the ResultColumns.
- * This is done for SELECT statements. For TableOperatorNodes, we
- * simply pass the check through to the left and right children.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown if a ? parameter found
- * directly under a ResultColumn
- */
-
- public void rejectParameters() throws StandardException
- {
- leftResultSet.rejectParameters();
- rightResultSet.rejectParameters();
- }
-
- /**
- * Bind the expressions in this ResultSetNode if it has tables. This means binding the
- * sub-expressions, as well as figuring out what the return type is for
- * each expression.
- *
- * @param fromListParam FromList to use/append to.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
- public void bindExpressionsWithTables(FromList fromListParam)
- throws StandardException
- {
- /*
- ** Parameters not allowed in select list of either side of union,
- ** except when the union is for a table constructor.
- */
- if ( ! (this instanceof UnionNode) ||
- ! ((UnionNode) this).tableConstructor())
- {
- leftResultSet.rejectParameters();
- rightResultSet.rejectParameters();
- }
-
- leftResultSet.bindExpressionsWithTables(fromListParam);
- rightResultSet.bindExpressionsWithTables(fromListParam);
- }
-
- /**
- * Bind the result columns of this ResultSetNode when there is no
- * base table to bind them to. This is useful for SELECT statements,
- * where the result columns get their types from the expressions that
- * live under them.
- *
- * @param fromListParam FromList to use/append to.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
- public void bindResultColumns(FromList fromListParam)
- throws StandardException
- {
- leftResultSet.bindResultColumns(fromListParam);
- rightResultSet.bindResultColumns(fromListParam);
- }
-
- /**
- * Bind the result columns for this ResultSetNode to a base table.
- * This is useful for INSERT and UPDATE statements, where the
- * result columns get their types from the table being updated or
- * inserted into.
- * If a result column list is specified, then the verification that the
- * result column list does not contain any duplicates will be done when
- * binding them by name.
- *
- * @param targetTableDescriptor The TableDescriptor for the table being
- * updated or inserted into
- * @param targetColumnList For INSERT statements, the user
- * does not have to supply column
- * names (for example, "insert into t
- * values (1,2,3)". When this
- * parameter is null, it means that
- * the user did not supply column
- * names, and so the binding should
- * be done based on order. When it
- * is not null, it means do the binding
- * by name, not position.
- * @param statement Calling DMLStatementNode (Insert or Update)
- * @param fromListParam FromList to use/append to.
- *
- * @return Nothing
- *
- * @exception StandardException Thrown on error
- */
-
- public void bindResultColumns(TableDescriptor targetTableDescriptor,
- FromVTI targetVTI,
- ResultColumnList targetColumnList,
- DMLStatementNode statement,
- FromList fromListParam)
- throws StandardException
- {
- leftResultSet.bindResultColumns(targetTableDescriptor,
- targetVTI,
- targetColumnList,
- statement, fromListParam);
- rightResultSet.bindResultColumns(targetTableDescriptor,
- targetVTI,
- targetColumnList,
- statement, fromListParam);
- }
-
- /**
- * Determine whether or not the specified name is an exposed name in
- * the current query block.
- *
- * @param name The specified name to search for as an exposed name.
- * @param schemaName Schema name, if non-null.
- * @param exactMatch Whether or not we need an exact match on specified schema and table
- * names or match on table id.
- *
- * @return The FromTable, if any, with the exposed name.
- *
- * @exception StandardException Thrown on error
- */
- protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch)
- throws StandardException
- {
- FromTable result = leftResultSet.getFromTableByName(name, schemaName, exactMatch);
-
- /* We search both sides for a TableOperatorNode (join nodes)
- * but only the left side for a UnionNode.
- */
- if (result == null)
- {
- result = rightResultSet.getFromTableByName(name, schemaName, exactMatch);
- }
- return result;
- }
-
- /**
- * Put a ProjectRestrictNode on top of each FromTable in the FromList.
- * ColumnReferences must continue to point to the same ResultColumn, so
- * that ResultColumn must percolate up to the new PRN. However,
- * that ResultColumn will point to a new expression, a VirtualColumnNode,
- * which points to the FromTable and the ResultColumn that is the source for
- * the ColumnReference.
- * (The new PRN will have the original of the ResultColumnList and
- * the ResultColumns from that list. The FromTable will get shallow copies
- * of the ResultColumnList and its ResultColumns. ResultColumn.expression
- * will remain at the FromTable, with the PRN getting a new
- * VirtualColumnNode for each ResultColumn.expression.)
- * We then project out the non-referenced columns. If there are no referenced
- * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
- * whose expression is 1.
- *
- * @param numTables Number of tables in the DML Statement
- * @param gbl The group by list, if any
- * @param fromList The from list, if any
- *
- * @return The generated ProjectRestrictNode atop the original FromTable.
- *
- * @exception StandardException Thrown on error
- */
-
- public ResultSetNode preprocess(int numTables,
- GroupByList gbl,
- FromList fromList)
- throws StandardException
- {
- leftResultSet = leftResultSet.preprocess(numTables, gbl, fromList);
- /* If leftResultSet is a FromSubquery, then we must explicitly extract
- * out the subquery (flatten it). (SelectNodes have their own
- * method of flattening them.
- */
- if (leftResultSet instanceof FromSubquery)
- {
- leftResultSet = ((FromSubquery) leftResultSet).extractSubquery(numTables);
- }
- rightResultSet = rightResultSet.preprocess(numTables, gbl, fromList);
- /* If rightResultSet is a FromSubquery, then we must explicitly extract
- * out the subquery (flatten it). (SelectNodes have their own
- * method of flattening them.
- */
- if (rightResultSet instanceof FromSubquery)
- {
- rightResultSet = ((FromSubquery) rightResultSet).extractSubquery(numTables);
- }
-
- /* Build the referenced table map (left || right) */
- referencedTableMap = (JBitSet) leftResultSet.getReferencedTableMap().clone();
- referencedTableMap.or((JBitSet) rightResultSet.getReferencedTableMap());
- referencedTableMap.set(tableNumber);
-
- /* Only generate a PRN if this node is not a flattenable join node. */
- if (isFlattenableJoinNode())
- {
- return this;
- }
- else
- {
- /* Project out any unreferenced RCs before we generate the PRN.
- * NOTE: We have to do this at the end of preprocess since it has to
- * be from the bottom up. We can't do it until the join expression is
- * bound, since the join expression may contain column references that
- * are not referenced anywhere else above us.
- */
- projectResultColumns();
- return genProjectRestrict(numTables);
- }
- }
-
- /**
- * Find the unreferenced result columns and project them out. This is used in pre-processing joins
- * that are not flattened into the where clause.
- */
- void projectResultColumns() throws StandardException
- {
- resultColumns.doProjection();
- }
-
- /**
- * Set the referenced columns in the column list if it may not be correct.
- */
- void setReferencedColumns()
- {}
-
- /**
- * Optimize a TableOperatorNode.
- *
- * @param dataDictionary The DataDictionary to use for optimization
- * @param predicateList The PredicateList to apply.
- *
- * @return ResultSetNode The top of the optimized query tree
- *
- * @exception StandardException Thrown on error
- */
- public ResultSetNode optimize(DataDictionary dataDictionary,
- PredicateList predicateList,
- double outerRows)
- throws StandardException
- {
- /* Get an optimizer, so we can get a cost structure */
- Optimizer optimizer =
- getOptimizer(
- (FromList) getNodeFactory().getNode(
- C_NodeTypes.FROM_LIST,
- getNodeFactory().doJoinOrderOptimization(),
- this,
- getContextManager()),
- predicateList,
- dataDictionary,
- (RequiredRowOrdering) null);
-
- costEstimate = optimizer.newCostEstimate();
-
- /* RESOLVE: This is just a stub for now */
- leftResultSet = leftResultSet.optimize(
- dataDictionary,
- predicateList,
- outerRows);
- rightResultSet = rightResultSet.optimize(
- dataDictionary,
- predicateList,
- outerRows);
-
- /* The cost is the sum of the two child costs */
- costEstimate.setCost(leftResultSet.getCostEstimate().getEstimatedCost(),
- leftResultSet.getCostEstimate().rowCount(),
- leftResultSet.getCostEstimate().singleScanRowCount() +
- rightResultSet.getCostEstimate().singleScanRowCount());
-
- costEstimate.add(rightResultSet.costEstimate, costEstimate);
-
- return this;
- }
-
- /**
- * @see ResultSetNode#modifyAccessPaths
- *
- * @exception StandardException Thrown on error
- */
- public ResultSetNode modifyAccessPaths() throws StandardException
- {
- /* Beetle 4454 - union all with another union all would modify access
- * paths twice causing NullPointerException, make sure we don't
- * do this again, if we have already done it in modifyAccessPaths(outertables)
- */
- if (!leftModifyAccessPathsDone)
- {
- if (leftOptimizer != null)
- leftOptimizer.modifyAccessPaths();
- else
- leftResultSet = leftResultSet.modifyAccessPaths();
- }
- if (!rightModifyAccessPathsDone)
- {
- if (rightOptimizer != null)
- rightOptimizer.modifyAccessPaths();
- else
- rightResultSet = rightResultSet.modifyAccessPaths();
- }
- return this;
- }
-
- /**
- * Search to see if a query references the specifed table name.
- *
- * @param name Table name (String) to search for.
- * @param baseTable Whether or not name is for a base table
- *
- * @return true if found, else false
- *
- * @exception StandardException Thrown on error
- */
- public boolean referencesTarget(String name, boolean baseTable)
- throws StandardException
- {
- return leftResultSet.referencesTarget(name, baseTable) ||
- rightResultSet.referencesTarget(name, baseTable);
- }
-
- /**
- * Return true if the node references SESSION schema tables (temporary or permanent)
- *
- * @return true if references SESSION schema tables, else false
- *
- * @exception StandardException Thrown on error
- */
- public boolean referencesSessionSchema()
- throws StandardException
- {
- return leftResultSet.referencesSessionSchema() ||
- rightResultSet.referencesSessionSchema();
- }
-
- /**
- * Optimize a source result set to this table operator.
- *
- * @exception StandardException Thrown on error
- */
- protected ResultSetNode optimizeSource(
- Optimizer optimizer,
- ResultSetNode sourceResultSet,
- PredicateList predList,
- CostEstimate outerCost)
- throws StandardException
- {
- ResultSetNode retval;
-
- if (sourceResultSet instanceof FromTable)
- {
- FromList optList = (FromList) getNodeFactory().getNode(
- C_NodeTypes.FROM_LIST,
- getNodeFactory().doJoinOrderOptimization(),
- sourceResultSet,
- getContextManager());
-
- /* If there is no predicate list, create an empty one */
- if (predList == null)
- predList = (PredicateList) getNodeFactory().getNode(
- C_NodeTypes.PREDICATE_LIST,
- getContextManager());
-
- LanguageConnectionContext lcc = getLanguageConnectionContext();
- OptimizerFactory optimizerFactory = lcc.getOptimizerFactory();
- optimizer = optimizerFactory.getOptimizer(optList,
- predList,
- getDataDictionary(),
- (RequiredRowOrdering) null,
- getCompilerContext().getNumTables(),
- lcc);
-
- if (sourceResultSet == leftResultSet)
- {
- leftOptimizer = optimizer;
- }
- else if (sourceResultSet == rightResultSet)
- {
- rightOptimizer = optimizer;
- }
- else
- {
- if (SanityManager.DEBUG)
- SanityManager.THROWASSERT("Result set being optimized is neither left nor right");
- }
-
- /*
- ** Set the estimated number of outer rows from the outer part of
- ** the plan.
- */
- optimizer.setOuterRows(outerCost.rowCount());
-
- /* Optimize the underlying result set */
- while (optimizer.getNextPermutation())
- {
- while (optimizer.getNextDecoratedPermutation())
- {
- optimizer.costPermutation();
- }
- }
-
- retval = sourceResultSet;
- }
- else
- {
- retval = sourceResultSet.optimize(
- optimizer.getDataDictionary(),
- predList,
- outerCost.rowCount());
- }
-
- return retval;
- }
-
- /**
- * Decrement (query block) level (0-based) for
- * all of the tables in this ResultSet tree.
- * This is useful when flattening a subquery.
- *
- * @param decrement The amount to decrement by.
- *
- * @return Nothing;
- */
- void decrementLevel(int decrement)
- {
- leftResultSet.decrementLevel(decrement);
- rightResultSet.decrementLevel(decrement);
- }
-
- /**
- * Replace any DEFAULTs with the associated tree for the default.
- *
- * @param ttd The TableDescriptor for the target table.
- * @param tcl The RCL for the target table.
- *
- * @exception StandardException Thrown on error
- */
- void replaceDefaults(TableDescriptor ttd, ResultColumnList tcl)
- throws StandardException
- {
- leftResultSet.replaceDefaults(ttd, tcl);
- rightResultSet.replaceDefaults(ttd, tcl);
- }
-
- /**
- * Notify the underlying result set tree that the result is
- * ordering dependent. (For example, no bulk fetch on an index
- * if under an IndexRowToBaseRow.)
- *
- * @return Nothing.
- */
- void markOrderingDependent()
- {
- leftResultSet.markOrderingDependent();
- rightResultSet.markOrderingDependent();
- }
-
- /**
- * Accept a visitor, and call v.visit()
- * on child nodes as necessary.
- *
- * @param v the visitor
- *
- * @exception StandardException on error
- */
- public Visitable accept(Visitor v)
- throws StandardException
- {
- if (v.skipChildren(this))
- {
- return v.visit(this);
- }
-
- Visitable returnNode = super.accept(v);
-
- if (leftResultSet != null && !v.stopTraversal())
- {
- leftResultSet = (ResultSetNode)leftResultSet.accept(v);
- }
- if (rightResultSet != null && !v.stopTraversal())
- {
- rightResultSet = (ResultSetNode)rightResultSet.accept(v);
- }
- return returnNode;
- }
-
- /**
- * apparently something special needs to be done for me....
- */
- public boolean needsSpecialRCLBinding()
- {
- return true;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.context.ContextManager;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.compile.CompilerContext;
+import org.apache.derby.iapi.sql.compile.Optimizable;
+import org.apache.derby.iapi.sql.compile.Visitable;
+import org.apache.derby.iapi.sql.compile.Visitor;
+import org.apache.derby.iapi.sql.compile.Optimizer;
+import org.apache.derby.iapi.sql.compile.OptimizableList;
+import org.apache.derby.iapi.sql.compile.CostEstimate;
+import org.apache.derby.iapi.sql.compile.OptimizerFactory;
+import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+
+import org.apache.derby.iapi.util.JBitSet;
+
+import java.util.Properties;
+
+/**
+ * A TableOperatorNode represents a relational operator like UNION, INTERSECT,
+ * JOIN, etc. that takes two tables as parameters and returns a table. The
+ * parameters it takes are represented as ResultSetNodes.
+ *
+ * Currently, all known table operators are binary operators, so there are no
+ * subclasses of this node type called "BinaryTableOperatorNode" and
+ * "UnaryTableOperatorNode".
+ *
+ * @author Jeff Lichtman
+ */
+
+public abstract class TableOperatorNode extends FromTable
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ boolean nestedInParens;
+ ResultSetNode leftResultSet;
+ ResultSetNode rightResultSet;
+ Optimizer leftOptimizer;
+ Optimizer rightOptimizer;
+ private boolean leftModifyAccessPathsDone;
+ private boolean rightModifyAccessPathsDone;
+
+ /**
+ * Initializer for a TableOperatorNode.
+ *
+ * @param leftResultSet The ResultSetNode on the left side of this node
+ * @param rightResultSet The ResultSetNode on the right side of this node
+ * @param tableProperties Properties list associated with the table
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void init(Object leftResultSet,
+ Object rightResultSet,
+ Object tableProperties)
+ throws StandardException
+ {
+ /* correlationName is always null */
+ init(null, tableProperties);
+ this.leftResultSet = (ResultSetNode) leftResultSet;
+ this.rightResultSet = (ResultSetNode) rightResultSet;
+ }
+
+ /**
+ * @see Optimizable#modifyAccessPath
+ *
+ * @exception StandardException Thrown on error
+ */
+ public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException
+ {
+ boolean callModifyAccessPaths = false;
+
+ if (leftResultSet instanceof FromTable)
+ {
+ if (leftOptimizer != null)
+ leftOptimizer.modifyAccessPaths();
+ else
+ {
+ leftResultSet =
+ (ResultSetNode)
+ ((FromTable) leftResultSet).modifyAccessPath(outerTables);
+ }
+ leftModifyAccessPathsDone = true;
+ }
+ else
+ {
+ callModifyAccessPaths = true;
+ }
+
+ if (rightResultSet instanceof FromTable)
+ {
+ if (rightOptimizer != null)
+ rightOptimizer.modifyAccessPaths();
+ else
+ {
+ rightResultSet =
+ (ResultSetNode)
+ ((FromTable) rightResultSet).modifyAccessPath(outerTables);
+ }
+ rightModifyAccessPathsDone = true;
+ }
+ else
+ {
+ callModifyAccessPaths = true;
+ }
+
+ if (callModifyAccessPaths)
+ {
+ return (Optimizable) modifyAccessPaths();
+ }
+ return this;
+ }
+
+ /** @see Optimizable#verifyProperties
+ * @exception StandardException Thrown on error
+ */
+ public void verifyProperties(DataDictionary dDictionary)
+ throws StandardException
+ {
+ if (leftResultSet instanceof Optimizable)
+ {
+ ((Optimizable) leftResultSet).verifyProperties(dDictionary);
+ }
+ if (rightResultSet instanceof Optimizable)
+ {
+ ((Optimizable) rightResultSet).verifyProperties(dDictionary);
+ }
+
+ super.verifyProperties(dDictionary);
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ return "nestedInParens: " + nestedInParens + "\n" +
+ leftResultSet.toString() + "\n" +
+ rightResultSet.toString() + "\n" +
+ super.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Prints the sub-nodes of this object. See QueryTreeNode.java for
+ * how tree printing is supposed to work.
+ *
+ * @param depth The depth of this node in the tree
+ *
+ * @return Nothing
+ */
+
+ public void printSubNodes(int depth)
+ {
+ if (SanityManager.DEBUG)
+ {
+ super.printSubNodes(depth);
+
+ if (leftResultSet != null)
+ {
+ printLabel(depth, "leftResultSet: ");
+ leftResultSet.printSubNodes(depth + 1);
+ }
+
+ if (rightResultSet != null)
+ {
+ printLabel(depth, "rightResultSet: ");
+ rightResultSet.printSubNodes(depth + 1);
+ }
+ }
+ }
+
+ /**
+ * Get the leftResultSet from this node.
+ *
+ * @return ResultSetNode The leftResultSet from this node.
+ */
+ public ResultSetNode getLeftResultSet()
+ {
+ return leftResultSet;
+ }
+
+ /**
+ * Get the rightResultSet from this node.
+ *
+ * @return ResultSetNode The rightResultSet from this node.
+ */
+ public ResultSetNode getRightResultSet()
+ {
+ return rightResultSet;
+ }
+
+ public ResultSetNode getLeftmostResultSet()
+ {
+ if (leftResultSet instanceof TableOperatorNode)
+ {
+ return ((TableOperatorNode) leftResultSet).getLeftmostResultSet();
+ }
+ else
+ {
+ return leftResultSet;
+ }
+ }
+
+ public void setLeftmostResultSet(ResultSetNode newLeftResultSet)
+ {
+ if (leftResultSet instanceof TableOperatorNode)
+ {
+ ((TableOperatorNode) leftResultSet).setLeftmostResultSet(newLeftResultSet);
+ }
+ else
+ {
+ this.leftResultSet = newLeftResultSet;
+ }
+ }
+
+ /**
+ * Set the (query block) level (0-based) for this FromTable.
+ *
+ * @param level The query block level for this FromTable.
+ *
+ * @return Nothing
+ */
+ public void setLevel(int level)
+ {
+ super.setLevel(level);
+ if (leftResultSet instanceof FromTable)
+ {
+ ((FromTable) leftResultSet).setLevel(level);
+ }
+ if (rightResultSet instanceof FromTable)
+ {
+ ((FromTable) rightResultSet).setLevel(level);
+ }
+ }
+
+ /**
+ * Return the exposed name for this table, which is the name that
+ * can be used to refer to this table in the rest of the query.
+ *
+ * @return The exposed name for this table.
+ */
+
+ public String getExposedName()
+ {
+ return null;
+ }
+
+ /**
+ * Mark whether or not this node is nested in parens. (Useful to parser
+ * since some trees get created left deep and others right deep.)
+ *
+ * @param nestedInParens Whether or not this node is nested in parens.
+ *
+ * @return Nothing.
+ */
+ public void setNestedInParens(boolean nestedInParens)
+ {
+ this.nestedInParens = nestedInParens;
+ }
+
+ /**
+ * Return whether or not the table operator for this node was
+ * nested in parens in the query. (Useful to parser
+ * since some trees get created left deep and others right deep.)
+ *
+ * @return boolean Whether or not this node was nested in parens.
+ */
+ public boolean getNestedInParens()
+ {
+ return nestedInParens;
+ }
+
+
+ /**
+ * Bind the non VTI tables in this TableOperatorNode. This means getting
+ * their TableDescriptors from the DataDictionary.
+ * We will build an unbound RCL for this node. This RCL must be
+ * "bound by hand" after the underlying left and right RCLs
+ * are bound.
+ *
+ * @param dataDictionary The DataDictionary to use for binding
+ * @param fromListParam FromList to use/append to.
+ *
+ * @return ResultSetNode Returns this.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ResultSetNode bindNonVTITables(DataDictionary dataDictionary,
+ FromList fromListParam)
+ throws StandardException
+ {
+ leftResultSet = leftResultSet.bindNonVTITables(dataDictionary, fromListParam);
+ rightResultSet = rightResultSet.bindNonVTITables(dataDictionary, fromListParam);
+ /* Assign the tableNumber */
+ if (tableNumber == -1) // allow re-bind, in which case use old number
+ tableNumber = getCompilerContext().getNextTableNumber();
+
+ return this;
+ }
+
+ /**
+ * Bind the VTI tables in this TableOperatorNode. This means getting
+ * their TableDescriptors from the DataDictionary.
+ * We will build an unbound RCL for this node. This RCL must be
+ * "bound by hand" after the underlying left and right RCLs
+ * are bound.
+ *
+ * @param fromListParam FromList to use/append to.
+ *
+ * @return ResultSetNode Returns this.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ResultSetNode bindVTITables(FromList fromListParam)
+ throws StandardException
+ {
+ leftResultSet = leftResultSet.bindVTITables(fromListParam);
+ rightResultSet = rightResultSet.bindVTITables(fromListParam);
+
+ return this;
+ }
+
+ /**
+ * Bind the expressions under this TableOperatorNode. This means
+ * binding the sub-expressions, as well as figuring out what the
+ * return type is for each expression.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void bindExpressions(FromList fromListParam)
+ throws StandardException
+ {
+ /*
+ ** Parameters not allowed in select list of either side of union,
+ ** except when the union is for a table constructor.
+ */
+ if ( ! (this instanceof UnionNode) ||
+ ! ((UnionNode) this).tableConstructor())
+ {
+ leftResultSet.rejectParameters();
+ rightResultSet.rejectParameters();
+ }
+
+ leftResultSet.bindExpressions(fromListParam);
+ rightResultSet.bindExpressions(fromListParam);
+ }
+
+ /**
+ * Check for (and reject) ? parameters directly under the ResultColumns.
+ * This is done for SELECT statements. For TableOperatorNodes, we
+ * simply pass the check through to the left and right children.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown if a ? parameter found
+ * directly under a ResultColumn
+ */
+
+ public void rejectParameters() throws StandardException
+ {
+ leftResultSet.rejectParameters();
+ rightResultSet.rejectParameters();
+ }
+
+ /**
+ * Bind the expressions in this ResultSetNode if it has tables. This means binding the
+ * sub-expressions, as well as figuring out what the return type is for
+ * each expression.
+ *
+ * @param fromListParam FromList to use/append to.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void bindExpressionsWithTables(FromList fromListParam)
+ throws StandardException
+ {
+ /*
+ ** Parameters not allowed in select list of either side of union,
+ ** except when the union is for a table constructor.
+ */
+ if ( ! (this instanceof UnionNode) ||
+ ! ((UnionNode) this).tableConstructor())
+ {
+ leftResultSet.rejectParameters();
+ rightResultSet.rejectParameters();
+ }
+
+ leftResultSet.bindExpressionsWithTables(fromListParam);
+ rightResultSet.bindExpressionsWithTables(fromListParam);
+ }
+
+ /**
+ * Bind the result columns of this ResultSetNode when there is no
+ * base table to bind them to. This is useful for SELECT statements,
+ * where the result columns get their types from the expressions that
+ * live under them.
+ *
+ * @param fromListParam FromList to use/append to.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+ public void bindResultColumns(FromList fromListParam)
+ throws StandardException
+ {
+ leftResultSet.bindResultColumns(fromListParam);
+ rightResultSet.bindResultColumns(fromListParam);
+ }
+
+ /**
+ * Bind the result columns for this ResultSetNode to a base table.
+ * This is useful for INSERT and UPDATE statements, where the
+ * result columns get their types from the table being updated or
+ * inserted into.
+ * If a result column list is specified, then the verification that the
+ * result column list does not contain any duplicates will be done when
+ * binding them by name.
+ *
+ * @param targetTableDescriptor The TableDescriptor for the table being
+ * updated or inserted into
+ * @param targetColumnList For INSERT statements, the user
+ * does not have to supply column
+ * names (for example, "insert into t
+ * values (1,2,3)". When this
+ * parameter is null, it means that
+ * the user did not supply column
+ * names, and so the binding should
+ * be done based on order. When it
+ * is not null, it means do the binding
+ * by name, not position.
+ * @param statement Calling DMLStatementNode (Insert or Update)
+ * @param fromListParam FromList to use/append to.
+ *
+ * @return Nothing
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void bindResultColumns(TableDescriptor targetTableDescriptor,
+ FromVTI targetVTI,
+ ResultColumnList targetColumnList,
+ DMLStatementNode statement,
+ FromList fromListParam)
+ throws StandardException
+ {
+ leftResultSet.bindResultColumns(targetTableDescriptor,
+ targetVTI,
+ targetColumnList,
+ statement, fromListParam);
+ rightResultSet.bindResultColumns(targetTableDescriptor,
+ targetVTI,
+ targetColumnList,
+ statement, fromListParam);
+ }
+
+ /**
+ * Determine whether or not the specified name is an exposed name in
+ * the current query block.
+ *
+ * @param name The specified name to search for as an exposed name.
+ * @param schemaName Schema name, if non-null.
+ * @param exactMatch Whether or not we need an exact match on specified schema and table
+ * names or match on table id.
+ *
+ * @return The FromTable, if any, with the exposed name.
+ *
+ * @exception StandardException Thrown on error
+ */
+ protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch)
+ throws StandardException
+ {
+ FromTable result = leftResultSet.getFromTableByName(name, schemaName, exactMatch);
+
+ /* We search both sides for a TableOperatorNode (join nodes)
+ * but only the left side for a UnionNode.
+ */
+ if (result == null)
+ {
+ result = rightResultSet.getFromTableByName(name, schemaName, exactMatch);
+ }
+ return result;
+ }
+
+ /**
+ * Put a ProjectRestrictNode on top of each FromTable in the FromList.
+ * ColumnReferences must continue to point to the same ResultColumn, so
+ * that ResultColumn must percolate up to the new PRN. However,
+ * that ResultColumn will point to a new expression, a VirtualColumnNode,
+ * which points to the FromTable and the ResultColumn that is the source for
+ * the ColumnReference.
+ * (The new PRN will have the original of the ResultColumnList and
+ * the ResultColumns from that list. The FromTable will get shallow copies
+ * of the ResultColumnList and its ResultColumns. ResultColumn.expression
+ * will remain at the FromTable, with the PRN getting a new
+ * VirtualColumnNode for each ResultColumn.expression.)
+ * We then project out the non-referenced columns. If there are no referenced
+ * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
+ * whose expression is 1.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param gbl The group by list, if any
+ * @param fromList The from list, if any
+ *
+ * @return The generated ProjectRestrictNode atop the original FromTable.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ResultSetNode preprocess(int numTables,
+ GroupByList gbl,
+ FromList fromList)
+ throws StandardException
+ {
+ leftResultSet = leftResultSet.preprocess(numTables, gbl, fromList);
+ /* If leftResultSet is a FromSubquery, then we must explicitly extract
+ * out the subquery (flatten it). (SelectNodes have their own
+ * method of flattening them.
+ */
+ if (leftResultSet instanceof FromSubquery)
+ {
+ leftResultSet = ((FromSubquery) leftResultSet).extractSubquery(numTables);
+ }
+ rightResultSet = rightResultSet.preprocess(numTables, gbl, fromList);
+ /* If rightResultSet is a FromSubquery, then we must explicitly extract
+ * out the subquery (flatten it). (SelectNodes have their own
+ * method of flattening them.
+ */
+ if (rightResultSet instanceof FromSubquery)
+ {
+ rightResultSet = ((FromSubquery) rightResultSet).extractSubquery(numTables);
+ }
+
+ /* Build the referenced table map (left || right) */
+ referencedTableMap = (JBitSet) leftResultSet.getReferencedTableMap().clone();
+ referencedTableMap.or((JBitSet) rightResultSet.getReferencedTableMap());
+ referencedTableMap.set(tableNumber);
+
+ /* Only generate a PRN if this node is not a flattenable join node. */
+ if (isFlattenableJoinNode())
+ {
+ return this;
+ }
+ else
+ {
+ /* Project out any unreferenced RCs before we generate the PRN.
+ * NOTE: We have to do this at the end of preprocess since it has to
+ * be from the bottom up. We can't do it until the join expression is
+ * bound, since the join expression may contain column references that
+ * are not referenced anywhere else above us.
+ */
+ projectResultColumns();
+ return genProjectRestrict(numTables);
+ }
+ }
+
+ /**
+ * Find the unreferenced result columns and project them out. This is used in pre-processing joins
+ * that are not flattened into the where clause.
+ */
+ void projectResultColumns() throws StandardException
+ {
+ resultColumns.doProjection();
+ }
+
+ /**
+ * Set the referenced columns in the column list if it may not be correct.
+ */
+ void setReferencedColumns()
+ {}
+
+ /**
+ * Optimize a TableOperatorNode.
+ *
+ * @param dataDictionary The DataDictionary to use for optimization
+ * @param predicateList The PredicateList to apply.
+ *
+ * @return ResultSetNode The top of the optimized query tree
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ResultSetNode optimize(DataDictionary dataDictionary,
+ PredicateList predicateList,
+ double outerRows)
+ throws StandardException
+ {
+ /* Get an optimizer, so we can get a cost structure */
+ Optimizer optimizer =
+ getOptimizer(
+ (FromList) getNodeFactory().getNode(
+ C_NodeTypes.FROM_LIST,
+ getNodeFactory().doJoinOrderOptimization(),
+ this,
+ getContextManager()),
+ predicateList,
+ dataDictionary,
+ (RequiredRowOrdering) null);
+
+ costEstimate = optimizer.newCostEstimate();
+
+ /* RESOLVE: This is just a stub for now */
+ leftResultSet = leftResultSet.optimize(
+ dataDictionary,
+ predicateList,
+ outerRows);
+ rightResultSet = rightResultSet.optimize(
+ dataDictionary,
+ predicateList,
+ outerRows);
+
+ /* The cost is the sum of the two child costs */
+ costEstimate.setCost(leftResultSet.getCostEstimate().getEstimatedCost(),
+ leftResultSet.getCostEstimate().rowCount(),
+ leftResultSet.getCostEstimate().singleScanRowCount() +
+ rightResultSet.getCostEstimate().singleScanRowCount());
+
+ costEstimate.add(rightResultSet.costEstimate, costEstimate);
+
+ return this;
+ }
+
+ /**
+ * @see ResultSetNode#modifyAccessPaths
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ResultSetNode modifyAccessPaths() throws StandardException
+ {
+ /* Beetle 4454 - union all with another union all would modify access
+ * paths twice causing NullPointerException, make sure we don't
+ * do this again, if we have already done it in modifyAccessPaths(outertables)
+ */
+ if (!leftModifyAccessPathsDone)
+ {
+ if (leftOptimizer != null)
+ leftOptimizer.modifyAccessPaths();
+ else
+ leftResultSet = leftResultSet.modifyAccessPaths();
+ }
+ if (!rightModifyAccessPathsDone)
+ {
+ if (rightOptimizer != null)
+ rightOptimizer.modifyAccessPaths();
+ else
+ rightResultSet = rightResultSet.modifyAccessPaths();
+ }
+ return this;
+ }
+
+ /**
+ * Search to see if a query references the specifed table name.
+ *
+ * @param name Table name (String) to search for.
+ * @param baseTable Whether or not name is for a base table
+ *
+ * @return true if found, else false
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean referencesTarget(String name, boolean baseTable)
+ throws StandardException
+ {
+ return leftResultSet.referencesTarget(name, baseTable) ||
+ rightResultSet.referencesTarget(name, baseTable);
+ }
+
+ /**
+ * Return true if the node references SESSION schema tables (temporary or permanent)
+ *
+ * @return true if references SESSION schema tables, else false
+ *
+ * @exception StandardException Thrown on error
+ */
+ public boolean referencesSessionSchema()
+ throws StandardException
+ {
+ return leftResultSet.referencesSessionSchema() ||
+ rightResultSet.referencesSessionSchema();
+ }
+
+ /**
+ * Optimize a source result set to this table operator.
+ *
+ * @exception StandardException Thrown on error
+ */
+ protected ResultSetNode optimizeSource(
+ Optimizer optimizer,
+ ResultSetNode sourceResultSet,
+ PredicateList predList,
+ CostEstimate outerCost)
+ throws StandardException
+ {
+ ResultSetNode retval;
+
+ if (sourceResultSet instanceof FromTable)
+ {
+ FromList optList = (FromList) getNodeFactory().getNode(
+ C_NodeTypes.FROM_LIST,
+ getNodeFactory().doJoinOrderOptimization(),
+ sourceResultSet,
+ getContextManager());
+
+ /* If there is no predicate list, create an empty one */
+ if (predList == null)
+ predList = (PredicateList) getNodeFactory().getNode(
+ C_NodeTypes.PREDICATE_LIST,
+ getContextManager());
+
+ LanguageConnectionContext lcc = getLanguageConnectionContext();
+ OptimizerFactory optimizerFactory = lcc.getOptimizerFactory();
+ optimizer = optimizerFactory.getOptimizer(optList,
+ predList,
+ getDataDictionary(),
+ (RequiredRowOrdering) null,
+ getCompilerContext().getNumTables(),
+ lcc);
+
+ if (sourceResultSet == leftResultSet)
+ {
+ leftOptimizer = optimizer;
+ }
+ else if (sourceResultSet == rightResultSet)
+ {
+ rightOptimizer = optimizer;
+ }
+ else
+ {
+ if (SanityManager.DEBUG)
+ SanityManager.THROWASSERT("Result set being optimized is neither left nor right");
+ }
+
+ /*
+ ** Set the estimated number of outer rows from the outer part of
+ ** the plan.
+ */
+ optimizer.setOuterRows(outerCost.rowCount());
+
+ /* Optimize the underlying result set */
+ while (optimizer.getNextPermutation())
+ {
+ while (optimizer.getNextDecoratedPermutation())
+ {
+ optimizer.costPermutation();
+ }
+ }
+
+ retval = sourceResultSet;
+ }
+ else
+ {
+ retval = sourceResultSet.optimize(
+ optimizer.getDataDictionary(),
+ predList,
+ outerCost.rowCount());
+ }
+
+ return retval;
+ }
+
+ /**
+ * Decrement (query block) level (0-based) for
+ * all of the tables in this ResultSet tree.
+ * This is useful when flattening a subquery.
+ *
+ * @param decrement The amount to decrement by.
+ *
+ * @return Nothing;
+ */
+ void decrementLevel(int decrement)
+ {
+ leftResultSet.decrementLevel(decrement);
+ rightResultSet.decrementLevel(decrement);
+ }
+
+ /**
+ * Replace any DEFAULTs with the associated tree for the default.
+ *
+ * @param ttd The TableDescriptor for the target table.
+ * @param tcl The RCL for the target table.
+ *
+ * @exception StandardException Thrown on error
+ */
+ void replaceDefaults(TableDescriptor ttd, ResultColumnList tcl)
+ throws StandardException
+ {
+ leftResultSet.replaceDefaults(ttd, tcl);
+ rightResultSet.replaceDefaults(ttd, tcl);
+ }
+
+ /**
+ * Notify the underlying result set tree that the result is
+ * ordering dependent. (For example, no bulk fetch on an index
+ * if under an IndexRowToBaseRow.)
+ *
+ * @return Nothing.
+ */
+ void markOrderingDependent()
+ {
+ leftResultSet.markOrderingDependent();
+ rightResultSet.markOrderingDependent();
+ }
+
+ /**
+ * Accept a visitor, and call v.visit()
+ * on child nodes as necessary.
+ *
+ * @param v the visitor
+ *
+ * @exception StandardException on error
+ */
+ public Visitable accept(Visitor v)
+ throws StandardException
+ {
+ if (v.skipChildren(this))
+ {
+ return v.visit(this);
+ }
+
+ Visitable returnNode = super.accept(v);
+
+ if (leftResultSet != null && !v.stopTraversal())
+ {
+ leftResultSet = (ResultSetNode)leftResultSet.accept(v);
+ }
+ if (rightResultSet != null && !v.stopTraversal())
+ {
+ rightResultSet = (ResultSetNode)rightResultSet.accept(v);
+ }
+ return returnNode;
+ }
+
+ /**
+ * apparently something special needs to be done for me....
+ */
+ public boolean needsSpecialRCLBinding()
+ {
+ return true;
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TernaryOperatorNode.java Fri Sep 24 10:33:20 2004
@@ -1,827 +1,827 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-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.services.sanity.SanityManager;
-import org.apache.derby.iapi.sql.compile.C_NodeTypes;
-import org.apache.derby.iapi.sql.compile.Visitable;
-import org.apache.derby.iapi.sql.compile.Visitor;
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.store.access.Qualifier;
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-import org.apache.derby.iapi.types.NumberDataValue;
-import org.apache.derby.iapi.types.StringDataValue;
-import org.apache.derby.iapi.types.TypeId;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-import org.apache.derby.iapi.store.access.Qualifier;
-import org.apache.derby.iapi.reference.SQLState;
-import org.apache.derby.iapi.reference.ClassName;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.iapi.util.JBitSet;
-
-import java.lang.reflect.Modifier;
-
-import java.sql.Types;
-import java.util.Vector;
-/**
- * A TernaryOperatorNode represents a built-in ternary operators.
- * This covers built-in functions like substr().
- * Java operators are not represented here: the JSQL language allows Java
- * methods to be called from expressions, but not Java operators.
- *
- * @author Jerry Brenner
- */
-
-public class TernaryOperatorNode extends ValueNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- String operator;
- String methodName;
- int operatorType;
- ValueNode receiver;
-
- ValueNode leftOperand;
- ValueNode rightOperand;
-
- String resultInterfaceType;
- String receiverInterfaceType;
- String leftInterfaceType;
- String rightInterfaceType;
- int trimType;
-
- public static final int TRIM = 0;
- public static final int LOCATE = 1;
- public static final int SUBSTRING = 2;
- public static final int LIKE = 3;
- static final String[] TernaryOperators = {"trim", "LOCATE", "substring", "like"};
- static final String[] TernaryMethodNames = {"trim", "locate", "substring", "like"};
- static final String[] TernaryResultType = {ClassName.StringDataValue,
- ClassName.NumberDataValue,
- ClassName.ConcatableDataValue,
- ClassName.BooleanDataValue};
- static final String[][] TernaryArgType = {
- {ClassName.StringDataValue, ClassName.StringDataValue, "java.lang.Integer"},
- {ClassName.StringDataValue, ClassName.StringDataValue, ClassName.NumberDataValue},
- {ClassName.ConcatableDataValue, ClassName.NumberDataValue, ClassName.NumberDataValue},
- {ClassName.DataValueDescriptor, ClassName.DataValueDescriptor, ClassName.DataValueDescriptor}
- };
-
- /**
- * Initializer for a TernaryOperatorNode
- *
- * @param receiver The receiver (eg, string being operated on in substr())
- * @param leftOperand The left operand of the node
- * @param rightOperand The right operand of the node
- * @param operatorType The type of the operand
- */
-
- public void init(
- Object receiver,
- Object leftOperand,
- Object rightOperand,
- Object operatorType,
- Object trimType)
- {
- this.receiver = (ValueNode) receiver;
- this.leftOperand = (ValueNode) leftOperand;
- this.rightOperand = (ValueNode) rightOperand;
- this.operatorType = ((Integer) operatorType).intValue();
- this.operator = (String) TernaryOperators[this.operatorType];
- this.methodName = (String) TernaryMethodNames[this.operatorType];
- this.resultInterfaceType = (String) TernaryResultType[this.operatorType];
- this.receiverInterfaceType = (String) TernaryArgType[this.operatorType][0];
- this.leftInterfaceType = (String) TernaryArgType[this.operatorType][1];
- this.rightInterfaceType = (String) TernaryArgType[this.operatorType][2];
- if (trimType != null)
- this.trimType = ((Integer) trimType).intValue();
- }
-
- /**
- * Convert this object to a String. See comments in QueryTreeNode.java
- * for how this should be done for tree printing.
- *
- * @return This object as a String
- */
-
- public String toString()
- {
- if (SanityManager.DEBUG)
- {
- return "operator: " + operator + "\n" +
- "methodName: " + methodName + "\n" +
- "resultInterfaceType: " + resultInterfaceType + "\n" +
- "receiverInterfaceType: " + receiverInterfaceType + "\n" +
- "leftInterfaceType: " + leftInterfaceType + "\n" +
- "rightInterfaceType: " + rightInterfaceType + "\n" +
- super.toString();
- }
- else
- {
- return "";
- }
- }
-
- /**
- * Set the clause that this node appears in.
- *
- * @param clause The clause that this node appears in.
- *
- * @return Nothing.
- */
- public void setClause(int clause)
- {
- super.setClause(clause);
- receiver.setClause(clause);
- leftOperand.setClause(clause);
- if (rightOperand != null)
- {
- rightOperand.setClause(clause);
- }
- }
-
- /**
- * Prints the sub-nodes of this object. See QueryTreeNode.java for
- * how tree printing is supposed to work.
- *
- * @param depth The depth of this node in the tree
- *
- * @return Nothing
- */
-
- public void printSubNodes(int depth)
- {
- if (SanityManager.DEBUG)
- {
- super.printSubNodes(depth);
-
- if (receiver != null)
- {
- printLabel(depth, "receiver: ");
- receiver.treePrint(depth + 1);
- }
-
- if (leftOperand != null)
- {
- printLabel(depth, "leftOperand: ");
- leftOperand.treePrint(depth + 1);
- }
-
- if (rightOperand != null)
- {
- printLabel(depth, "rightOperand: ");
- rightOperand.treePrint(depth + 1);
- }
- }
- }
-
- /**
- * Bind this expression. This means binding the sub-expressions,
- * as well as figuring out what the return type is for this expression.
- *
- * @param fromList The FROM list for the query this
- * expression is in, for binding columns.
- * @param subqueryList The subquery list being built as we find SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
-
- public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- receiver = receiver.bindExpression(fromList, subqueryList,
- aggregateVector);
- leftOperand = leftOperand.bindExpression(fromList, subqueryList,
- aggregateVector);
-
- if (rightOperand != null)
- {
- rightOperand = rightOperand.bindExpression(fromList, subqueryList,
- aggregateVector);
- }
- if (operatorType == TRIM)
- trimBind();
- else if (operatorType == LOCATE)
- locateBind();
- else if (operatorType == SUBSTRING)
- substrBind();
-
- return this;
- }
-
- /**
- * Preprocess an expression tree. We do a number of transformations
- * here (including subqueries, IN lists, LIKE and BETWEEN) plus
- * subquery flattening.
- * NOTE: This is done before the outer ResultSetNode is preprocessed.
- *
- * @param numTables Number of tables in the DML Statement
- * @param outerFromList FromList from outer query block
- * @param outerSubqueryList SubqueryList from outer query block
- * @param outerPredicateList PredicateList from outer query block
- *
- * @return The modified expression
- *
- * @exception StandardException Thrown on error
- */
- public ValueNode preprocess(int numTables,
- FromList outerFromList,
- SubqueryList outerSubqueryList,
- PredicateList outerPredicateList)
- throws StandardException
- {
- receiver = receiver.preprocess(numTables,
- outerFromList, outerSubqueryList,
- outerPredicateList);
-
- leftOperand = leftOperand.preprocess(numTables,
- outerFromList, outerSubqueryList,
- outerPredicateList);
- if (rightOperand != null)
- {
- rightOperand = rightOperand.preprocess(numTables,
- outerFromList, outerSubqueryList,
- outerPredicateList);
- }
- return this;
- }
- /**
- * Do code generation for this ternary operator.
- *
- * @param acb The ExpressionClassBuilder for the class we're generating
- * @param mb The method the expression will go into
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateExpression(ExpressionClassBuilder acb,
- MethodBuilder mb)
- throws StandardException
- {
- int nargs = 0;
- String receiverType = null;
-
- /* Allocate an object for re-use to hold the result of the operator */
- LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultInterfaceType);
-
- receiver.generateExpression(acb, mb);
- if (operatorType == TRIM)
- {
- mb.push(trimType);
- mb.getField(field);
- nargs = 2;
- receiverType = receiverInterfaceType;
- }
- else if (operatorType == LOCATE)
- {
- leftOperand.generateExpression(acb, mb);
- mb.upCast(leftInterfaceType);
- rightOperand.generateExpression(acb, mb);
- mb.upCast(rightInterfaceType);
- mb.getField(field);
- nargs = 3;
-
- }
- else if (operatorType == SUBSTRING)
- {
- leftOperand.generateExpression(acb, mb);
- mb.upCast(leftInterfaceType);
- if (rightOperand != null)
- {
- rightOperand.generateExpression(acb, mb);
- mb.upCast(rightInterfaceType);
- }
- else
- {
- mb.pushNull(rightInterfaceType);
- }
-
- mb.getField(field); // third arg
- mb.push(receiver.getTypeServices().getMaximumWidth());
- nargs = 4;
- receiverType = receiverInterfaceType;
- }
- mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultInterfaceType, nargs);
-
- /*
- ** Store the result of the method call in the field, so we can re-use
- ** the object.
- */
- mb.putField(field);
- }
-
- /**
- * Set the leftOperand to the specified ValueNode
- *
- * @param newLeftOperand The new leftOperand
- *
- * @return None.
- */
- public void setLeftOperand(ValueNode newLeftOperand)
- {
- leftOperand = newLeftOperand;
- }
-
- /**
- * Get the leftOperand
- *
- * @return The current leftOperand.
- */
- public ValueNode getLeftOperand()
- {
- return leftOperand;
- }
-
- /**
- * Set the rightOperand to the specified ValueNode
- *
- * @param newRightOperand The new rightOperand
- *
- * @return None.
- */
- public void setRightOperand(ValueNode newRightOperand)
- {
- rightOperand = newRightOperand;
- }
-
- /**
- * Get the rightOperand
- *
- * @return The current rightOperand.
- */
- public ValueNode getRightOperand()
- {
- return rightOperand;
- }
-
- /**
- * Categorize this predicate. Initially, this means
- * building a bit map of the referenced tables for each predicate.
- * If the source of this ColumnReference (at the next underlying level)
- * is not a ColumnReference or a VirtualColumnNode then this predicate
- * will not be pushed down.
- *
- * For example, in:
- * select * from (select 1 from s) a (x) where x = 1
- * we will not push down x = 1.
- * NOTE: It would be easy to handle the case of a constant, but if the
- * inner SELECT returns an arbitrary expression, then we would have to copy
- * that tree into the pushed predicate, and that tree could contain
- * subqueries and method calls.
- * RESOLVE - revisit this issue once we have views.
- *
- * @param referencedTabs JBitSet with bit map of referenced FromTables
- * @param simplePredsOnly Whether or not to consider method
- * calls, field references and conditional nodes
- * when building bit map
- *
- * @return boolean Whether or not source.expression is a ColumnReference
- * or a VirtualColumnNode.
- * @exception StandardException Thrown on error
- */
- public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
- throws StandardException
- {
- boolean pushable;
- pushable = receiver.categorize(referencedTabs, simplePredsOnly);
- pushable = (leftOperand.categorize(referencedTabs, simplePredsOnly) && pushable);
- if (rightOperand != null)
- {
- pushable = (rightOperand.categorize(referencedTabs, simplePredsOnly) && pushable);
- }
- return pushable;
- }
-
- /**
- * Remap all ColumnReferences in this tree to be clones of the
- * underlying expression.
- *
- * @return ValueNode The remapped expression tree.
- *
- * @exception StandardException Thrown on error
- */
- public ValueNode remapColumnReferencesToExpressions()
- throws StandardException
- {
- receiver = receiver.remapColumnReferencesToExpressions();
- leftOperand = leftOperand.remapColumnReferencesToExpressions();
- if (rightOperand != null)
- {
- rightOperand = rightOperand.remapColumnReferencesToExpressions();
- }
- return this;
- }
-
- /**
- * Return whether or not this expression tree represents a constant expression.
- *
- * @return Whether or not this expression tree represents a constant expression.
- */
- public boolean isConstantExpression()
- {
- return (receiver.isConstantExpression() &&
- leftOperand.isConstantExpression() &&
- (rightOperand == null || rightOperand.isConstantExpression()));
- }
-
- /** @see ValueNode#constantExpression */
- public boolean constantExpression(PredicateList whereClause)
- {
- return (receiver.constantExpression(whereClause) &&
- leftOperand.constantExpression(whereClause) &&
- (rightOperand == null ||
- rightOperand.constantExpression(whereClause)));
- }
-
- /**
- * Accept a visitor, and call v.visit()
- * on child nodes as necessary.
- *
- * @param v the visitor
- *
- * @exception StandardException on error
- */
- public Visitable accept(Visitor v)
- throws StandardException
- {
- Visitable returnNode = v.visit(this);
-
- if (v.skipChildren(this))
- {
- return returnNode;
- }
-
- if (receiver != null && !v.stopTraversal())
- {
- receiver = (ValueNode)receiver.accept(v);
- }
-
- if (leftOperand != null && !v.stopTraversal())
- {
- leftOperand = (ValueNode)leftOperand.accept(v);
- }
-
- if (rightOperand != null && !v.stopTraversal())
- {
- rightOperand = (ValueNode)rightOperand.accept(v);
- }
-
- return returnNode;
- }
- /**
- * Bind trim expression.
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
-
- private ValueNode trimBind()
- throws StandardException
- {
- TypeId receiverType;
- TypeId resultType = TypeId.getBuiltInTypeId(Types.VARCHAR);
-
- // handle parameters here
-
- /* Is there a ? parameter for the receiver? */
- if (receiver.isParameterNode())
- {
- /*
- ** According to the SQL standard, if trim has a ? receiver,
- ** its type is varchar with the implementation-defined maximum length
- ** for a varchar.
- */
-
- ((ParameterNode) receiver).setDescriptor(getVarcharDescriptor());
- }
-
- /* Is there a ? parameter on the left? */
- if (leftOperand.isParameterNode())
- {
- /* Set the left operand type to varchar. */
- ((ParameterNode) leftOperand).setDescriptor(getVarcharDescriptor());
- }
-
- bindToBuiltIn();
-
- /*
- ** Check the type of the receiver - this function is allowed only on
- ** string value types.
- */
- receiverType = receiver.getTypeId();
- if (receiverType.userType())
- throwBadType("trim", receiverType.getSQLTypeName());
-
- receiver = castArgToString(receiver);
-
- if ((receiverType.getTypeFormatId() == StoredFormatIds.CLOB_TYPE_ID) ||
- (receiverType.getTypeFormatId() == StoredFormatIds.NCLOB_TYPE_ID)) {
- // special case for CLOBs: if we start with a CLOB, we have to get
- // a CLOB as a result (as opposed to a VARCHAR), because we can have a
- // CLOB that is beyond the max length of VARCHAR (ex. "clob(100k)").
- // This is okay because CLOBs, like VARCHARs, allow variable-length
- // values (which is a must for the trim to actually work).
- resultType = receiverType;
- }
-
- /*
- ** Check the type of the leftOperand (trimSet).
- ** The leftOperand should be a string value type.
- */
- TypeId leftCTI;
- leftCTI = leftOperand.getTypeId();
- if (leftCTI.userType())
- throwBadType("trim", leftCTI.getSQLTypeName());
-
- leftOperand = castArgToString(leftOperand);
-
- /*
- ** The result type of trim is varchar.
- */
- setResultType(resultType);
-
- return this;
- }
- /*
- ** set result type for operator
- */
- private void setResultType(TypeId resultType) throws StandardException
- {
- setType(new DataTypeDescriptor(
- resultType,
- true,
- receiver.getTypeServices().getMaximumWidth()
- )
- );
- }
- /**
- * Bind locate operator
- *
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
-
- public ValueNode locateBind() throws StandardException
- {
- TypeId firstOperandType, secondOperandType, offsetType;
-
- /*
- * Is there a ? parameter for the first arg. Copy the
- * left/firstOperand's. If the left/firstOperand are both parameters,
- * both will be max length.
- */
- if( receiver.isParameterNode())
- {
- if( leftOperand.isParameterNode())
- {
- ((ParameterNode) receiver).setDescriptor(getVarcharDescriptor());
- }
- else
- {
- if( leftOperand.getTypeId().isStringTypeId() )
- {
- ((ParameterNode) receiver).setDescriptor(
- leftOperand.getTypeServices());
- }
- }
- }
-
- /*
- * Is there a ? parameter for the second arg. Copy the receiver's.
- * If the receiver are both parameters, both will be max length.
- */
- if(leftOperand.isParameterNode())
- {
- if(receiver.isParameterNode())
- {
- ((ParameterNode) leftOperand).setDescriptor(getVarcharDescriptor());
- }
- else
- {
- if( receiver.getTypeId().isStringTypeId() )
- {
- ((ParameterNode) leftOperand).setDescriptor(
- receiver.getTypeServices());
- }
- }
- }
-
- /*
- * Is there a ? paramter for the third arg. It will be an int.
- */
- if( rightOperand.isParameterNode())
- {
- ((ParameterNode) rightOperand).setDescriptor(
- new DataTypeDescriptor(TypeId.INTEGER_ID, true));
- }
-
- bindToBuiltIn();
-
- /*
- ** Check the type of the operand - this function is allowed only
- ** for: receiver = CHAR
- ** firstOperand = CHAR
- ** secondOperand = INT
- */
- secondOperandType = leftOperand.getTypeId();
- offsetType = rightOperand.getTypeId();
- firstOperandType = receiver.getTypeId();
-
- if (!firstOperandType.isStringTypeId() ||
- !secondOperandType.isStringTypeId() ||
- offsetType.getJDBCTypeId() != Types.INTEGER)
- throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE,
- "LOCATE", "FUNCTION");
-
- /*
- ** The result type of a LocateFunctionNode is an integer.
- */
- setType(new DataTypeDescriptor(TypeId.INTEGER_ID,
- receiver.getTypeServices().isNullable()));
-
- return this;
- }
-
- /* cast arg to a varchar */
- protected ValueNode castArgToString(ValueNode vn) throws StandardException
- {
- TypeCompiler vnTC = vn.getTypeCompiler();
- if (! vn.getTypeId().isStringTypeId())
- {
- ValueNode newNode = (ValueNode)
- getNodeFactory().getNode(
- C_NodeTypes.CAST_NODE,
- vn,
- DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true,
- vnTC.getCastToCharWidth(
- vn.getTypeServices())),
- getContextManager());
- ((CastNode) newNode).bindCastNodeOnly();
- return newNode;
- }
- return vn;
- }
-
- /**
- * Bind substr expression.
- *
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
-
- public ValueNode substrBind()
- throws StandardException
- {
- TypeId receiverType;
- TypeId resultType;
-
- // handle parameters here
-
- /* Is there a ? parameter for the receiver? */
- if (receiver.isParameterNode())
- {
- /*
- ** According to the SQL standard, if substr has a ? receiver,
- ** its type is varchar with the implementation-defined maximum length
- ** for a varchar.
- */
-
- ((ParameterNode) receiver).setDescriptor(getVarcharDescriptor());
- }
-
- /* Is there a ? parameter on the left? */
- if (leftOperand.isParameterNode())
- {
- /* Set the left operand type to int. */
- ((ParameterNode) leftOperand).setDescriptor(
- new DataTypeDescriptor(TypeId.INTEGER_ID, true));
- }
-
- /* Is there a ? parameter on the right? */
- if ((rightOperand != null) && rightOperand.isParameterNode())
- {
- /* Set the right operand type to int. */
- ((ParameterNode) rightOperand).setDescriptor(
- new DataTypeDescriptor(TypeId.INTEGER_ID, true));
- }
-
- bindToBuiltIn();
-
- if (!leftOperand.getTypeId().isNumericTypeId() ||
- (rightOperand != null && !rightOperand.getTypeId().isNumericTypeId()))
- throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "SUBSTR", "FUNCTION");
-
- /*
- ** Check the type of the receiver - this function is allowed only on
- ** string value types.
- */
- resultType = receiverType = receiver.getTypeId();
- switch (receiverType.getJDBCTypeId())
- {
- case Types.CHAR:
- case Types.VARCHAR:
- case Types.LONGVARCHAR:
- case Types.CLOB:
- break;
- default:
- {
- throwBadType("SUBSTR", receiverType.getSQLTypeName());
- }
- }
-
- // Determine the maximum length of the result
- int resultLen = receiver.getTypeServices().getMaximumWidth();
-
- if (rightOperand != null && rightOperand instanceof ConstantNode)
- {
- if (((ConstantNode)rightOperand).getValue().getInt() < resultLen)
- resultLen = ((ConstantNode)rightOperand).getValue().getInt();
- }
-
- /*
- ** The result type of substr is a string type
- */
- setType(new DataTypeDescriptor(
- resultType,
- true,
- resultLen
- ));
-
- return this;
- }
-
- public ValueNode getReceiver()
- {
- return receiver;
- }
-
- /* throw bad type message */
- private void throwBadType(String funcName, String type)
- throws StandardException
- {
- throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
- funcName,
- type);
- }
-
- /* bind arguments to built in types */
- protected void bindToBuiltIn()
- throws StandardException
- {
- /* If the receiver is not a built-in type, then generate a bound conversion
- * tree to a built-in type.
- */
- if (! receiver.getTypeId().systemBuiltIn())
- {
- receiver = receiver.genSQLJavaSQLTree();
- }
-
- /* If the left operand is not a built-in type, then generate a bound conversion
- * tree to a built-in type.
- */
- if (! leftOperand.getTypeId().systemBuiltIn())
- {
- leftOperand = leftOperand.genSQLJavaSQLTree();
- }
-
- /* If the right operand is not a built-in type, then generate a bound conversion
- * tree to a built-in type.
- */
- if (rightOperand != null)
- {
- if (! rightOperand.getTypeId().systemBuiltIn())
- {
- rightOperand = rightOperand.genSQLJavaSQLTree();
- }
- }
- }
-
- private DataTypeDescriptor getVarcharDescriptor() {
- return new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.VARCHAR), true);
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+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.services.sanity.SanityManager;
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+import org.apache.derby.iapi.sql.compile.Visitable;
+import org.apache.derby.iapi.sql.compile.Visitor;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.store.access.Qualifier;
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.sql.compile.TypeCompiler;
+import org.apache.derby.iapi.types.NumberDataValue;
+import org.apache.derby.iapi.types.StringDataValue;
+import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import org.apache.derby.iapi.store.access.Qualifier;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.reference.ClassName;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+import org.apache.derby.iapi.util.JBitSet;
+
+import java.lang.reflect.Modifier;
+
+import java.sql.Types;
+import java.util.Vector;
+/**
+ * A TernaryOperatorNode represents a built-in ternary operators.
+ * This covers built-in functions like substr().
+ * Java operators are not represented here: the JSQL language allows Java
+ * methods to be called from expressions, but not Java operators.
+ *
+ * @author Jerry Brenner
+ */
+
+public class TernaryOperatorNode extends ValueNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ String operator;
+ String methodName;
+ int operatorType;
+ ValueNode receiver;
+
+ ValueNode leftOperand;
+ ValueNode rightOperand;
+
+ String resultInterfaceType;
+ String receiverInterfaceType;
+ String leftInterfaceType;
+ String rightInterfaceType;
+ int trimType;
+
+ public static final int TRIM = 0;
+ public static final int LOCATE = 1;
+ public static final int SUBSTRING = 2;
+ public static final int LIKE = 3;
+ static final String[] TernaryOperators = {"trim", "LOCATE", "substring", "like"};
+ static final String[] TernaryMethodNames = {"trim", "locate", "substring", "like"};
+ static final String[] TernaryResultType = {ClassName.StringDataValue,
+ ClassName.NumberDataValue,
+ ClassName.ConcatableDataValue,
+ ClassName.BooleanDataValue};
+ static final String[][] TernaryArgType = {
+ {ClassName.StringDataValue, ClassName.StringDataValue, "java.lang.Integer"},
+ {ClassName.StringDataValue, ClassName.StringDataValue, ClassName.NumberDataValue},
+ {ClassName.ConcatableDataValue, ClassName.NumberDataValue, ClassName.NumberDataValue},
+ {ClassName.DataValueDescriptor, ClassName.DataValueDescriptor, ClassName.DataValueDescriptor}
+ };
+
+ /**
+ * Initializer for a TernaryOperatorNode
+ *
+ * @param receiver The receiver (eg, string being operated on in substr())
+ * @param leftOperand The left operand of the node
+ * @param rightOperand The right operand of the node
+ * @param operatorType The type of the operand
+ */
+
+ public void init(
+ Object receiver,
+ Object leftOperand,
+ Object rightOperand,
+ Object operatorType,
+ Object trimType)
+ {
+ this.receiver = (ValueNode) receiver;
+ this.leftOperand = (ValueNode) leftOperand;
+ this.rightOperand = (ValueNode) rightOperand;
+ this.operatorType = ((Integer) operatorType).intValue();
+ this.operator = (String) TernaryOperators[this.operatorType];
+ this.methodName = (String) TernaryMethodNames[this.operatorType];
+ this.resultInterfaceType = (String) TernaryResultType[this.operatorType];
+ this.receiverInterfaceType = (String) TernaryArgType[this.operatorType][0];
+ this.leftInterfaceType = (String) TernaryArgType[this.operatorType][1];
+ this.rightInterfaceType = (String) TernaryArgType[this.operatorType][2];
+ if (trimType != null)
+ this.trimType = ((Integer) trimType).intValue();
+ }
+
+ /**
+ * Convert this object to a String. See comments in QueryTreeNode.java
+ * for how this should be done for tree printing.
+ *
+ * @return This object as a String
+ */
+
+ public String toString()
+ {
+ if (SanityManager.DEBUG)
+ {
+ return "operator: " + operator + "\n" +
+ "methodName: " + methodName + "\n" +
+ "resultInterfaceType: " + resultInterfaceType + "\n" +
+ "receiverInterfaceType: " + receiverInterfaceType + "\n" +
+ "leftInterfaceType: " + leftInterfaceType + "\n" +
+ "rightInterfaceType: " + rightInterfaceType + "\n" +
+ super.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Set the clause that this node appears in.
+ *
+ * @param clause The clause that this node appears in.
+ *
+ * @return Nothing.
+ */
+ public void setClause(int clause)
+ {
+ super.setClause(clause);
+ receiver.setClause(clause);
+ leftOperand.setClause(clause);
+ if (rightOperand != null)
+ {
+ rightOperand.setClause(clause);
+ }
+ }
+
+ /**
+ * Prints the sub-nodes of this object. See QueryTreeNode.java for
+ * how tree printing is supposed to work.
+ *
+ * @param depth The depth of this node in the tree
+ *
+ * @return Nothing
+ */
+
+ public void printSubNodes(int depth)
+ {
+ if (SanityManager.DEBUG)
+ {
+ super.printSubNodes(depth);
+
+ if (receiver != null)
+ {
+ printLabel(depth, "receiver: ");
+ receiver.treePrint(depth + 1);
+ }
+
+ if (leftOperand != null)
+ {
+ printLabel(depth, "leftOperand: ");
+ leftOperand.treePrint(depth + 1);
+ }
+
+ if (rightOperand != null)
+ {
+ printLabel(depth, "rightOperand: ");
+ rightOperand.treePrint(depth + 1);
+ }
+ }
+ }
+
+ /**
+ * Bind this expression. This means binding the sub-expressions,
+ * as well as figuring out what the return type is for this expression.
+ *
+ * @param fromList The FROM list for the query this
+ * expression is in, for binding columns.
+ * @param subqueryList The subquery list being built as we find SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ receiver = receiver.bindExpression(fromList, subqueryList,
+ aggregateVector);
+ leftOperand = leftOperand.bindExpression(fromList, subqueryList,
+ aggregateVector);
+
+ if (rightOperand != null)
+ {
+ rightOperand = rightOperand.bindExpression(fromList, subqueryList,
+ aggregateVector);
+ }
+ if (operatorType == TRIM)
+ trimBind();
+ else if (operatorType == LOCATE)
+ locateBind();
+ else if (operatorType == SUBSTRING)
+ substrBind();
+
+ return this;
+ }
+
+ /**
+ * Preprocess an expression tree. We do a number of transformations
+ * here (including subqueries, IN lists, LIKE and BETWEEN) plus
+ * subquery flattening.
+ * NOTE: This is done before the outer ResultSetNode is preprocessed.
+ *
+ * @param numTables Number of tables in the DML Statement
+ * @param outerFromList FromList from outer query block
+ * @param outerSubqueryList SubqueryList from outer query block
+ * @param outerPredicateList PredicateList from outer query block
+ *
+ * @return The modified expression
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ValueNode preprocess(int numTables,
+ FromList outerFromList,
+ SubqueryList outerSubqueryList,
+ PredicateList outerPredicateList)
+ throws StandardException
+ {
+ receiver = receiver.preprocess(numTables,
+ outerFromList, outerSubqueryList,
+ outerPredicateList);
+
+ leftOperand = leftOperand.preprocess(numTables,
+ outerFromList, outerSubqueryList,
+ outerPredicateList);
+ if (rightOperand != null)
+ {
+ rightOperand = rightOperand.preprocess(numTables,
+ outerFromList, outerSubqueryList,
+ outerPredicateList);
+ }
+ return this;
+ }
+ /**
+ * Do code generation for this ternary operator.
+ *
+ * @param acb The ExpressionClassBuilder for the class we're generating
+ * @param mb The method the expression will go into
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateExpression(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ throws StandardException
+ {
+ int nargs = 0;
+ String receiverType = null;
+
+ /* Allocate an object for re-use to hold the result of the operator */
+ LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultInterfaceType);
+
+ receiver.generateExpression(acb, mb);
+ if (operatorType == TRIM)
+ {
+ mb.push(trimType);
+ mb.getField(field);
+ nargs = 2;
+ receiverType = receiverInterfaceType;
+ }
+ else if (operatorType == LOCATE)
+ {
+ leftOperand.generateExpression(acb, mb);
+ mb.upCast(leftInterfaceType);
+ rightOperand.generateExpression(acb, mb);
+ mb.upCast(rightInterfaceType);
+ mb.getField(field);
+ nargs = 3;
+
+ }
+ else if (operatorType == SUBSTRING)
+ {
+ leftOperand.generateExpression(acb, mb);
+ mb.upCast(leftInterfaceType);
+ if (rightOperand != null)
+ {
+ rightOperand.generateExpression(acb, mb);
+ mb.upCast(rightInterfaceType);
+ }
+ else
+ {
+ mb.pushNull(rightInterfaceType);
+ }
+
+ mb.getField(field); // third arg
+ mb.push(receiver.getTypeServices().getMaximumWidth());
+ nargs = 4;
+ receiverType = receiverInterfaceType;
+ }
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultInterfaceType, nargs);
+
+ /*
+ ** Store the result of the method call in the field, so we can re-use
+ ** the object.
+ */
+ mb.putField(field);
+ }
+
+ /**
+ * Set the leftOperand to the specified ValueNode
+ *
+ * @param newLeftOperand The new leftOperand
+ *
+ * @return None.
+ */
+ public void setLeftOperand(ValueNode newLeftOperand)
+ {
+ leftOperand = newLeftOperand;
+ }
+
+ /**
+ * Get the leftOperand
+ *
+ * @return The current leftOperand.
+ */
+ public ValueNode getLeftOperand()
+ {
+ return leftOperand;
+ }
+
+ /**
+ * Set the rightOperand to the specified ValueNode
+ *
+ * @param newRightOperand The new rightOperand
+ *
+ * @return None.
+ */
+ public void setRightOperand(ValueNode newRightOperand)
+ {
+ rightOperand = newRightOperand;
+ }
+
+ /**
+ * Get the rightOperand
+ *
+ * @return The current rightOperand.
+ */
+ public ValueNode getRightOperand()
+ {
+ return rightOperand;
+ }
+
+ /**
+ * Categorize this predicate. Initially, this means
+ * building a bit map of the referenced tables for each predicate.
+ * If the source of this ColumnReference (at the next underlying level)
+ * is not a ColumnReference or a VirtualColumnNode then this predicate
+ * will not be pushed down.
+ *
+ * For example, in:
+ * select * from (select 1 from s) a (x) where x = 1
+ * we will not push down x = 1.
+ * NOTE: It would be easy to handle the case of a constant, but if the
+ * inner SELECT returns an arbitrary expression, then we would have to copy
+ * that tree into the pushed predicate, and that tree could contain
+ * subqueries and method calls.
+ * RESOLVE - revisit this issue once we have views.
+ *
+ * @param referencedTabs JBitSet with bit map of referenced FromTables
+ * @param simplePredsOnly Whether or not to consider method
+ * calls, field references and conditional nodes
+ * when building bit map
+ *
+ * @return boolean Whether or not source.expression is a ColumnReference
+ * or a VirtualColumnNode.
+ * @exception StandardException Thrown on error
+ */
+ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
+ throws StandardException
+ {
+ boolean pushable;
+ pushable = receiver.categorize(referencedTabs, simplePredsOnly);
+ pushable = (leftOperand.categorize(referencedTabs, simplePredsOnly) && pushable);
+ if (rightOperand != null)
+ {
+ pushable = (rightOperand.categorize(referencedTabs, simplePredsOnly) && pushable);
+ }
+ return pushable;
+ }
+
+ /**
+ * Remap all ColumnReferences in this tree to be clones of the
+ * underlying expression.
+ *
+ * @return ValueNode The remapped expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+ public ValueNode remapColumnReferencesToExpressions()
+ throws StandardException
+ {
+ receiver = receiver.remapColumnReferencesToExpressions();
+ leftOperand = leftOperand.remapColumnReferencesToExpressions();
+ if (rightOperand != null)
+ {
+ rightOperand = rightOperand.remapColumnReferencesToExpressions();
+ }
+ return this;
+ }
+
+ /**
+ * Return whether or not this expression tree represents a constant expression.
+ *
+ * @return Whether or not this expression tree represents a constant expression.
+ */
+ public boolean isConstantExpression()
+ {
+ return (receiver.isConstantExpression() &&
+ leftOperand.isConstantExpression() &&
+ (rightOperand == null || rightOperand.isConstantExpression()));
+ }
+
+ /** @see ValueNode#constantExpression */
+ public boolean constantExpression(PredicateList whereClause)
+ {
+ return (receiver.constantExpression(whereClause) &&
+ leftOperand.constantExpression(whereClause) &&
+ (rightOperand == null ||
+ rightOperand.constantExpression(whereClause)));
+ }
+
+ /**
+ * Accept a visitor, and call v.visit()
+ * on child nodes as necessary.
+ *
+ * @param v the visitor
+ *
+ * @exception StandardException on error
+ */
+ public Visitable accept(Visitor v)
+ throws StandardException
+ {
+ Visitable returnNode = v.visit(this);
+
+ if (v.skipChildren(this))
+ {
+ return returnNode;
+ }
+
+ if (receiver != null && !v.stopTraversal())
+ {
+ receiver = (ValueNode)receiver.accept(v);
+ }
+
+ if (leftOperand != null && !v.stopTraversal())
+ {
+ leftOperand = (ValueNode)leftOperand.accept(v);
+ }
+
+ if (rightOperand != null && !v.stopTraversal())
+ {
+ rightOperand = (ValueNode)rightOperand.accept(v);
+ }
+
+ return returnNode;
+ }
+ /**
+ * Bind trim expression.
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ private ValueNode trimBind()
+ throws StandardException
+ {
+ TypeId receiverType;
+ TypeId resultType = TypeId.getBuiltInTypeId(Types.VARCHAR);
+
+ // handle parameters here
+
+ /* Is there a ? parameter for the receiver? */
+ if (receiver.isParameterNode())
+ {
+ /*
+ ** According to the SQL standard, if trim has a ? receiver,
+ ** its type is varchar with the implementation-defined maximum length
+ ** for a varchar.
+ */
+
+ ((ParameterNode) receiver).setDescriptor(getVarcharDescriptor());
+ }
+
+ /* Is there a ? parameter on the left? */
+ if (leftOperand.isParameterNode())
+ {
+ /* Set the left operand type to varchar. */
+ ((ParameterNode) leftOperand).setDescriptor(getVarcharDescriptor());
+ }
+
+ bindToBuiltIn();
+
+ /*
+ ** Check the type of the receiver - this function is allowed only on
+ ** string value types.
+ */
+ receiverType = receiver.getTypeId();
+ if (receiverType.userType())
+ throwBadType("trim", receiverType.getSQLTypeName());
+
+ receiver = castArgToString(receiver);
+
+ if ((receiverType.getTypeFormatId() == StoredFormatIds.CLOB_TYPE_ID) ||
+ (receiverType.getTypeFormatId() == StoredFormatIds.NCLOB_TYPE_ID)) {
+ // special case for CLOBs: if we start with a CLOB, we have to get
+ // a CLOB as a result (as opposed to a VARCHAR), because we can have a
+ // CLOB that is beyond the max length of VARCHAR (ex. "clob(100k)").
+ // This is okay because CLOBs, like VARCHARs, allow variable-length
+ // values (which is a must for the trim to actually work).
+ resultType = receiverType;
+ }
+
+ /*
+ ** Check the type of the leftOperand (trimSet).
+ ** The leftOperand should be a string value type.
+ */
+ TypeId leftCTI;
+ leftCTI = leftOperand.getTypeId();
+ if (leftCTI.userType())
+ throwBadType("trim", leftCTI.getSQLTypeName());
+
+ leftOperand = castArgToString(leftOperand);
+
+ /*
+ ** The result type of trim is varchar.
+ */
+ setResultType(resultType);
+
+ return this;
+ }
+ /*
+ ** set result type for operator
+ */
+ private void setResultType(TypeId resultType) throws StandardException
+ {
+ setType(new DataTypeDescriptor(
+ resultType,
+ true,
+ receiver.getTypeServices().getMaximumWidth()
+ )
+ );
+ }
+ /**
+ * Bind locate operator
+ *
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ValueNode locateBind() throws StandardException
+ {
+ TypeId firstOperandType, secondOperandType, offsetType;
+
+ /*
+ * Is there a ? parameter for the first arg. Copy the
+ * left/firstOperand's. If the left/firstOperand are both parameters,
+ * both will be max length.
+ */
+ if( receiver.isParameterNode())
+ {
+ if( leftOperand.isParameterNode())
+ {
+ ((ParameterNode) receiver).setDescriptor(getVarcharDescriptor());
+ }
+ else
+ {
+ if( leftOperand.getTypeId().isStringTypeId() )
+ {
+ ((ParameterNode) receiver).setDescriptor(
+ leftOperand.getTypeServices());
+ }
+ }
+ }
+
+ /*
+ * Is there a ? parameter for the second arg. Copy the receiver's.
+ * If the receiver are both parameters, both will be max length.
+ */
+ if(leftOperand.isParameterNode())
+ {
+ if(receiver.isParameterNode())
+ {
+ ((ParameterNode) leftOperand).setDescriptor(getVarcharDescriptor());
+ }
+ else
+ {
+ if( receiver.getTypeId().isStringTypeId() )
+ {
+ ((ParameterNode) leftOperand).setDescriptor(
+ receiver.getTypeServices());
+ }
+ }
+ }
+
+ /*
+ * Is there a ? paramter for the third arg. It will be an int.
+ */
+ if( rightOperand.isParameterNode())
+ {
+ ((ParameterNode) rightOperand).setDescriptor(
+ new DataTypeDescriptor(TypeId.INTEGER_ID, true));
+ }
+
+ bindToBuiltIn();
+
+ /*
+ ** Check the type of the operand - this function is allowed only
+ ** for: receiver = CHAR
+ ** firstOperand = CHAR
+ ** secondOperand = INT
+ */
+ secondOperandType = leftOperand.getTypeId();
+ offsetType = rightOperand.getTypeId();
+ firstOperandType = receiver.getTypeId();
+
+ if (!firstOperandType.isStringTypeId() ||
+ !secondOperandType.isStringTypeId() ||
+ offsetType.getJDBCTypeId() != Types.INTEGER)
+ throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE,
+ "LOCATE", "FUNCTION");
+
+ /*
+ ** The result type of a LocateFunctionNode is an integer.
+ */
+ setType(new DataTypeDescriptor(TypeId.INTEGER_ID,
+ receiver.getTypeServices().isNullable()));
+
+ return this;
+ }
+
+ /* cast arg to a varchar */
+ protected ValueNode castArgToString(ValueNode vn) throws StandardException
+ {
+ TypeCompiler vnTC = vn.getTypeCompiler();
+ if (! vn.getTypeId().isStringTypeId())
+ {
+ ValueNode newNode = (ValueNode)
+ getNodeFactory().getNode(
+ C_NodeTypes.CAST_NODE,
+ vn,
+ DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true,
+ vnTC.getCastToCharWidth(
+ vn.getTypeServices())),
+ getContextManager());
+ ((CastNode) newNode).bindCastNodeOnly();
+ return newNode;
+ }
+ return vn;
+ }
+
+ /**
+ * Bind substr expression.
+ *
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ValueNode substrBind()
+ throws StandardException
+ {
+ TypeId receiverType;
+ TypeId resultType;
+
+ // handle parameters here
+
+ /* Is there a ? parameter for the receiver? */
+ if (receiver.isParameterNode())
+ {
+ /*
+ ** According to the SQL standard, if substr has a ? receiver,
+ ** its type is varchar with the implementation-defined maximum length
+ ** for a varchar.
+ */
+
+ ((ParameterNode) receiver).setDescriptor(getVarcharDescriptor());
+ }
+
+ /* Is there a ? parameter on the left? */
+ if (leftOperand.isParameterNode())
+ {
+ /* Set the left operand type to int. */
+ ((ParameterNode) leftOperand).setDescriptor(
+ new DataTypeDescriptor(TypeId.INTEGER_ID, true));
+ }
+
+ /* Is there a ? parameter on the right? */
+ if ((rightOperand != null) && rightOperand.isParameterNode())
+ {
+ /* Set the right operand type to int. */
+ ((ParameterNode) rightOperand).setDescriptor(
+ new DataTypeDescriptor(TypeId.INTEGER_ID, true));
+ }
+
+ bindToBuiltIn();
+
+ if (!leftOperand.getTypeId().isNumericTypeId() ||
+ (rightOperand != null && !rightOperand.getTypeId().isNumericTypeId()))
+ throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "SUBSTR", "FUNCTION");
+
+ /*
+ ** Check the type of the receiver - this function is allowed only on
+ ** string value types.
+ */
+ resultType = receiverType = receiver.getTypeId();
+ switch (receiverType.getJDBCTypeId())
+ {
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ case Types.CLOB:
+ break;
+ default:
+ {
+ throwBadType("SUBSTR", receiverType.getSQLTypeName());
+ }
+ }
+
+ // Determine the maximum length of the result
+ int resultLen = receiver.getTypeServices().getMaximumWidth();
+
+ if (rightOperand != null && rightOperand instanceof ConstantNode)
+ {
+ if (((ConstantNode)rightOperand).getValue().getInt() < resultLen)
+ resultLen = ((ConstantNode)rightOperand).getValue().getInt();
+ }
+
+ /*
+ ** The result type of substr is a string type
+ */
+ setType(new DataTypeDescriptor(
+ resultType,
+ true,
+ resultLen
+ ));
+
+ return this;
+ }
+
+ public ValueNode getReceiver()
+ {
+ return receiver;
+ }
+
+ /* throw bad type message */
+ private void throwBadType(String funcName, String type)
+ throws StandardException
+ {
+ throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE,
+ funcName,
+ type);
+ }
+
+ /* bind arguments to built in types */
+ protected void bindToBuiltIn()
+ throws StandardException
+ {
+ /* If the receiver is not a built-in type, then generate a bound conversion
+ * tree to a built-in type.
+ */
+ if (! receiver.getTypeId().systemBuiltIn())
+ {
+ receiver = receiver.genSQLJavaSQLTree();
+ }
+
+ /* If the left operand is not a built-in type, then generate a bound conversion
+ * tree to a built-in type.
+ */
+ if (! leftOperand.getTypeId().systemBuiltIn())
+ {
+ leftOperand = leftOperand.genSQLJavaSQLTree();
+ }
+
+ /* If the right operand is not a built-in type, then generate a bound conversion
+ * tree to a built-in type.
+ */
+ if (rightOperand != null)
+ {
+ if (! rightOperand.getTypeId().systemBuiltIn())
+ {
+ rightOperand = rightOperand.genSQLJavaSQLTree();
+ }
+ }
+ }
+
+ private DataTypeDescriptor getVarcharDescriptor() {
+ return new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.VARCHAR), true);
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TestConstraintNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TestConstraintNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TestConstraintNode.java Fri Sep 24 10:33:20 2004
@@ -1,141 +1,141 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.sql.compile.C_NodeTypes;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-import org.apache.derby.iapi.reference.ClassName;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.types.TypeId;
-import org.apache.derby.iapi.types.BooleanDataValue;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import java.util.Vector;
-
-/**
- * A TestConstraintNode is used to determine when a constraint
- * has been violated.
- *
- * @author jeff
- */
-
-public class TestConstraintNode extends UnaryLogicalOperatorNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- private String sqlState;
- private String tableName;
- private String constraintName;
-
- /**
- * Initializer for a TestConstraintNode
- *
- * @param operand The operand of the constraint test
- * @param sqlState The SQLState of the exception to throw if the
- * constraint has failed
- * @param tableName The name of the table that the constraint is on
- * @param constraintName The name of the constraint being checked
- */
-
- public void init(Object booleanValue,
- Object sqlState,
- Object tableName,
- Object constraintName)
- {
- super.init(booleanValue, "throwExceptionIfFalse");
- this.sqlState = (String) sqlState;
- this.tableName = (String) tableName;
- this.constraintName = (String) constraintName;
- }
-
- /**
- * Bind this logical operator. All that has to be done for binding
- * a logical operator is to bind the operand, check that the operand
- * is SQLBoolean, and set the result type to SQLBoolean.
- *
- * @param fromList The query's FROM list
- * @param subqueryList The subquery list being built as we find SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
-
- public ValueNode bindExpression(
- FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- bindUnaryOperator(fromList, subqueryList, aggregateVector);
-
- /*
- ** If the operand is not boolean, cast it.
- */
-
- if ( ! operand.getTypeServices().getTypeId().getSQLTypeName().equals(
- TypeId.BOOLEAN_NAME))
- {
- operand = (ValueNode)
- getNodeFactory().getNode(
- C_NodeTypes.CAST_NODE,
- operand,
- new DataTypeDescriptor(TypeId.BOOLEAN_ID, true),
- getContextManager());
- ((CastNode) operand).bindCastNodeOnly();
- }
-
- /* Set the type info */
- setFullTypeInfo();
-
- return this;
- }
-
- /**
- * Do code generation for the TestConstraint operator.
- *
- * @param acb The ExpressionClassBuilder for the class we're generating
- * @param mb The method the expression will go into
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateExpression(ExpressionClassBuilder acb,
- MethodBuilder mb)
- throws StandardException
- {
-
- /*
- ** This generates the following code:
- **
- ** operand.testConstraint(sqlState, tableName, constraintName)
- */
-
- operand.generateExpression(acb, mb);
-
- mb.push(sqlState);
- mb.push(tableName);
- mb.push(constraintName);
-
- mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.BooleanDataValue,
- "throwExceptionIfFalse", ClassName.BooleanDataValue, 3);
-
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+import org.apache.derby.iapi.reference.ClassName;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.BooleanDataValue;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import java.util.Vector;
+
+/**
+ * A TestConstraintNode is used to determine when a constraint
+ * has been violated.
+ *
+ * @author jeff
+ */
+
+public class TestConstraintNode extends UnaryLogicalOperatorNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ private String sqlState;
+ private String tableName;
+ private String constraintName;
+
+ /**
+ * Initializer for a TestConstraintNode
+ *
+ * @param operand The operand of the constraint test
+ * @param sqlState The SQLState of the exception to throw if the
+ * constraint has failed
+ * @param tableName The name of the table that the constraint is on
+ * @param constraintName The name of the constraint being checked
+ */
+
+ public void init(Object booleanValue,
+ Object sqlState,
+ Object tableName,
+ Object constraintName)
+ {
+ super.init(booleanValue, "throwExceptionIfFalse");
+ this.sqlState = (String) sqlState;
+ this.tableName = (String) tableName;
+ this.constraintName = (String) constraintName;
+ }
+
+ /**
+ * Bind this logical operator. All that has to be done for binding
+ * a logical operator is to bind the operand, check that the operand
+ * is SQLBoolean, and set the result type to SQLBoolean.
+ *
+ * @param fromList The query's FROM list
+ * @param subqueryList The subquery list being built as we find SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ValueNode bindExpression(
+ FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ bindUnaryOperator(fromList, subqueryList, aggregateVector);
+
+ /*
+ ** If the operand is not boolean, cast it.
+ */
+
+ if ( ! operand.getTypeServices().getTypeId().getSQLTypeName().equals(
+ TypeId.BOOLEAN_NAME))
+ {
+ operand = (ValueNode)
+ getNodeFactory().getNode(
+ C_NodeTypes.CAST_NODE,
+ operand,
+ new DataTypeDescriptor(TypeId.BOOLEAN_ID, true),
+ getContextManager());
+ ((CastNode) operand).bindCastNodeOnly();
+ }
+
+ /* Set the type info */
+ setFullTypeInfo();
+
+ return this;
+ }
+
+ /**
+ * Do code generation for the TestConstraint operator.
+ *
+ * @param acb The ExpressionClassBuilder for the class we're generating
+ * @param mb The method the expression will go into
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateExpression(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ throws StandardException
+ {
+
+ /*
+ ** This generates the following code:
+ **
+ ** operand.testConstraint(sqlState, tableName, constraintName)
+ */
+
+ operand.generateExpression(acb, mb);
+
+ mb.push(sqlState);
+ mb.push(tableName);
+ mb.push(constraintName);
+
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.BooleanDataValue,
+ "throwExceptionIfFalse", ClassName.BooleanDataValue, 3);
+
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimeTypeCompiler.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimeTypeCompiler.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimeTypeCompiler.java Fri Sep 24 10:33:20 2004
@@ -1,167 +1,167 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.loader.ClassFactory;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.DateTimeDataValue;
-import org.apache.derby.iapi.types.DataValueFactory;
-import org.apache.derby.iapi.types.TypeId;
-
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import java.sql.Types;
-import org.apache.derby.iapi.reference.ClassName;
-
-public class TimeTypeCompiler extends BaseTypeCompiler
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
- /* TypeCompiler methods */
-
- /**
- * Dates are comparable to timestamps and to comparable
- * user types.
- *
- * @param otherType the type of the instance to compare with this type.
- * @param forEquals True if this is an = or <> comparison, false
- * otherwise.
- * @param cf A ClassFactory
- * @return true if otherType is comparable to this type, else false.
- */
- public boolean comparable(TypeId otherType,
- boolean forEquals,
- ClassFactory cf)
- {
- int otherJDBCTypeId = otherType.getJDBCTypeId();
-
- // Long types cannot be compared
- if (otherType.isLongConcatableTypeId())
- return false;
-
- if (otherJDBCTypeId == Types.TIME || otherType.isStringTypeId())
- return true;
-
- TypeCompiler otherTC = getTypeCompiler(otherType);
-
- /* User types know the rules for what can be compared to them */
- if (otherType.userType())
- {
- return otherTC.comparable(getTypeId(), forEquals, cf);
- }
-
- return false;
- }
-
- /**
- * User types are convertible to other user types only if
- * (for now) they are the same type and are being used to
- * implement some JDBC type. This is sufficient for
- * date/time types; it may be generalized later for e.g.
- * comparison of any user type with one of its subtypes.
- *
- * @see TypeCompiler#convertible
- */
- public boolean convertible(TypeId otherType,
- boolean forDataTypeFunction)
- {
-
- if (otherType.isStringTypeId() &&
- (!otherType.isLOBTypeId()) &&
- !otherType.isLongVarcharTypeId())
- {
- return true;
- }
-
-
- /*
- ** If same type, convert always ok.
- */
- return (getStoredFormatIdFromTypeId() ==
- otherType.getTypeFormatId());
-
- }
-
- /** @see TypeCompiler#compatible */
- public boolean compatible(TypeId otherType)
- {
- return convertible(otherType,false);
- }
-
- /**
- * User types are storable into other user types that they
- * are assignable to. The other type must be a subclass of
- * this type, or implement this type as one of its interfaces.
- *
- * Built-in types are also storable into user types when the built-in
- * type's corresponding Java type is assignable to the user type.
- *
- * @param otherType the type of the instance to store into this type.
- * @param cf A ClassFactory
- * @return true if otherType is storable into this type, else false.
- */
- public boolean storable(TypeId otherType, ClassFactory cf)
- {
- int otherJDBCTypeId = otherType.getJDBCTypeId();
-
- if (otherJDBCTypeId == Types.TIME ||
- (otherJDBCTypeId == Types.CHAR) ||
- (otherJDBCTypeId == Types.VARCHAR))
- {
- return true;
- }
-
- return cf.getClassInspector().assignableTo(
- otherType.getCorrespondingJavaTypeName(),
- "java.sql.Time");
- }
-
- /** @see TypeCompiler#interfaceName */
- public String interfaceName()
- {
- return ClassName.DateTimeDataValue;
- }
-
- /**
- * @see TypeCompiler#getCorrespondingPrimitiveTypeName
- */
-
- public String getCorrespondingPrimitiveTypeName()
- {
- return "java.sql.Time";
- }
-
- /**
- * @see TypeCompiler#getCastToCharWidth
- */
- public int getCastToCharWidth(DataTypeDescriptor dts)
- {
- return 8;
- }
-
- public double estimatedMemoryUsage(DataTypeDescriptor dtd)
- {
- return 12.0;
- }
-
- protected String nullMethodName()
- {
- return "getNullTime";
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.loader.ClassFactory;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.types.DateTimeDataValue;
+import org.apache.derby.iapi.types.DataValueFactory;
+import org.apache.derby.iapi.types.TypeId;
+
+import org.apache.derby.iapi.sql.compile.TypeCompiler;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import java.sql.Types;
+import org.apache.derby.iapi.reference.ClassName;
+
+public class TimeTypeCompiler extends BaseTypeCompiler
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
+ /* TypeCompiler methods */
+
+ /**
+ * Dates are comparable to timestamps and to comparable
+ * user types.
+ *
+ * @param otherType the type of the instance to compare with this type.
+ * @param forEquals True if this is an = or <> comparison, false
+ * otherwise.
+ * @param cf A ClassFactory
+ * @return true if otherType is comparable to this type, else false.
+ */
+ public boolean comparable(TypeId otherType,
+ boolean forEquals,
+ ClassFactory cf)
+ {
+ int otherJDBCTypeId = otherType.getJDBCTypeId();
+
+ // Long types cannot be compared
+ if (otherType.isLongConcatableTypeId())
+ return false;
+
+ if (otherJDBCTypeId == Types.TIME || otherType.isStringTypeId())
+ return true;
+
+ TypeCompiler otherTC = getTypeCompiler(otherType);
+
+ /* User types know the rules for what can be compared to them */
+ if (otherType.userType())
+ {
+ return otherTC.comparable(getTypeId(), forEquals, cf);
+ }
+
+ return false;
+ }
+
+ /**
+ * User types are convertible to other user types only if
+ * (for now) they are the same type and are being used to
+ * implement some JDBC type. This is sufficient for
+ * date/time types; it may be generalized later for e.g.
+ * comparison of any user type with one of its subtypes.
+ *
+ * @see TypeCompiler#convertible
+ */
+ public boolean convertible(TypeId otherType,
+ boolean forDataTypeFunction)
+ {
+
+ if (otherType.isStringTypeId() &&
+ (!otherType.isLOBTypeId()) &&
+ !otherType.isLongVarcharTypeId())
+ {
+ return true;
+ }
+
+
+ /*
+ ** If same type, convert always ok.
+ */
+ return (getStoredFormatIdFromTypeId() ==
+ otherType.getTypeFormatId());
+
+ }
+
+ /** @see TypeCompiler#compatible */
+ public boolean compatible(TypeId otherType)
+ {
+ return convertible(otherType,false);
+ }
+
+ /**
+ * User types are storable into other user types that they
+ * are assignable to. The other type must be a subclass of
+ * this type, or implement this type as one of its interfaces.
+ *
+ * Built-in types are also storable into user types when the built-in
+ * type's corresponding Java type is assignable to the user type.
+ *
+ * @param otherType the type of the instance to store into this type.
+ * @param cf A ClassFactory
+ * @return true if otherType is storable into this type, else false.
+ */
+ public boolean storable(TypeId otherType, ClassFactory cf)
+ {
+ int otherJDBCTypeId = otherType.getJDBCTypeId();
+
+ if (otherJDBCTypeId == Types.TIME ||
+ (otherJDBCTypeId == Types.CHAR) ||
+ (otherJDBCTypeId == Types.VARCHAR))
+ {
+ return true;
+ }
+
+ return cf.getClassInspector().assignableTo(
+ otherType.getCorrespondingJavaTypeName(),
+ "java.sql.Time");
+ }
+
+ /** @see TypeCompiler#interfaceName */
+ public String interfaceName()
+ {
+ return ClassName.DateTimeDataValue;
+ }
+
+ /**
+ * @see TypeCompiler#getCorrespondingPrimitiveTypeName
+ */
+
+ public String getCorrespondingPrimitiveTypeName()
+ {
+ return "java.sql.Time";
+ }
+
+ /**
+ * @see TypeCompiler#getCastToCharWidth
+ */
+ public int getCastToCharWidth(DataTypeDescriptor dts)
+ {
+ return 8;
+ }
+
+ public double estimatedMemoryUsage(DataTypeDescriptor dtd)
+ {
+ return 12.0;
+ }
+
+ protected String nullMethodName()
+ {
+ return "getNullTime";
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampOperatorNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampOperatorNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampOperatorNode.java Fri Sep 24 10:33:20 2004
@@ -1,115 +1,115 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.types.TypeId;
-import org.apache.derby.iapi.types.DataValueFactory;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-
-import org.apache.derby.iapi.reference.ClassName;
-import org.apache.derby.iapi.reference.SQLState;
-
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import java.sql.Types;
-
-import java.util.Vector;
-
-/**
- * The TimestampOperatorNode class implements the timestamp( date, time) function.
- */
-
-public class TimestampOperatorNode extends BinaryOperatorNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2004;
-
- /**
- * Initailizer for a TimestampOperatorNode.
- *
- * @param date The date
- * @param time The time
- */
-
- public void init( Object date,
- Object time)
- {
- leftOperand = (ValueNode) date;
- rightOperand = (ValueNode) time;
- operator = "timestamp";
- methodName = "getTimestamp";
- }
-
-
- /**
- * Bind this expression. This means binding the sub-expressions,
- * as well as figuring out what the return type is for this expression.
- *
- * @param fromList The FROM list for the query this
- * expression is in, for binding columns.
- * @param subqueryList The subquery list being built as we find SubqueryNodes
- * @param aggregateVector The aggregate vector being built as we find AggregateNodes
- *
- * @return The new top of the expression tree.
- *
- * @exception StandardException Thrown on error
- */
-
- public ValueNode bindExpression(
- FromList fromList, SubqueryList subqueryList,
- Vector aggregateVector)
- throws StandardException
- {
- leftOperand = leftOperand.bindExpression(fromList, subqueryList,
- aggregateVector);
- rightOperand = rightOperand.bindExpression(fromList, subqueryList,
- aggregateVector);
-
- TypeId leftTypeId = leftOperand.getTypeId();
- TypeId rightTypeId = rightOperand.getTypeId();
- if( !(leftTypeId.isStringTypeId() || leftTypeId.getJDBCTypeId() == Types.DATE || leftOperand.isParameterNode()))
- throw StandardException.newException(SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED,
- operator, leftTypeId.getSQLTypeName(), rightTypeId.getSQLTypeName());
- if( !(rightTypeId.isStringTypeId() || rightTypeId.getJDBCTypeId() == Types.TIME || rightOperand.isParameterNode()))
- throw StandardException.newException(SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED,
- operator, leftTypeId.getSQLTypeName(), rightTypeId.getSQLTypeName());
- setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor( Types.TIMESTAMP));
- return genSQLJavaSQLTree();
- } // end of bindExpression
-
- /**
- * Do code generation for this binary operator.
- *
- * @param acb The ExpressionClassBuilder for the class we're generating
- * @param mb The method the code to place the code
- *
- *
- * @exception StandardException Thrown on error
- */
-
- public void generateExpression(ExpressionClassBuilder acb,
- MethodBuilder mb)
- throws StandardException
- {
- acb.pushDataValueFactory(mb);
- leftOperand.generateExpression(acb, mb);
- mb.cast( ClassName.DataValueDescriptor);
- rightOperand.generateExpression(acb, mb);
- mb.cast( ClassName.DataValueDescriptor);
- mb.callMethod( VMOpcode.INVOKEINTERFACE, null, methodName, ClassName.DateTimeDataValue, 2);
- } // end of generateExpression
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.types.TypeId;
+import org.apache.derby.iapi.types.DataValueFactory;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
+
+import org.apache.derby.iapi.reference.ClassName;
+import org.apache.derby.iapi.reference.SQLState;
+
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+
+import java.sql.Types;
+
+import java.util.Vector;
+
+/**
+ * The TimestampOperatorNode class implements the timestamp( date, time) function.
+ */
+
+public class TimestampOperatorNode extends BinaryOperatorNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2004;
+
+ /**
+ * Initailizer for a TimestampOperatorNode.
+ *
+ * @param date The date
+ * @param time The time
+ */
+
+ public void init( Object date,
+ Object time)
+ {
+ leftOperand = (ValueNode) date;
+ rightOperand = (ValueNode) time;
+ operator = "timestamp";
+ methodName = "getTimestamp";
+ }
+
+
+ /**
+ * Bind this expression. This means binding the sub-expressions,
+ * as well as figuring out what the return type is for this expression.
+ *
+ * @param fromList The FROM list for the query this
+ * expression is in, for binding columns.
+ * @param subqueryList The subquery list being built as we find SubqueryNodes
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes
+ *
+ * @return The new top of the expression tree.
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public ValueNode bindExpression(
+ FromList fromList, SubqueryList subqueryList,
+ Vector aggregateVector)
+ throws StandardException
+ {
+ leftOperand = leftOperand.bindExpression(fromList, subqueryList,
+ aggregateVector);
+ rightOperand = rightOperand.bindExpression(fromList, subqueryList,
+ aggregateVector);
+
+ TypeId leftTypeId = leftOperand.getTypeId();
+ TypeId rightTypeId = rightOperand.getTypeId();
+ if( !(leftTypeId.isStringTypeId() || leftTypeId.getJDBCTypeId() == Types.DATE || leftOperand.isParameterNode()))
+ throw StandardException.newException(SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED,
+ operator, leftTypeId.getSQLTypeName(), rightTypeId.getSQLTypeName());
+ if( !(rightTypeId.isStringTypeId() || rightTypeId.getJDBCTypeId() == Types.TIME || rightOperand.isParameterNode()))
+ throw StandardException.newException(SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED,
+ operator, leftTypeId.getSQLTypeName(), rightTypeId.getSQLTypeName());
+ setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor( Types.TIMESTAMP));
+ return genSQLJavaSQLTree();
+ } // end of bindExpression
+
+ /**
+ * Do code generation for this binary operator.
+ *
+ * @param acb The ExpressionClassBuilder for the class we're generating
+ * @param mb The method the code to place the code
+ *
+ *
+ * @exception StandardException Thrown on error
+ */
+
+ public void generateExpression(ExpressionClassBuilder acb,
+ MethodBuilder mb)
+ throws StandardException
+ {
+ acb.pushDataValueFactory(mb);
+ leftOperand.generateExpression(acb, mb);
+ mb.cast( ClassName.DataValueDescriptor);
+ rightOperand.generateExpression(acb, mb);
+ mb.cast( ClassName.DataValueDescriptor);
+ mb.callMethod( VMOpcode.INVOKEINTERFACE, null, methodName, ClassName.DateTimeDataValue, 2);
+ } // end of generateExpression
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampTypeCompiler.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampTypeCompiler.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TimestampTypeCompiler.java Fri Sep 24 10:33:20 2004
@@ -1,196 +1,196 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.loader.ClassFactory;
-
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.DateTimeDataValue;
-import org.apache.derby.iapi.types.DataValueFactory;
-import org.apache.derby.iapi.types.TypeId;
-
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-import java.sql.Types;
-import org.apache.derby.iapi.reference.ClassName;
-
-public class TimestampTypeCompiler extends BaseTypeCompiler
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
- /* TypeCompiler methods */
-
- /**
- * Timestamps are comparable to timestamps and to comparable
- * user types.
- *
- * @param otherType the type of the instance to compare with this type.
- * @param forEquals True if this is an = or <> comparison, false
- * otherwise.
- * @param cf A ClassFactory
- * @return true if otherType is comparable to this type, else false.
- */
- public boolean comparable(TypeId otherType,
- boolean forEquals,
- ClassFactory cf)
- {
- return comparable(getTypeId(), otherType, forEquals, cf);
- }
-
- boolean comparable(TypeId leftType,
- TypeId otherType,
- boolean forEquals,
- ClassFactory cf)
- {
-
- int otherJDBCTypeId = otherType.getJDBCTypeId();
-
- // Long types cannot be compared
- if (otherType.isLongConcatableTypeId())
- return false;
-
- TypeCompiler otherTC = getTypeCompiler(otherType);
- if (otherJDBCTypeId == Types.TIMESTAMP || otherType.isStringTypeId())
- return true;
-
- /* User types know the rules for what can be compared to them */
- if (otherType.userType())
- {
- return otherTC.comparable(getTypeId(), forEquals, cf);
- }
-
- return false;
- }
-
- /**
- * User types are convertible to other user types only if
- * (for now) they are the same type and are being used to
- * implement some JDBC type. This is sufficient for
- * date/time types; it may be generalized later for e.g.
- * comparison of any user type with one of its subtypes.
- *
- * @see TypeCompiler#convertible
- *
- */
- public boolean convertible(TypeId otherType,
- boolean forDataTypeFunction)
- {
- if (otherType.isStringTypeId()&&
- (!otherType.isLongConcatableTypeId()))
- {
- return true;
- }
-
- int otherJDBCTypeId = otherType.getJDBCTypeId();
-
- /*
- ** At this point, we have only date/time. If
- ** same type, convert always ok.
- */
- if (otherJDBCTypeId == Types.TIMESTAMP)
- {
- return true;
- }
-
- /*
- ** Otherwise, we can convert timestamp to
- ** date or time only.
- */
- return ((otherJDBCTypeId == Types.DATE) ||
- (otherJDBCTypeId == Types.TIME));
- }
-
- /**
- * Tell whether this type (timestamp) is compatible with the given type.
- *
- * @param otherType The TypeId of the other type.
- */
- public boolean compatible(TypeId otherType)
- {
- if (otherType.isStringTypeId() &&
- (!otherType.isLongConcatableTypeId()))
- {
- return true;
- }
-
- /*
- ** Both are timestamp datatypes and hence compatible.
- */
- return (getStoredFormatIdFromTypeId() ==
- otherType.getTypeFormatId());
- }
-
- /**
- * User types are storable into other user types that they
- * are assignable to. The other type must be a subclass of
- * this type, or implement this type as one of its interfaces.
- *
- * Built-in types are also storable into user types when the built-in
- * type's corresponding Java type is assignable to the user type.
- *
- * @param otherType the type of the instance to store into this type.
- * @param cf A ClassFactory
- * @return true if otherType is storable into this type, else false.
- */
- public boolean storable(TypeId otherType, ClassFactory cf)
- {
- int otherJDBCTypeId = otherType.getJDBCTypeId();
-
- if (otherJDBCTypeId == Types.TIMESTAMP ||
- (otherJDBCTypeId == Types.CHAR) ||
- (otherJDBCTypeId == Types.VARCHAR))
- {
- return true;
- }
-
- return cf.getClassInspector().assignableTo(
- otherType.getCorrespondingJavaTypeName(),
- "java.sql.Timestamp");
- }
-
- /** @see TypeCompiler#interfaceName */
- public String interfaceName()
- {
- return ClassName.DateTimeDataValue;
- }
-
- /**
- * @see TypeCompiler#getCorrespondingPrimitiveTypeName
- */
-
- public String getCorrespondingPrimitiveTypeName()
- {
- return "java.sql.Timestamp";
- }
-
- /**
- * @see TypeCompiler#getCastToCharWidth
- */
- public int getCastToCharWidth(DataTypeDescriptor dts)
- {
- return 26; // DATE TIME.milliseconds (extra few for good measure)
- }
-
- public double estimatedMemoryUsage(DataTypeDescriptor dtd)
- {
- return 12.0;
- }
- protected String nullMethodName()
- {
- return "getNullTimestamp";
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.loader.ClassFactory;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.types.DateTimeDataValue;
+import org.apache.derby.iapi.types.DataValueFactory;
+import org.apache.derby.iapi.types.TypeId;
+
+import org.apache.derby.iapi.sql.compile.TypeCompiler;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import java.sql.Types;
+import org.apache.derby.iapi.reference.ClassName;
+
+public class TimestampTypeCompiler extends BaseTypeCompiler
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
+ /* TypeCompiler methods */
+
+ /**
+ * Timestamps are comparable to timestamps and to comparable
+ * user types.
+ *
+ * @param otherType the type of the instance to compare with this type.
+ * @param forEquals True if this is an = or <> comparison, false
+ * otherwise.
+ * @param cf A ClassFactory
+ * @return true if otherType is comparable to this type, else false.
+ */
+ public boolean comparable(TypeId otherType,
+ boolean forEquals,
+ ClassFactory cf)
+ {
+ return comparable(getTypeId(), otherType, forEquals, cf);
+ }
+
+ boolean comparable(TypeId leftType,
+ TypeId otherType,
+ boolean forEquals,
+ ClassFactory cf)
+ {
+
+ int otherJDBCTypeId = otherType.getJDBCTypeId();
+
+ // Long types cannot be compared
+ if (otherType.isLongConcatableTypeId())
+ return false;
+
+ TypeCompiler otherTC = getTypeCompiler(otherType);
+ if (otherJDBCTypeId == Types.TIMESTAMP || otherType.isStringTypeId())
+ return true;
+
+ /* User types know the rules for what can be compared to them */
+ if (otherType.userType())
+ {
+ return otherTC.comparable(getTypeId(), forEquals, cf);
+ }
+
+ return false;
+ }
+
+ /**
+ * User types are convertible to other user types only if
+ * (for now) they are the same type and are being used to
+ * implement some JDBC type. This is sufficient for
+ * date/time types; it may be generalized later for e.g.
+ * comparison of any user type with one of its subtypes.
+ *
+ * @see TypeCompiler#convertible
+ *
+ */
+ public boolean convertible(TypeId otherType,
+ boolean forDataTypeFunction)
+ {
+ if (otherType.isStringTypeId()&&
+ (!otherType.isLongConcatableTypeId()))
+ {
+ return true;
+ }
+
+ int otherJDBCTypeId = otherType.getJDBCTypeId();
+
+ /*
+ ** At this point, we have only date/time. If
+ ** same type, convert always ok.
+ */
+ if (otherJDBCTypeId == Types.TIMESTAMP)
+ {
+ return true;
+ }
+
+ /*
+ ** Otherwise, we can convert timestamp to
+ ** date or time only.
+ */
+ return ((otherJDBCTypeId == Types.DATE) ||
+ (otherJDBCTypeId == Types.TIME));
+ }
+
+ /**
+ * Tell whether this type (timestamp) is compatible with the given type.
+ *
+ * @param otherType The TypeId of the other type.
+ */
+ public boolean compatible(TypeId otherType)
+ {
+ if (otherType.isStringTypeId() &&
+ (!otherType.isLongConcatableTypeId()))
+ {
+ return true;
+ }
+
+ /*
+ ** Both are timestamp datatypes and hence compatible.
+ */
+ return (getStoredFormatIdFromTypeId() ==
+ otherType.getTypeFormatId());
+ }
+
+ /**
+ * User types are storable into other user types that they
+ * are assignable to. The other type must be a subclass of
+ * this type, or implement this type as one of its interfaces.
+ *
+ * Built-in types are also storable into user types when the built-in
+ * type's corresponding Java type is assignable to the user type.
+ *
+ * @param otherType the type of the instance to store into this type.
+ * @param cf A ClassFactory
+ * @return true if otherType is storable into this type, else false.
+ */
+ public boolean storable(TypeId otherType, ClassFactory cf)
+ {
+ int otherJDBCTypeId = otherType.getJDBCTypeId();
+
+ if (otherJDBCTypeId == Types.TIMESTAMP ||
+ (otherJDBCTypeId == Types.CHAR) ||
+ (otherJDBCTypeId == Types.VARCHAR))
+ {
+ return true;
+ }
+
+ return cf.getClassInspector().assignableTo(
+ otherType.getCorrespondingJavaTypeName(),
+ "java.sql.Timestamp");
+ }
+
+ /** @see TypeCompiler#interfaceName */
+ public String interfaceName()
+ {
+ return ClassName.DateTimeDataValue;
+ }
+
+ /**
+ * @see TypeCompiler#getCorrespondingPrimitiveTypeName
+ */
+
+ public String getCorrespondingPrimitiveTypeName()
+ {
+ return "java.sql.Timestamp";
+ }
+
+ /**
+ * @see TypeCompiler#getCastToCharWidth
+ */
+ public int getCastToCharWidth(DataTypeDescriptor dts)
+ {
+ return 26; // DATE TIME.milliseconds (extra few for good measure)
+ }
+
+ public double estimatedMemoryUsage(DataTypeDescriptor dtd)
+ {
+ return 12.0;
+ }
+ protected String nullMethodName()
+ {
+ return "getNullTimestamp";
+ }
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Token.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Token.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Token.java Fri Sep 24 10:33:20 2004
@@ -1,102 +1,102 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.sql.compile;
-
-/**
- * Describes the input token stream.
- */
-
-public class Token {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- /**
- * An integer that describes the kind of this token. This numbering
- * system is determined by JavaCCParser, and a table of these numbers is
- * stored in the file ...Constants.java.
- */
- public int kind;
-
- /**
- * beginLine and beginColumn describe the position of the first character
- * of this token; endLine and endColumn describe the position of the
- * last character of this token.
- */
- public int beginLine, beginColumn, endLine, endColumn;
-
- /**
- * beginOffset and endOffset are useful for siphoning substrings out of
- * the Statement so that we can recompile the substrings at upgrade time.
- * For instance, VIEW definitions and the Restrictions on Published Tables
- * need to be recompiled at upgrade time.
- */
- public int beginOffset, endOffset;
-
- /**
- * The string image of the token.
- */
- public String image;
-
- /**
- * A reference to the next regular (non-special) token from the input
- * stream. If this is the last token from the input stream, or if the
- * token manager has not read tokens beyond this one, this field is
- * set to null. This is true only if this token is also a regular
- * token. Otherwise, see below for a description of the contents of
- * this field.
- */
- public Token next;
-
- /**
- * This field is used to access special tokens that occur prior to this
- * token, but after the immediately preceding regular (non-special) token.
- * If there are no such special tokens, this field is set to null.
- * When there are more than one such special token, this field refers
- * to the last of these special tokens, which in turn refers to the next
- * previous special token through its specialToken field, and so on
- * until the first special token (whose specialToken field is null).
- * The next fields of special tokens refer to other special tokens that
- * immediately follow it (without an intervening regular token). If there
- * is no such token, this field is null.
- */
- public Token specialToken;
-
- /**
- * Returns the image.
- */
- public String toString()
- {
- return image;
- }
-
- /**
- * Returns a new Token object, by default. However, if you want, you
- * can create and return subclass objects based on the value of ofKind.
- * Simply add the cases to the switch for all those special cases.
- * For example, if you have a subclass of Token called IDToken that
- * you want to create if ofKind is ID, simlpy add something like :
- *
- * case MyParserConstants.ID : return new IDToken();
- *
- * to the following switch statement. Then you can cast matchedToken
- * variable to the appropriate type and use it in your lexical actions.
- */
- public static final Token newToken(int ofKind)
- {
- switch(ofKind)
- {
- default : return new Token();
- }
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.sql.compile;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ /**
+ * An integer that describes the kind of this token. This numbering
+ * system is determined by JavaCCParser, and a table of these numbers is
+ * stored in the file ...Constants.java.
+ */
+ public int kind;
+
+ /**
+ * beginLine and beginColumn describe the position of the first character
+ * of this token; endLine and endColumn describe the position of the
+ * last character of this token.
+ */
+ public int beginLine, beginColumn, endLine, endColumn;
+
+ /**
+ * beginOffset and endOffset are useful for siphoning substrings out of
+ * the Statement so that we can recompile the substrings at upgrade time.
+ * For instance, VIEW definitions and the Restrictions on Published Tables
+ * need to be recompiled at upgrade time.
+ */
+ public int beginOffset, endOffset;
+
+ /**
+ * The string image of the token.
+ */
+ public String image;
+
+ /**
+ * A reference to the next regular (non-special) token from the input
+ * stream. If this is the last token from the input stream, or if the
+ * token manager has not read tokens beyond this one, this field is
+ * set to null. This is true only if this token is also a regular
+ * token. Otherwise, see below for a description of the contents of
+ * this field.
+ */
+ public Token next;
+
+ /**
+ * This field is used to access special tokens that occur prior to this
+ * token, but after the immediately preceding regular (non-special) token.
+ * If there are no such special tokens, this field is set to null.
+ * When there are more than one such special token, this field refers
+ * to the last of these special tokens, which in turn refers to the next
+ * previous special token through its specialToken field, and so on
+ * until the first special token (whose specialToken field is null).
+ * The next fields of special tokens refer to other special tokens that
+ * immediately follow it (without an intervening regular token). If there
+ * is no such token, this field is null.
+ */
+ public Token specialToken;
+
+ /**
+ * Returns the image.
+ */
+ public String toString()
+ {
+ return image;
+ }
+
+ /**
+ * Returns a new Token object, by default. However, if you want, you
+ * can create and return subclass objects based on the value of ofKind.
+ * Simply add the cases to the switch for all those special cases.
+ * For example, if you have a subclass of Token called IDToken that
+ * you want to create if ofKind is ID, simlpy add something like :
+ *
+ * case MyParserConstants.ID : return new IDToken();
+ *
+ * to the following switch statement. Then you can cast matchedToken
+ * variable to the appropriate type and use it in your lexical actions.
+ */
+ public static final Token newToken(int ofKind)
+ {
+ switch(ofKind)
+ {
+ default : return new Token();
+ }
+ }
+
+}
Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TransactionStatementNode.java
==============================================================================
--- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TransactionStatementNode.java (original)
+++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TransactionStatementNode.java Fri Sep 24 10:33:20 2004
@@ -1,58 +1,58 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.sql.compile
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-
-package org.apache.derby.impl.sql.compile;
-
-import org.apache.derby.iapi.services.context.ContextManager;
-
-import org.apache.derby.iapi.services.sanity.SanityManager;
-
-/**
- * A TransactionStatementNode represents any type of Transaction statement:
- * SET TRANSACTION, COMMIT, and ROLLBACK.
- *
- * @author Ames Carlson
- */
-
-public abstract class TransactionStatementNode extends StatementNode
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- int activationKind()
- {
- return StatementNode.NEED_NOTHING_ACTIVATION;
- }
- /**
- * COMMIT and ROLLBACK are allowed to commit
- * and rollback, duh.
- *
- * @return false
- */
- public boolean isAtomic()
- {
- return false;
- }
-
- /**
- * Returns whether or not this Statement requires a set/clear savepoint
- * around its execution. The following statement "types" do not require them:
- * Cursor - unnecessary and won't work in a read only environment
- * Xact - savepoint will get blown away underneath us during commit/rollback
- *
- * @return boolean Whether or not this Statement requires a set/clear savepoint
- */
- public boolean needsSavepoint()
- {
- return false;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.sql.compile
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+
+package org.apache.derby.impl.sql.compile;
+
+import org.apache.derby.iapi.services.context.ContextManager;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+/**
+ * A TransactionStatementNode represents any type of Transaction statement:
+ * SET TRANSACTION, COMMIT, and ROLLBACK.
+ *
+ * @author Ames Carlson
+ */
+
+public abstract class TransactionStatementNode extends StatementNode
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ int activationKind()
+ {
+ return StatementNode.NEED_NOTHING_ACTIVATION;
+ }
+ /**
+ * COMMIT and ROLLBACK are allowed to commit
+ * and rollback, duh.
+ *
+ * @return false
+ */
+ public boolean isAtomic()
+ {
+ return false;
+ }
+
+ /**
+ * Returns whether or not this Statement requires a set/clear savepoint
+ * around its execution. The following statement "types" do not require them:
+ * Cursor - unnecessary and won't work in a read only environment
+ * Xact - savepoint will get blown away underneath us during commit/rollback
+ *
+ * @return boolean Whether or not this Statement requires a set/clear savepoint
+ */
+ public boolean needsSavepoint()
+ {
+ return false;
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ConnectionEnv.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ConnectionEnv.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ConnectionEnv.java Fri Sep 24 10:33:20 2004
@@ -1,205 +1,205 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import java.util.Hashtable;
-import java.util.Enumeration;
-import java.util.Properties;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
-import org.apache.derby.tools.JDBCDisplayUtil;
-import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
-
-/**
- To enable multi-user use of ij.Main2
-
- @author jerry
- */
-class ConnectionEnv {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- Hashtable sessions = new Hashtable();
- private Session currSession;
- private String tag;
- private boolean only;
- private static final String CONNECTION_PROPERTY = "ij.connection";
- private String protocol;
-
- ConnectionEnv(int userNumber, boolean printUserNumber, boolean theOnly) {
- if (printUserNumber)
- tag = "("+(userNumber+1)+")";
- only = theOnly;
- }
-
- /**
- separate from the constructor so that connection
- failure does not prevent object creation.
- */
- void init(LocalizedOutput out) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
-
- Connection c = util.startJBMS(null,null);
-
- // only load up ij.connection.* properties if there is
- // only one ConnectionEnv in the system.
- if (only) {
- Properties p = System.getProperties();
- protocol = p.getProperty(ij.PROTOCOL_PROPERTY);
-
- String prefix = CONNECTION_PROPERTY + ".";
- for (Enumeration e = p.propertyNames(); e.hasMoreElements(); )
- {
- String key = (String)e.nextElement();
- if (key.startsWith(prefix)) {
- String name = key.substring(prefix.length());
- installConnection(name.toUpperCase(java.util.Locale.ENGLISH),
- p.getProperty(key), out);
- }
- }
- }
-
- if (c!=null) // have a database from the startup?
- {
- String sname=Session.DEFAULT_NAME+sessions.size();
- Session s = new Session(c,tag,sname);
- sessions.put(sname,s);
- currSession = s;
- }
-
- }
-
- void doPrompt(boolean newStatement, LocalizedOutput out) {
- if (currSession != null) currSession.doPrompt(newStatement, out, sessions.size()>1);
- else utilMain.doPrompt(newStatement, out, tag);
- }
-
- Connection getConnection() {
- if (currSession == null) return null;
- return currSession.getConnection();
- }
-
- /**
- Making a new connection, add it to the pool, and make it current.
- */
- void addSession(Connection conn,String name) {
- String aName;
- if (name == null) aName = getUniqueConnectionName();
- else aName = name;
- Session s = new Session(conn, tag, aName);
- sessions.put(aName, s);
- currSession = s;
- }
-
- //returns a unique Connection# name by going through existing sessions
- public String getUniqueConnectionName() {
- int newNum = 0;
- boolean newConnectionNameOk = false;
- String newConnectionName = "";
- Enumeration enum;
- while (!newConnectionNameOk){
- newConnectionName = Session.DEFAULT_NAME + newNum;
- newConnectionNameOk = true;
- enum = sessions.keys();
- while (enum.hasMoreElements() && newConnectionNameOk){
- if (((String)enum.nextElement()).equals(newConnectionName))
- newConnectionNameOk = false;
- }
- newNum = newNum + 1;
- }
- return newConnectionName;
- }
-
- Session getSession() {
- return currSession;
- }
-
- Hashtable getSessions() {
- return sessions;
- }
-
- Session setCurrentSession(String name) {
- currSession = (Session) sessions.get(name);
- return currSession;
- }
-
- boolean haveSession(String name) {
- return (name != null) && (sessions.size()>0) && (null != sessions.get(name));
- }
-
- void removeCurrentSession() throws SQLException {
- if (currSession ==null) return;
- sessions.remove(currSession.getName());
- currSession.close();
- currSession = null;
- }
-
- void removeSession(String name) throws SQLException {
- Session s = (Session) sessions.remove(name);
- s.close();
- if (currSession == s)
- currSession = null;
- }
-
- void removeAllSessions() throws SQLException {
- if (sessions == null || sessions.size() == 0)
- return;
- else
- for (Enumeration e = sessions.keys(); e.hasMoreElements(); ) {
- String n = (String)e.nextElement();
- removeSession(n);
- }
- }
-
- private void installConnection(String name, String value, LocalizedOutput out) throws SQLException {
- // add protocol if no driver matches url
- boolean noDriver = false;
- try {
- // if we have a full URL, make sure it's loaded first
- try {
- if (value.startsWith("jdbc:"))
- util.loadDriverIfKnown(value);
- } catch (Exception e) {
- // want to continue with the attempt
- }
- DriverManager.getDriver(value);
- } catch (SQLException se) {
- noDriver = true;
- }
- if (noDriver && (protocol != null)) {
- value = protocol + value;
- }
-
- if (sessions.get(name) != null) {
- throw ijException.alreadyHaveConnectionNamed(name);
- }
- try {
-
- String user = util.getSystemProperty("ij.user");
- String password = util.getSystemProperty("ij.password");
- Properties connInfo = util.updateConnInfo(user, password,null);
-
- Connection theConnection =
- DriverManager.getConnection(value, connInfo);
-
- addSession(theConnection,name);
- } catch (Throwable t) {
- JDBCDisplayUtil.ShowException(out,t);
- }
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.apache.derby.tools.JDBCDisplayUtil;
+import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
+
+/**
+ To enable multi-user use of ij.Main2
+
+ @author jerry
+ */
+class ConnectionEnv {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ Hashtable sessions = new Hashtable();
+ private Session currSession;
+ private String tag;
+ private boolean only;
+ private static final String CONNECTION_PROPERTY = "ij.connection";
+ private String protocol;
+
+ ConnectionEnv(int userNumber, boolean printUserNumber, boolean theOnly) {
+ if (printUserNumber)
+ tag = "("+(userNumber+1)+")";
+ only = theOnly;
+ }
+
+ /**
+ separate from the constructor so that connection
+ failure does not prevent object creation.
+ */
+ void init(LocalizedOutput out) throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
+
+ Connection c = util.startJBMS(null,null);
+
+ // only load up ij.connection.* properties if there is
+ // only one ConnectionEnv in the system.
+ if (only) {
+ Properties p = System.getProperties();
+ protocol = p.getProperty(ij.PROTOCOL_PROPERTY);
+
+ String prefix = CONNECTION_PROPERTY + ".";
+ for (Enumeration e = p.propertyNames(); e.hasMoreElements(); )
+ {
+ String key = (String)e.nextElement();
+ if (key.startsWith(prefix)) {
+ String name = key.substring(prefix.length());
+ installConnection(name.toUpperCase(java.util.Locale.ENGLISH),
+ p.getProperty(key), out);
+ }
+ }
+ }
+
+ if (c!=null) // have a database from the startup?
+ {
+ String sname=Session.DEFAULT_NAME+sessions.size();
+ Session s = new Session(c,tag,sname);
+ sessions.put(sname,s);
+ currSession = s;
+ }
+
+ }
+
+ void doPrompt(boolean newStatement, LocalizedOutput out) {
+ if (currSession != null) currSession.doPrompt(newStatement, out, sessions.size()>1);
+ else utilMain.doPrompt(newStatement, out, tag);
+ }
+
+ Connection getConnection() {
+ if (currSession == null) return null;
+ return currSession.getConnection();
+ }
+
+ /**
+ Making a new connection, add it to the pool, and make it current.
+ */
+ void addSession(Connection conn,String name) {
+ String aName;
+ if (name == null) aName = getUniqueConnectionName();
+ else aName = name;
+ Session s = new Session(conn, tag, aName);
+ sessions.put(aName, s);
+ currSession = s;
+ }
+
+ //returns a unique Connection# name by going through existing sessions
+ public String getUniqueConnectionName() {
+ int newNum = 0;
+ boolean newConnectionNameOk = false;
+ String newConnectionName = "";
+ Enumeration enum;
+ while (!newConnectionNameOk){
+ newConnectionName = Session.DEFAULT_NAME + newNum;
+ newConnectionNameOk = true;
+ enum = sessions.keys();
+ while (enum.hasMoreElements() && newConnectionNameOk){
+ if (((String)enum.nextElement()).equals(newConnectionName))
+ newConnectionNameOk = false;
+ }
+ newNum = newNum + 1;
+ }
+ return newConnectionName;
+ }
+
+ Session getSession() {
+ return currSession;
+ }
+
+ Hashtable getSessions() {
+ return sessions;
+ }
+
+ Session setCurrentSession(String name) {
+ currSession = (Session) sessions.get(name);
+ return currSession;
+ }
+
+ boolean haveSession(String name) {
+ return (name != null) && (sessions.size()>0) && (null != sessions.get(name));
+ }
+
+ void removeCurrentSession() throws SQLException {
+ if (currSession ==null) return;
+ sessions.remove(currSession.getName());
+ currSession.close();
+ currSession = null;
+ }
+
+ void removeSession(String name) throws SQLException {
+ Session s = (Session) sessions.remove(name);
+ s.close();
+ if (currSession == s)
+ currSession = null;
+ }
+
+ void removeAllSessions() throws SQLException {
+ if (sessions == null || sessions.size() == 0)
+ return;
+ else
+ for (Enumeration e = sessions.keys(); e.hasMoreElements(); ) {
+ String n = (String)e.nextElement();
+ removeSession(n);
+ }
+ }
+
+ private void installConnection(String name, String value, LocalizedOutput out) throws SQLException {
+ // add protocol if no driver matches url
+ boolean noDriver = false;
+ try {
+ // if we have a full URL, make sure it's loaded first
+ try {
+ if (value.startsWith("jdbc:"))
+ util.loadDriverIfKnown(value);
+ } catch (Exception e) {
+ // want to continue with the attempt
+ }
+ DriverManager.getDriver(value);
+ } catch (SQLException se) {
+ noDriver = true;
+ }
+ if (noDriver && (protocol != null)) {
+ value = protocol + value;
+ }
+
+ if (sessions.get(name) != null) {
+ throw ijException.alreadyHaveConnectionNamed(name);
+ }
+ try {
+
+ String user = util.getSystemProperty("ij.user");
+ String password = util.getSystemProperty("ij.password");
+ Properties connInfo = util.updateConnInfo(user, password,null);
+
+ Connection theConnection =
+ DriverManager.getConnection(value, connInfo);
+
+ addSession(theConnection,name);
+ } catch (Throwable t) {
+ JDBCDisplayUtil.ShowException(out,t);
+ }
+ }
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main.java Fri Sep 24 10:33:20 2004
@@ -1,252 +1,252 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.tools.JDBCDisplayUtil;
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-import org.apache.derby.iapi.tools.i18n.LocalizedInput;
-import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
-
-import java.io.FileInputStream;
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-import java.io.IOException;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
-import java.util.*;
-
-/**
- * This is the controller for ij. It uses two parsers:
- * one to grab the next statement, and another to
- * see if it is an ij command, and if so execute it.
- * If it is not an ij command, it is treated as a JSQL
- * statement and executed against the current connection.
- * ijParser controls the current connection, and so contains
- * all of the state information for executing JSQL statements.
- * <p>
- * This was written to facilitate a test harness for language
- * functionality tests.
- *
- * @author ames
- *
- */
-public class Main {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- public LocalizedOutput out;
- public utilMain utilInstance;
- public Class langUtilClass;
-
-
-
- /**
- * ij can be used directly on a shell command line through
- * its main program.
- * @param args allows 1 file name to be specified, from which
- * input will be read; if not specified, stdin is used.
- */
- public static void main(String[] args)
- throws IOException
- {
- mainCore(args, new Main(true));
- }
-
- public static void mainCore(String[] args, Main main)
- throws IOException
- {
- LocalizedInput in = null;
- InputStream in1 = null;
- Main me;
- String file;
- String inputResourceName;
- boolean gotProp;
-
- String tmpUnicode = null;
- Properties connAttributeDefaults = null;
-
- // load the property file if specified
- gotProp = util.getPropertyArg(args);
-
- // get the default connection attributes
- connAttributeDefaults = util.getConnAttributeArg(args);
- // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
- main.initAppUI();
-
- LocalizedResource langUtil = LocalizedResource.getInstance();
-
- LocalizedOutput out = langUtil.getNewOutput(System.out);
-
- file = util.getFileArg(args);
- inputResourceName = util.getInputResourceNameArg(args);
- if (util.invalidArgs(args, gotProp, file, inputResourceName)) {
- util.Usage(out);
- return;
- }
- else if (inputResourceName != null) {
- in = langUtil.getNewInput(util.getResourceAsStream(inputResourceName));
- if (in == null) {
- out.println(langUtil.getTextMessage("IJ_IjErroResoNo",inputResourceName));
- return;
- }
- } else if (file == null) {
- in = langUtil.getNewInput(System.in);
- out.flush();
- } else {
- try {
- in1 = new FileInputStream(file);
- if (in1 != null) {
- in1 = new BufferedInputStream(in1, utilMain.BUFFEREDFILESIZE);
- in = langUtil.getNewInput(in1);
- }
- } catch (FileNotFoundException e) {
- if (Boolean.getBoolean("ij.searchClassPath")) {
- in = langUtil.getNewInput(util.getResourceAsStream(file));
- }
- if (in == null) {
- out.println(langUtil.getTextMessage("IJ_IjErroFileNo",file));
- return;
- }
- }
- }
-
- // set initial Unicode Escape Mode
- tmpUnicode = util.getSystemProperty("ij.unicodeEscape");
- if ((tmpUnicode != null) && tmpUnicode.toUpperCase(Locale.ENGLISH).equals("ON")) {
- LocalizedResource.setUnicodeEscape(true);
- }
- String outFile = util.getSystemProperty("ij.outfile");
- if (outFile != null && outFile.length()>0) {
- LocalizedOutput oldOut = out;
- try {
- out = langUtil.getNewOutput(new FileOutputStream(outFile));
- }
- catch (IOException ioe) {
- oldOut.println(langUtil.getTextMessage("IJ_IjErroUnabTo",outFile));
- }
- }
-
- // the old property name is deprecated...
- String maxDisplayWidth = util.getSystemProperty("maximumDisplayWidth");
- if (maxDisplayWidth==null)
- maxDisplayWidth = util.getSystemProperty("ij.maximumDisplayWidth");
- if (maxDisplayWidth != null && maxDisplayWidth.length() > 0) {
- try {
- int maxWidth = Integer.parseInt(maxDisplayWidth);
- JDBCDisplayUtil.setMaxDisplayWidth(maxWidth);
- }
- catch (NumberFormatException nfe) {
- out.println(langUtil.getTextMessage("IJ_IjErroMaxiVa", maxDisplayWidth));
- }
- }
-
- /* Use the main parameter to get to
- * a new Main that we can use.
- * (We can't do the work in Main(out)
- * until after we do all of the work above
- * us in this method.
- */
- me = main.getMain(out);
-
- /* Let the processing begin! */
- me.go(in, out, connAttributeDefaults);
- in.close(); out.close();
- }
-
- /**
- * Get the right Main (according to
- * the JDBC version.
- *
- * @return The right main (according to the JDBC version).
- */
- public Main getMain(LocalizedOutput out)
- {
- return new Main(out);
- }
-
- /**
- * Get the right utilMain (according to
- * the JDBC version.
- *
- * @return The right utilMain (according to the JDBC version).
- */
- public utilMain getutilMain(int numConnections, LocalizedOutput out)
- {
- return new utilMain(numConnections, out);
- }
-
- /**
- Give a shortcut to go on the utilInstance so
- we don't expose utilMain.
- */
- public void go(LocalizedInput in, LocalizedOutput out ,
- Properties connAttributeDefaults)
- {
- LocalizedInput[] inA = { in } ;
- utilInstance.go(inA, out,connAttributeDefaults);
- }
-
- public void go(InputStream in, PrintStream out,
- Properties connAttributeDefaults)
- {
- initAppUI();
- LocalizedResource langUtil = LocalizedResource.getInstance();
- go(langUtil.getNewInput(in), langUtil.getNewOutput(out),
- connAttributeDefaults);
- }
-
- /**
- * create an ij tool waiting to be given input and output streams.
- */
- public Main() {
- this(null);
- }
-
- public Main(LocalizedOutput out) {
- if (out!=null) {
- this.out = out;
- } else {
- this.out = LocalizedResource.getInstance().getNewOutput(System.out);
- }
- utilInstance = getutilMain(1, this.out);
- }
-
- /**
- * This constructor is only used so that we
- * can get to the right Main based on the
- * JDBC version. We don't do any work in
- * this constructor and we only use this
- * object to get to the right Main via
- * getMain().
- */
- public Main(boolean trash)
- {
- }
- public void initAppUI(){
- //To fix a problem in the AppUI implementation, a reference to the AppUI class is
- //maintained by this tool. Without this reference, it is possible for the
- //AppUI class to be garbage collected and the initialization values lost.
- //langUtilClass = LocalizedResource.class;
-
- // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
- LocalizedResource.getInstance();
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.tools.JDBCDisplayUtil;
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+import org.apache.derby.iapi.tools.i18n.LocalizedInput;
+import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
+
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.io.IOException;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import java.util.*;
+
+/**
+ * This is the controller for ij. It uses two parsers:
+ * one to grab the next statement, and another to
+ * see if it is an ij command, and if so execute it.
+ * If it is not an ij command, it is treated as a JSQL
+ * statement and executed against the current connection.
+ * ijParser controls the current connection, and so contains
+ * all of the state information for executing JSQL statements.
+ * <p>
+ * This was written to facilitate a test harness for language
+ * functionality tests.
+ *
+ * @author ames
+ *
+ */
+public class Main {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ public LocalizedOutput out;
+ public utilMain utilInstance;
+ public Class langUtilClass;
+
+
+
+ /**
+ * ij can be used directly on a shell command line through
+ * its main program.
+ * @param args allows 1 file name to be specified, from which
+ * input will be read; if not specified, stdin is used.
+ */
+ public static void main(String[] args)
+ throws IOException
+ {
+ mainCore(args, new Main(true));
+ }
+
+ public static void mainCore(String[] args, Main main)
+ throws IOException
+ {
+ LocalizedInput in = null;
+ InputStream in1 = null;
+ Main me;
+ String file;
+ String inputResourceName;
+ boolean gotProp;
+
+ String tmpUnicode = null;
+ Properties connAttributeDefaults = null;
+
+ // load the property file if specified
+ gotProp = util.getPropertyArg(args);
+
+ // get the default connection attributes
+ connAttributeDefaults = util.getConnAttributeArg(args);
+ // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
+ main.initAppUI();
+
+ LocalizedResource langUtil = LocalizedResource.getInstance();
+
+ LocalizedOutput out = langUtil.getNewOutput(System.out);
+
+ file = util.getFileArg(args);
+ inputResourceName = util.getInputResourceNameArg(args);
+ if (util.invalidArgs(args, gotProp, file, inputResourceName)) {
+ util.Usage(out);
+ return;
+ }
+ else if (inputResourceName != null) {
+ in = langUtil.getNewInput(util.getResourceAsStream(inputResourceName));
+ if (in == null) {
+ out.println(langUtil.getTextMessage("IJ_IjErroResoNo",inputResourceName));
+ return;
+ }
+ } else if (file == null) {
+ in = langUtil.getNewInput(System.in);
+ out.flush();
+ } else {
+ try {
+ in1 = new FileInputStream(file);
+ if (in1 != null) {
+ in1 = new BufferedInputStream(in1, utilMain.BUFFEREDFILESIZE);
+ in = langUtil.getNewInput(in1);
+ }
+ } catch (FileNotFoundException e) {
+ if (Boolean.getBoolean("ij.searchClassPath")) {
+ in = langUtil.getNewInput(util.getResourceAsStream(file));
+ }
+ if (in == null) {
+ out.println(langUtil.getTextMessage("IJ_IjErroFileNo",file));
+ return;
+ }
+ }
+ }
+
+ // set initial Unicode Escape Mode
+ tmpUnicode = util.getSystemProperty("ij.unicodeEscape");
+ if ((tmpUnicode != null) && tmpUnicode.toUpperCase(Locale.ENGLISH).equals("ON")) {
+ LocalizedResource.setUnicodeEscape(true);
+ }
+ String outFile = util.getSystemProperty("ij.outfile");
+ if (outFile != null && outFile.length()>0) {
+ LocalizedOutput oldOut = out;
+ try {
+ out = langUtil.getNewOutput(new FileOutputStream(outFile));
+ }
+ catch (IOException ioe) {
+ oldOut.println(langUtil.getTextMessage("IJ_IjErroUnabTo",outFile));
+ }
+ }
+
+ // the old property name is deprecated...
+ String maxDisplayWidth = util.getSystemProperty("maximumDisplayWidth");
+ if (maxDisplayWidth==null)
+ maxDisplayWidth = util.getSystemProperty("ij.maximumDisplayWidth");
+ if (maxDisplayWidth != null && maxDisplayWidth.length() > 0) {
+ try {
+ int maxWidth = Integer.parseInt(maxDisplayWidth);
+ JDBCDisplayUtil.setMaxDisplayWidth(maxWidth);
+ }
+ catch (NumberFormatException nfe) {
+ out.println(langUtil.getTextMessage("IJ_IjErroMaxiVa", maxDisplayWidth));
+ }
+ }
+
+ /* Use the main parameter to get to
+ * a new Main that we can use.
+ * (We can't do the work in Main(out)
+ * until after we do all of the work above
+ * us in this method.
+ */
+ me = main.getMain(out);
+
+ /* Let the processing begin! */
+ me.go(in, out, connAttributeDefaults);
+ in.close(); out.close();
+ }
+
+ /**
+ * Get the right Main (according to
+ * the JDBC version.
+ *
+ * @return The right main (according to the JDBC version).
+ */
+ public Main getMain(LocalizedOutput out)
+ {
+ return new Main(out);
+ }
+
+ /**
+ * Get the right utilMain (according to
+ * the JDBC version.
+ *
+ * @return The right utilMain (according to the JDBC version).
+ */
+ public utilMain getutilMain(int numConnections, LocalizedOutput out)
+ {
+ return new utilMain(numConnections, out);
+ }
+
+ /**
+ Give a shortcut to go on the utilInstance so
+ we don't expose utilMain.
+ */
+ public void go(LocalizedInput in, LocalizedOutput out ,
+ Properties connAttributeDefaults)
+ {
+ LocalizedInput[] inA = { in } ;
+ utilInstance.go(inA, out,connAttributeDefaults);
+ }
+
+ public void go(InputStream in, PrintStream out,
+ Properties connAttributeDefaults)
+ {
+ initAppUI();
+ LocalizedResource langUtil = LocalizedResource.getInstance();
+ go(langUtil.getNewInput(in), langUtil.getNewOutput(out),
+ connAttributeDefaults);
+ }
+
+ /**
+ * create an ij tool waiting to be given input and output streams.
+ */
+ public Main() {
+ this(null);
+ }
+
+ public Main(LocalizedOutput out) {
+ if (out!=null) {
+ this.out = out;
+ } else {
+ this.out = LocalizedResource.getInstance().getNewOutput(System.out);
+ }
+ utilInstance = getutilMain(1, this.out);
+ }
+
+ /**
+ * This constructor is only used so that we
+ * can get to the right Main based on the
+ * JDBC version. We don't do any work in
+ * this constructor and we only use this
+ * object to get to the right Main via
+ * getMain().
+ */
+ public Main(boolean trash)
+ {
+ }
+ public void initAppUI(){
+ //To fix a problem in the AppUI implementation, a reference to the AppUI class is
+ //maintained by this tool. Without this reference, it is possible for the
+ //AppUI class to be garbage collected and the initialization values lost.
+ //langUtilClass = LocalizedResource.class;
+
+ // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
+ LocalizedResource.getInstance();
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main14.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main14.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Main14.java Fri Sep 24 10:33:20 2004
@@ -1,100 +1,100 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 2002, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.tools.JDBCDisplayUtil;
-
-
-import java.io.BufferedInputStream;
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
-/**
- * This is the controller for the JDBC3.0 version
- * of ij.
- * <p>
- * This was written to facilitate a test harness for the
- * holding cursors over commit functionality in JDBC3.0.
- *
- */
-public class Main14 extends Main
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2002_2004;
- /**
- * ij can be used directly on a shell command line through
- * its main program.
- * @param args allows 1 file name to be specified, from which
- * input will be read; if not specified, stdin is used.
- */
- public static void main(String[] args) throws IOException
- {
- Main.mainCore(args, new Main14(true));
- }
-
- /**
- * create an ij tool waiting to be given input and output streams.
- */
- public Main14()
- {
- this(null);
- }
-
- public Main14(LocalizedOutput out)
- {
- super(out);
- }
-
- /**
- * This constructor is only used so that we
- * can get to the right Main based on the
- * JDBC version. We don't do any work in
- * this constructor and we only use this
- * object to get to the right Main via
- * getMain().
- */
- public Main14(boolean trash)
- {
- super(trash);
- }
- /**
- * Get the right Main (according to
- * the JDBC version.
- *
- * @return The right Main (according to the JDBC version).
- */
- public Main getMain(LocalizedOutput out)
- {
- return new Main14(out);
- }
-
- /**
- * Get the right utilMain (according to
- * the JDBC version.
- *
- * @return The right utilMain (according to the JDBC version).
- */
- public utilMain getutilMain(int numConnections, LocalizedOutput out)
- {
- return new utilMain14(numConnections, out);
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 2002, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.tools.JDBCDisplayUtil;
+
+
+import java.io.BufferedInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.IOException;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
+/**
+ * This is the controller for the JDBC3.0 version
+ * of ij.
+ * <p>
+ * This was written to facilitate a test harness for the
+ * holding cursors over commit functionality in JDBC3.0.
+ *
+ */
+public class Main14 extends Main
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2002_2004;
+ /**
+ * ij can be used directly on a shell command line through
+ * its main program.
+ * @param args allows 1 file name to be specified, from which
+ * input will be read; if not specified, stdin is used.
+ */
+ public static void main(String[] args) throws IOException
+ {
+ Main.mainCore(args, new Main14(true));
+ }
+
+ /**
+ * create an ij tool waiting to be given input and output streams.
+ */
+ public Main14()
+ {
+ this(null);
+ }
+
+ public Main14(LocalizedOutput out)
+ {
+ super(out);
+ }
+
+ /**
+ * This constructor is only used so that we
+ * can get to the right Main based on the
+ * JDBC version. We don't do any work in
+ * this constructor and we only use this
+ * object to get to the right Main via
+ * getMain().
+ */
+ public Main14(boolean trash)
+ {
+ super(trash);
+ }
+ /**
+ * Get the right Main (according to
+ * the JDBC version.
+ *
+ * @return The right Main (according to the JDBC version).
+ */
+ public Main getMain(LocalizedOutput out)
+ {
+ return new Main14(out);
+ }
+
+ /**
+ * Get the right utilMain (according to
+ * the JDBC version.
+ *
+ * @return The right utilMain (according to the JDBC version).
+ */
+ public utilMain getutilMain(int numConnections, LocalizedOutput out)
+ {
+ return new utilMain14(numConnections, out);
+ }
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ParseException.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ParseException.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ParseException.java Fri Sep 24 10:33:20 2004
@@ -1,208 +1,208 @@
-/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-package org.apache.derby.impl.tools.ij;
-
-/**
- * This exception is thrown when parse errors are encountered.
- * You can explicitly create objects of this exception type by
- * calling the method generateParseException in the generated
- * parser.
- *
- * You can modify this class to customize your error reporting
- * mechanisms so long as you retain the public fields.
- */
-public class ParseException extends Exception {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
- /**
- * This constructor is used by the method "generateParseException"
- * in the generated parser. Calling this constructor generates
- * a new object of this type with the fields "currentToken",
- * "expectedTokenSequences", and "tokenImage" set. The boolean
- * flag "specialConstructor" is also set to true to indicate that
- * this constructor was used to create this object.
- * This constructor calls its super class with the empty string
- * to force the "toString" method of parent class "Throwable" to
- * print the error message in the form:
- * ParseException: <result of getMessage>
- */
- public ParseException(Token currentTokenVal,
- int[][] expectedTokenSequencesVal,
- String[] tokenImageVal
- )
- {
- super("");
- specialConstructor = true;
- currentToken = currentTokenVal;
- expectedTokenSequences = expectedTokenSequencesVal;
- tokenImage = tokenImageVal;
- }
-
- /**
- * The following constructors are for use by you for whatever
- * purpose you can think of. Constructing the exception in this
- * manner makes the exception behave in the normal way - i.e., as
- * documented in the class "Throwable". The fields "errorToken",
- * "expectedTokenSequences", and "tokenImage" do not contain
- * relevant information. The JavaCC generated code does not use
- * these constructors.
- */
-
- public ParseException() {
- super();
- specialConstructor = false;
- }
-
- public ParseException(String message) {
- super(message);
- specialConstructor = false;
- }
-
- /**
- * This variable determines which constructor was used to create
- * this object and thereby affects the semantics of the
- * "getMessage" method (see below).
- */
- protected boolean specialConstructor;
-
- /**
- * This is the last token that has been consumed successfully. If
- * this object has been created due to a parse error, the token
- * followng this token will (therefore) be the first error token.
- */
- public Token currentToken;
-
- /**
- * Each entry in this array is an array of integers. Each array
- * of integers represents a sequence of tokens (by their ordinal
- * values) that is expected at this point of the parse.
- */
- public int[][] expectedTokenSequences;
-
- /**
- * This is a reference to the "tokenImage" array of the generated
- * parser within which the parse error occurred. This array is
- * defined in the generated ...Constants interface.
- */
- public String[] tokenImage;
-
- /**
- * This method has the standard behavior when this object has been
- * created using the standard constructors. Otherwise, it uses
- * "currentToken" and "expectedTokenSequences" to generate a parse
- * error message and returns it. If this object has been created
- * due to a parse error, and you do not catch it (it gets thrown
- * from the parser), then this method is called during the printing
- * of the final stack trace, and hence the correct error message
- * gets displayed.
- */
- public String getMessage() {
- if (!specialConstructor) {
- return super.getMessage();
- }
- String expected = "";
- int maxSize = 0;
- for (int i = 0; i < expectedTokenSequences.length; i++) {
- if (maxSize < expectedTokenSequences[i].length) {
- maxSize = expectedTokenSequences[i].length;
- }
- for (int j = 0; j < expectedTokenSequences[i].length; j++) {
- expected += tokenImage[expectedTokenSequences[i][j]] + " ";
- }
- if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
- expected += "...";
- }
- expected += eol + " ";
- }
- String retval = "Encountered \"";
- Token tok = currentToken.next;
- for (int i = 0; i < maxSize; i++) {
- if (i != 0) retval += " ";
- if (tok.kind == 0) {
- retval += tokenImage[0];
- break;
- }
- retval += add_escapes(tok.image);
- tok = tok.next;
- }
- retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
- /*
- * for output compatibility with previous releases, do not report expected tokens.
- *
- retval += "." + eol;
- if (expectedTokenSequences.length == 1) {
- retval += "Was expecting:" + eol + " ";
- } else {
- retval += "Was expecting one of:" + eol + " ";
- }
- retval += expected;
- */
- return retval;
- }
-
- /**
- * The end of line string for this machine.
- */
- protected String eol = System.getProperty("line.separator", "\n");
-
- /**
- * Used to convert raw characters to their escaped version
- * when these raw version cannot be used as part of an ASCII
- * string literal.
- */
- protected String add_escapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
- }
- }
- return retval.toString();
- }
-
-}
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+package org.apache.derby.impl.tools.ij;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+ /**
+ * This constructor is used by the method "generateParseException"
+ * in the generated parser. Calling this constructor generates
+ * a new object of this type with the fields "currentToken",
+ * "expectedTokenSequences", and "tokenImage" set. The boolean
+ * flag "specialConstructor" is also set to true to indicate that
+ * this constructor was used to create this object.
+ * This constructor calls its super class with the empty string
+ * to force the "toString" method of parent class "Throwable" to
+ * print the error message in the form:
+ * ParseException: <result of getMessage>
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal,
+ String[] tokenImageVal
+ )
+ {
+ super("");
+ specialConstructor = true;
+ currentToken = currentTokenVal;
+ expectedTokenSequences = expectedTokenSequencesVal;
+ tokenImage = tokenImageVal;
+ }
+
+ /**
+ * The following constructors are for use by you for whatever
+ * purpose you can think of. Constructing the exception in this
+ * manner makes the exception behave in the normal way - i.e., as
+ * documented in the class "Throwable". The fields "errorToken",
+ * "expectedTokenSequences", and "tokenImage" do not contain
+ * relevant information. The JavaCC generated code does not use
+ * these constructors.
+ */
+
+ public ParseException() {
+ super();
+ specialConstructor = false;
+ }
+
+ public ParseException(String message) {
+ super(message);
+ specialConstructor = false;
+ }
+
+ /**
+ * This variable determines which constructor was used to create
+ * this object and thereby affects the semantics of the
+ * "getMessage" method (see below).
+ */
+ protected boolean specialConstructor;
+
+ /**
+ * This is the last token that has been consumed successfully. If
+ * this object has been created due to a parse error, the token
+ * followng this token will (therefore) be the first error token.
+ */
+ public Token currentToken;
+
+ /**
+ * Each entry in this array is an array of integers. Each array
+ * of integers represents a sequence of tokens (by their ordinal
+ * values) that is expected at this point of the parse.
+ */
+ public int[][] expectedTokenSequences;
+
+ /**
+ * This is a reference to the "tokenImage" array of the generated
+ * parser within which the parse error occurred. This array is
+ * defined in the generated ...Constants interface.
+ */
+ public String[] tokenImage;
+
+ /**
+ * This method has the standard behavior when this object has been
+ * created using the standard constructors. Otherwise, it uses
+ * "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created
+ * due to a parse error, and you do not catch it (it gets thrown
+ * from the parser), then this method is called during the printing
+ * of the final stack trace, and hence the correct error message
+ * gets displayed.
+ */
+ public String getMessage() {
+ if (!specialConstructor) {
+ return super.getMessage();
+ }
+ String expected = "";
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected += tokenImage[expectedTokenSequences[i][j]] + " ";
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+ expected += "...";
+ }
+ expected += eol + " ";
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0) retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += add_escapes(tok.image);
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+ /*
+ * for output compatibility with previous releases, do not report expected tokens.
+ *
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected;
+ */
+ return retval;
+ }
+
+ /**
+ * The end of line string for this machine.
+ */
+ protected String eol = System.getProperty("line.separator", "\n");
+
+ /**
+ * Used to convert raw characters to their escaped version
+ * when these raw version cannot be used as part of an ASCII
+ * string literal.
+ */
+ protected String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Session.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Session.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/Session.java Fri Sep 24 10:33:20 2004
@@ -1,161 +1,161 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.Statement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Hashtable;
-
-/**
- Session holds the objects local to a particular database session,
- which starts with a connection and is all other JDBC
- stuff used on that connection, along with some ij state
- that is connection-based as well.
-
- This is separated out to localize database objects and
- also group objects by session.
-
- @author ames
- */
-class Session {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- static final String DEFAULT_NAME="CONNECTION";
-
- boolean singleSession = true;
- Connection conn = null;
- String tag, name;
- Hashtable prepStmts = new Hashtable();
- Hashtable cursorStmts = new Hashtable();
- Hashtable cursors = new Hashtable();
- Hashtable asyncStmts = new Hashtable();
- boolean isJCC= false; // Is this the IBM UNIVERSAL DRIVER.
-
- Session(Connection newConn, String newTag, String newName) {
- conn = newConn;
- tag = newTag;
- name = newName;
-
- try
- {
- isJCC = conn.getMetaData().getDriverName().startsWith("IBM DB2 JDBC Universal Driver");
- }
- catch (SQLException se)
- {
- // if there is a problem getting the driver name we will
- // assume it is not jcc.
- }
- }
-
- Connection getConnection() {
- // CHECK: should never be null
- return conn;
- }
-
- boolean getIsJCC()
- {
- return isJCC;
- }
-
- String getName() {
- return name;
- }
-
- Object addPreparedStatement(String name, PreparedStatement ps) {
- return prepStmts.put(name,ps);
- }
-
- Object addCursorStatement(String name, Statement s) {
- return cursorStmts.put(name, s);
- }
-
- Object addCursor(String name, ResultSet rs) {
- return cursors.put(name, rs);
- }
-
- Object addAsyncStatement(String name, AsyncStatement s) {
- return asyncStmts.put(name, s);
- }
-
- PreparedStatement getPreparedStatement(String name) {
- return (PreparedStatement) prepStmts.get(name);
- }
-
- Statement getCursorStatement(String name) {
- return (Statement)cursorStmts.get(name);
- }
-
- ResultSet getCursor(String name) {
- return (ResultSet)cursors.get(name);
- }
-
- AsyncStatement getAsyncStatement(String name) {
- return (AsyncStatement)asyncStmts.get(name);
- }
-
- boolean removePreparedStatement(String name) {
- return prepStmts.remove(name)!=null;
- }
-
- boolean removeCursorStatement(String name) {
- return cursorStmts.remove(name)!=null;
- }
-
- boolean removeCursor(String name) {
- return cursors.remove(name)!=null;
- }
-
- void doPrompt(boolean newStatement, LocalizedOutput out, boolean multiSessions) {
- // check if tag should be increased...
- if (multiSessions && singleSession) {
- singleSession = false;
-
- if (tag == null) tag = "("+name+")";
- else tag = tag.substring(0,tag.length()-1)+":"+name+")";
- }
-
- // check if tag should be reduced...
- if (!multiSessions && !singleSession) {
- singleSession = true;
-
- if (tag == null) {}
- else if (tag.length() == name.length()+2) tag = null;
- else tag = tag.substring(0,tag.length()-2-name.length())+")";
- }
-
- utilMain.doPrompt(newStatement, out, tag);
- }
-
- void close() throws SQLException {
-
- if (!conn.isClosed())
- {
- if (!conn.getAutoCommit() && name != null && ! name.startsWith("XA"))
- conn.rollback();
- conn.close();
- }
-
- prepStmts.clear(); // should we check & close them individually?
- cursorStmts.clear();
- cursors.clear();
- asyncStmts.clear();
-
- conn = null;
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Hashtable;
+
+/**
+ Session holds the objects local to a particular database session,
+ which starts with a connection and is all other JDBC
+ stuff used on that connection, along with some ij state
+ that is connection-based as well.
+
+ This is separated out to localize database objects and
+ also group objects by session.
+
+ @author ames
+ */
+class Session {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ static final String DEFAULT_NAME="CONNECTION";
+
+ boolean singleSession = true;
+ Connection conn = null;
+ String tag, name;
+ Hashtable prepStmts = new Hashtable();
+ Hashtable cursorStmts = new Hashtable();
+ Hashtable cursors = new Hashtable();
+ Hashtable asyncStmts = new Hashtable();
+ boolean isJCC= false; // Is this the IBM UNIVERSAL DRIVER.
+
+ Session(Connection newConn, String newTag, String newName) {
+ conn = newConn;
+ tag = newTag;
+ name = newName;
+
+ try
+ {
+ isJCC = conn.getMetaData().getDriverName().startsWith("IBM DB2 JDBC Universal Driver");
+ }
+ catch (SQLException se)
+ {
+ // if there is a problem getting the driver name we will
+ // assume it is not jcc.
+ }
+ }
+
+ Connection getConnection() {
+ // CHECK: should never be null
+ return conn;
+ }
+
+ boolean getIsJCC()
+ {
+ return isJCC;
+ }
+
+ String getName() {
+ return name;
+ }
+
+ Object addPreparedStatement(String name, PreparedStatement ps) {
+ return prepStmts.put(name,ps);
+ }
+
+ Object addCursorStatement(String name, Statement s) {
+ return cursorStmts.put(name, s);
+ }
+
+ Object addCursor(String name, ResultSet rs) {
+ return cursors.put(name, rs);
+ }
+
+ Object addAsyncStatement(String name, AsyncStatement s) {
+ return asyncStmts.put(name, s);
+ }
+
+ PreparedStatement getPreparedStatement(String name) {
+ return (PreparedStatement) prepStmts.get(name);
+ }
+
+ Statement getCursorStatement(String name) {
+ return (Statement)cursorStmts.get(name);
+ }
+
+ ResultSet getCursor(String name) {
+ return (ResultSet)cursors.get(name);
+ }
+
+ AsyncStatement getAsyncStatement(String name) {
+ return (AsyncStatement)asyncStmts.get(name);
+ }
+
+ boolean removePreparedStatement(String name) {
+ return prepStmts.remove(name)!=null;
+ }
+
+ boolean removeCursorStatement(String name) {
+ return cursorStmts.remove(name)!=null;
+ }
+
+ boolean removeCursor(String name) {
+ return cursors.remove(name)!=null;
+ }
+
+ void doPrompt(boolean newStatement, LocalizedOutput out, boolean multiSessions) {
+ // check if tag should be increased...
+ if (multiSessions && singleSession) {
+ singleSession = false;
+
+ if (tag == null) tag = "("+name+")";
+ else tag = tag.substring(0,tag.length()-1)+":"+name+")";
+ }
+
+ // check if tag should be reduced...
+ if (!multiSessions && !singleSession) {
+ singleSession = true;
+
+ if (tag == null) {}
+ else if (tag.length() == name.length()+2) tag = null;
+ else tag = tag.substring(0,tag.length()-2-name.length())+")";
+ }
+
+ utilMain.doPrompt(newStatement, out, tag);
+ }
+
+ void close() throws SQLException {
+
+ if (!conn.isClosed())
+ {
+ if (!conn.getAutoCommit() && name != null && ! name.startsWith("XA"))
+ conn.rollback();
+ conn.close();
+ }
+
+ prepStmts.clear(); // should we check & close them individually?
+ cursorStmts.clear();
+ cursors.clear();
+ asyncStmts.clear();
+
+ conn = null;
+ }
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/StatementFinder.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/StatementFinder.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/StatementFinder.java Fri Sep 24 10:33:20 2004
@@ -1,318 +1,318 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.io.IOException;
-import java.io.Reader;
-
-/**
- StatementGrabber looks through an input stream for
- the next JSQL statement. A statement is considered to
- be any tokens up to the next semicolon or EOF.
- <p>
- Semicolons inside comments, strings, and delimited identifiers
- are not considered to be statement terminators but to be
- part of those tokens.
- <p>
- The only comment form currently recognized is the SQL comment,
- which begins with "--" and ends at the next EOL.
- <p>
- Strings and delimited identifiers are permitted to contain
- newlines; the actual IJ or JSQL parsers will report errors when
- those cases occur.
- <p>
- There are no escaped characters, i.e. "\n" is considered to
- be two characters, '\' and 'n'.
-
- @author ames
- */
-
-public class StatementFinder {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- private Reader source;
- private StringBuffer statement = new StringBuffer();
- private int state;
- private boolean atEOF = false;
- private boolean peekEOF = false;
- private char peekChar;
- private boolean peeked = false;
-
- // state variables
- private static final int IN_STATEMENT = 0;
- private static final int IN_STRING = 1;
- private static final int IN_SQLCOMMENT = 2;
- private static final int END_OF_STATEMENT = 3;
- private static final int END_OF_INPUT = 4;
-
- // special state-changing characters
- private static final char MINUS = '-';
- private static final char SINGLEQUOTE = '\'';
- private static final char DOUBLEQUOTE = '\"';
- private static final char SEMICOLON = ';';
- private static final char NEWLINE = '\n';
- private static final char RETURN = '\r';
- private static final char SPACE = ' ';
- private static final char TAB = '\t';
- private static final char FORMFEED = '\f';
-
- /**
- The constructor does not assume the stream is data input
- or buffered, so it will wrap it appropriately.
-
- @param s the input stream for reading statements from.
- */
- public StatementFinder(Reader s) {
- source = s;
- }
-
- /**
- Reinit is used to redirect the finder to another stream.
- The previous stream should not have been in a PEEK state.
-
- @param s the input stream for reading statements from.
- */
- public void ReInit(Reader s) {
- try {
- source.close();
- } catch (IOException ioe) {
- // just be quiet if it is already gone
- }
- source = s;
- state = IN_STATEMENT;
- atEOF = false;
- peekEOF = false;
- peeked = false;
- }
-
- public void close() throws IOException {
- source.close();
- }
-
- /**
- get the next statement in the input stream. Returns it,
- dropping its closing semicolon if it has one. If there is
- no next statement, return a null.
-
- @return the next statement in the input stream.
- */
- public String nextStatement() {
- boolean haveSemi = false;
- char nextChar;
-
- // initialize fields for getting the next statement
- statement.setLength(0);
- if (state == END_OF_INPUT) return null;
-
- state = IN_STATEMENT;
-
- // skip leading whitespace
- nextChar = peekChar();
- if (peekEOF()) {
- state = END_OF_INPUT;
- return null;
- }
- if (whiteSpace(nextChar)) {
- while (whiteSpace(peekChar()) && ! peekEOF());
- if (peekEOF()) {
- state = END_OF_INPUT;
- return null;
- }
- }
-
- while (state != END_OF_STATEMENT && state != END_OF_INPUT) {
-
- // get the next character from the input
- nextChar = readChar();
- if (atEOF()) {
- state = END_OF_INPUT;
- break;
- }
-
- switch(nextChar) {
- case MINUS:
- readSingleLineComment(nextChar);
- break;
- case SINGLEQUOTE:
- case DOUBLEQUOTE:
- readString(nextChar);
- break;
- case SEMICOLON:
- haveSemi = true;
- state = END_OF_STATEMENT;
- break;
- default:
- // keep going, just a normal character
- break;
- }
- }
-
- if (haveSemi)
- statement.setLength(statement.length()-1);
- return statement.toString();
- }
-
- /**
- Determine if the given character is considered whitespace
-
- @param c the character to consider
- @return true if the character is whitespace
- */
- private boolean whiteSpace(char c) {
- return (c == SPACE ||
- c == TAB ||
- c == RETURN ||
- c == NEWLINE ||
- c == FORMFEED);
- }
-
- /**
- Advance the source stream to the end of a comment if it
- is on one, assuming the first character of
- a potential single line comment has been found.
- If it is not a comment, do not advance the stream.
- <p>
- The form of a single line comment is, in regexp, XX.*$,
- where XX is two instances of commentChar.
-
- @param commentChar the character whose duplication signifies
- the start of the comment.
- */
- private void readSingleLineComment(char commentChar) {
- char nextChar;
-
- nextChar = peekChar();
- // if next char is EOF, we are done.
- if (peekEOF()) return;
-
- // if nextChar is not a minus, it was just a normal minus,
- // nothing special to do
- if (nextChar != commentChar) return;
-
- // we are really in a comment
- readChar(); // grab the minus for real.
-
- state = IN_SQLCOMMENT;
- do {
- nextChar = peekChar();
- if (peekEOF()) {
- // let the caller process the EOF, don't read it
- state = IN_STATEMENT;
- return;
- }
- switch (nextChar) {
- case NEWLINE:
- case RETURN:
- readChar(); // okay to process the character
- state = IN_STATEMENT;
- return;
- default:
- readChar(); // process the character, still in comment
- break;
- }
- } while (state == IN_SQLCOMMENT); // could be while true...
- }
-
- /**
- Advance the stream to the end of the string.
- Assumes the opening delimiter of the string has been read.
- This handles the SQL ability to put the delimiter within
- the string by doubling it, by reading those as two strings
- sitting next to one another. I.e, 'Mary''s lamb' is read
- by this class as two strings, 'Mary' and 's lamb'.
- <p>
- The delimiter of the string is expected to be repeated at
- its other end. If the other flavor of delimiter occurs within
- the string, it is just a normal character within it.
- <p>
- All characters except the delimiter are permitted within the
- string. If EOF is hit before the closing delimiter is found,
- the end of the string is assumed. Parsers using this parser
- will detect the error in that case and return appropriate messages.
-
- @param stringDelimiter the starting and ending character
- for the string being read.
- */
- private void readString(char stringDelimiter) {
- state = IN_STRING;
- do {
- char nextChar = readChar();
-
- if (atEOF()) {
- state = END_OF_INPUT;
- return;
- }
-
- if (nextChar == stringDelimiter) {
- // we've reached the end of the string
- state = IN_STATEMENT;
- return;
- }
-
- // still in string
- } while (state == IN_STRING); // could be while true...
- }
-
- private boolean atEOF() {
- return atEOF;
- }
-
- private boolean peekEOF() {
- return peekEOF;
- }
-
- /**
- return the next character in the source stream and
- append it to the statement buffer.
-
- @return the next character in the source stream.
- */
- private char readChar() {
- if (!peeked) peekChar();
-
- peeked = false;
- atEOF = peekEOF;
-
- if (!atEOF) statement.append(peekChar);
-
- return peekChar;
- }
-
- /**
- return the next character in the source stream, without
- advancing.
-
- @return the next character in the source stream.
- */
- private char peekChar() {
- peeked = true;
- char c = '\00';
-
- try {
- int cInt;
-
- // REMIND: this is assuming a flat ascii source file.
- // will need to beef it up at some future point to
- // understand whether the stream is ascii or something else.
- cInt = source.read();
- peekEOF = (cInt == -1);
- if (!peekEOF) c = (char)cInt;
- } catch (IOException ie) {
- throw ijException.iOException(ie);
- }
-
- peekChar = c;
- return c;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ StatementGrabber looks through an input stream for
+ the next JSQL statement. A statement is considered to
+ be any tokens up to the next semicolon or EOF.
+ <p>
+ Semicolons inside comments, strings, and delimited identifiers
+ are not considered to be statement terminators but to be
+ part of those tokens.
+ <p>
+ The only comment form currently recognized is the SQL comment,
+ which begins with "--" and ends at the next EOL.
+ <p>
+ Strings and delimited identifiers are permitted to contain
+ newlines; the actual IJ or JSQL parsers will report errors when
+ those cases occur.
+ <p>
+ There are no escaped characters, i.e. "\n" is considered to
+ be two characters, '\' and 'n'.
+
+ @author ames
+ */
+
+public class StatementFinder {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ private Reader source;
+ private StringBuffer statement = new StringBuffer();
+ private int state;
+ private boolean atEOF = false;
+ private boolean peekEOF = false;
+ private char peekChar;
+ private boolean peeked = false;
+
+ // state variables
+ private static final int IN_STATEMENT = 0;
+ private static final int IN_STRING = 1;
+ private static final int IN_SQLCOMMENT = 2;
+ private static final int END_OF_STATEMENT = 3;
+ private static final int END_OF_INPUT = 4;
+
+ // special state-changing characters
+ private static final char MINUS = '-';
+ private static final char SINGLEQUOTE = '\'';
+ private static final char DOUBLEQUOTE = '\"';
+ private static final char SEMICOLON = ';';
+ private static final char NEWLINE = '\n';
+ private static final char RETURN = '\r';
+ private static final char SPACE = ' ';
+ private static final char TAB = '\t';
+ private static final char FORMFEED = '\f';
+
+ /**
+ The constructor does not assume the stream is data input
+ or buffered, so it will wrap it appropriately.
+
+ @param s the input stream for reading statements from.
+ */
+ public StatementFinder(Reader s) {
+ source = s;
+ }
+
+ /**
+ Reinit is used to redirect the finder to another stream.
+ The previous stream should not have been in a PEEK state.
+
+ @param s the input stream for reading statements from.
+ */
+ public void ReInit(Reader s) {
+ try {
+ source.close();
+ } catch (IOException ioe) {
+ // just be quiet if it is already gone
+ }
+ source = s;
+ state = IN_STATEMENT;
+ atEOF = false;
+ peekEOF = false;
+ peeked = false;
+ }
+
+ public void close() throws IOException {
+ source.close();
+ }
+
+ /**
+ get the next statement in the input stream. Returns it,
+ dropping its closing semicolon if it has one. If there is
+ no next statement, return a null.
+
+ @return the next statement in the input stream.
+ */
+ public String nextStatement() {
+ boolean haveSemi = false;
+ char nextChar;
+
+ // initialize fields for getting the next statement
+ statement.setLength(0);
+ if (state == END_OF_INPUT) return null;
+
+ state = IN_STATEMENT;
+
+ // skip leading whitespace
+ nextChar = peekChar();
+ if (peekEOF()) {
+ state = END_OF_INPUT;
+ return null;
+ }
+ if (whiteSpace(nextChar)) {
+ while (whiteSpace(peekChar()) && ! peekEOF());
+ if (peekEOF()) {
+ state = END_OF_INPUT;
+ return null;
+ }
+ }
+
+ while (state != END_OF_STATEMENT && state != END_OF_INPUT) {
+
+ // get the next character from the input
+ nextChar = readChar();
+ if (atEOF()) {
+ state = END_OF_INPUT;
+ break;
+ }
+
+ switch(nextChar) {
+ case MINUS:
+ readSingleLineComment(nextChar);
+ break;
+ case SINGLEQUOTE:
+ case DOUBLEQUOTE:
+ readString(nextChar);
+ break;
+ case SEMICOLON:
+ haveSemi = true;
+ state = END_OF_STATEMENT;
+ break;
+ default:
+ // keep going, just a normal character
+ break;
+ }
+ }
+
+ if (haveSemi)
+ statement.setLength(statement.length()-1);
+ return statement.toString();
+ }
+
+ /**
+ Determine if the given character is considered whitespace
+
+ @param c the character to consider
+ @return true if the character is whitespace
+ */
+ private boolean whiteSpace(char c) {
+ return (c == SPACE ||
+ c == TAB ||
+ c == RETURN ||
+ c == NEWLINE ||
+ c == FORMFEED);
+ }
+
+ /**
+ Advance the source stream to the end of a comment if it
+ is on one, assuming the first character of
+ a potential single line comment has been found.
+ If it is not a comment, do not advance the stream.
+ <p>
+ The form of a single line comment is, in regexp, XX.*$,
+ where XX is two instances of commentChar.
+
+ @param commentChar the character whose duplication signifies
+ the start of the comment.
+ */
+ private void readSingleLineComment(char commentChar) {
+ char nextChar;
+
+ nextChar = peekChar();
+ // if next char is EOF, we are done.
+ if (peekEOF()) return;
+
+ // if nextChar is not a minus, it was just a normal minus,
+ // nothing special to do
+ if (nextChar != commentChar) return;
+
+ // we are really in a comment
+ readChar(); // grab the minus for real.
+
+ state = IN_SQLCOMMENT;
+ do {
+ nextChar = peekChar();
+ if (peekEOF()) {
+ // let the caller process the EOF, don't read it
+ state = IN_STATEMENT;
+ return;
+ }
+ switch (nextChar) {
+ case NEWLINE:
+ case RETURN:
+ readChar(); // okay to process the character
+ state = IN_STATEMENT;
+ return;
+ default:
+ readChar(); // process the character, still in comment
+ break;
+ }
+ } while (state == IN_SQLCOMMENT); // could be while true...
+ }
+
+ /**
+ Advance the stream to the end of the string.
+ Assumes the opening delimiter of the string has been read.
+ This handles the SQL ability to put the delimiter within
+ the string by doubling it, by reading those as two strings
+ sitting next to one another. I.e, 'Mary''s lamb' is read
+ by this class as two strings, 'Mary' and 's lamb'.
+ <p>
+ The delimiter of the string is expected to be repeated at
+ its other end. If the other flavor of delimiter occurs within
+ the string, it is just a normal character within it.
+ <p>
+ All characters except the delimiter are permitted within the
+ string. If EOF is hit before the closing delimiter is found,
+ the end of the string is assumed. Parsers using this parser
+ will detect the error in that case and return appropriate messages.
+
+ @param stringDelimiter the starting and ending character
+ for the string being read.
+ */
+ private void readString(char stringDelimiter) {
+ state = IN_STRING;
+ do {
+ char nextChar = readChar();
+
+ if (atEOF()) {
+ state = END_OF_INPUT;
+ return;
+ }
+
+ if (nextChar == stringDelimiter) {
+ // we've reached the end of the string
+ state = IN_STATEMENT;
+ return;
+ }
+
+ // still in string
+ } while (state == IN_STRING); // could be while true...
+ }
+
+ private boolean atEOF() {
+ return atEOF;
+ }
+
+ private boolean peekEOF() {
+ return peekEOF;
+ }
+
+ /**
+ return the next character in the source stream and
+ append it to the statement buffer.
+
+ @return the next character in the source stream.
+ */
+ private char readChar() {
+ if (!peeked) peekChar();
+
+ peeked = false;
+ atEOF = peekEOF;
+
+ if (!atEOF) statement.append(peekChar);
+
+ return peekChar;
+ }
+
+ /**
+ return the next character in the source stream, without
+ advancing.
+
+ @return the next character in the source stream.
+ */
+ private char peekChar() {
+ peeked = true;
+ char c = '\00';
+
+ try {
+ int cInt;
+
+ // REMIND: this is assuming a flat ascii source file.
+ // will need to beef it up at some future point to
+ // understand whether the stream is ascii or something else.
+ cInt = source.read();
+ peekEOF = (cInt == -1);
+ if (!peekEOF) c = (char)cInt;
+ } catch (IOException ie) {
+ throw ijException.iOException(ie);
+ }
+
+ peekChar = c;
+ return c;
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/UCode_CharStream.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/UCode_CharStream.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/UCode_CharStream.java Fri Sep 24 10:33:20 2004
@@ -1,410 +1,410 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-/* Generated By:JavaCC: Do not edit this line. UCode_CharStream.java Version 0.7pre6 */
-package org.apache.derby.impl.tools.ij;
-
-/**
- * An implementation of interface CharStream, where the stream is assumed to
- * contain only Unicode characters.
- */
-
-public final class UCode_CharStream implements CharStream
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
- public static final boolean staticFlag = false;
- public int bufpos = -1;
- int bufsize;
- int available;
- int tokenBegin;
- private int bufline[];
- private int bufcolumn[];
-
- private int column = 0;
- private int line = 1;
-
- private boolean prevCharIsCR = false;
- private boolean prevCharIsLF = false;
-
- private java.io.Reader inputStream;
-
- private char[] nextCharBuf;
- private char[] buffer;
- private int maxNextCharInd = 0;
- private int nextCharInd = -1;
-
- private final void ExpandBuff(boolean wrapAround)
- {
- char[] newbuffer = new char[bufsize + 2048];
- int newbufline[] = new int[bufsize + 2048];
- int newbufcolumn[] = new int[bufsize + 2048];
-
- try
- {
- if (wrapAround)
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- System.arraycopy(buffer, 0, newbuffer,
- bufsize - tokenBegin, bufpos);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
- bufcolumn = newbufcolumn;
-
- bufpos += (bufsize - tokenBegin);
- }
- else
- {
- System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
- buffer = newbuffer;
-
- System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
- bufline = newbufline;
-
- System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
- bufcolumn = newbufcolumn;
-
- bufpos -= tokenBegin;
- }
- }
- catch (Throwable t)
- {
- throw new Error(t.getMessage());
- }
-
- available = (bufsize += 2048);
- tokenBegin = 0;
- }
-
- private final void FillBuff() throws java.io.IOException
- {
- if (maxNextCharInd == 4096)
- maxNextCharInd = nextCharInd = 0;
-
- int i;
- try {
- if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
- 4096 - maxNextCharInd)) == -1)
- {
- inputStream.close();
- throw new java.io.IOException();
- }
- else
- maxNextCharInd += i;
- return;
- }
- catch(java.io.IOException e) {
- if (bufpos != 0)
- {
- --bufpos;
- backup(0);
- }
- else
- {
- bufline[bufpos] = line;
- bufcolumn[bufpos] = column;
- }
- if (tokenBegin == -1)
- tokenBegin = bufpos;
- throw e;
- }
- }
-
- private final char ReadChar() throws java.io.IOException
- {
- if (++nextCharInd >= maxNextCharInd)
- FillBuff();
-
- return nextCharBuf[nextCharInd];
- }
-
- public char BeginToken() throws java.io.IOException
- {
- tokenBegin = -1;
- char c = readChar();
- tokenBegin = bufpos;
-
- return c;
- }
-
- private final void UpdateLineColumn(char c)
- {
- column++;
-
- if (prevCharIsLF)
- {
- prevCharIsLF = false;
- line += (column = 1);
- }
- else if (prevCharIsCR)
- {
- prevCharIsCR = false;
- if (c == '\n')
- {
- prevCharIsLF = true;
- }
- else
- line += (column = 1);
- }
-
- switch (c)
- {
- case '\r' :
- prevCharIsCR = true;
- break;
- case '\n' :
- prevCharIsLF = true;
- break;
- case '\t' :
- column--;
- column += (8 - (column & 07));
- break;
- default :
- break;
- }
- }
-
- private int inBuf = 0;
- public final char readChar() throws java.io.IOException
- {
- if (inBuf > 0)
- {
- --inBuf;
- return (char)buffer[(bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos];
- }
-
- bufpos++;
- char c = ReadChar();
- UpdateLineColumn(c);
-
- if (bufpos == available)
- {
- if (available == bufsize)
- {
- if (tokenBegin > 2048)
- {
- bufpos = 0;
- available = tokenBegin;
- }
- else if (tokenBegin < 0)
- bufpos = 0;
- else
- ExpandBuff(false);
- }
- else if (available > tokenBegin)
- available = bufsize;
- else if ((tokenBegin - available) < 2048)
- ExpandBuff(true);
- else
- available = tokenBegin;
- }
-
- return (buffer[bufpos] = c);
- }
-
- /**
- * @deprecated
- * @see #getEndColumn
- */
-
- public final int getColumn() {
- return bufcolumn[bufpos];
- }
-
- /**
- * @deprecated
- * @see #getEndLine
- */
-
- public final int getLine() {
- return bufline[bufpos];
- }
-
- public final int getEndColumn() {
- return bufcolumn[bufpos];
- }
-
- public final int getEndLine() {
- return bufline[bufpos];
- }
-
- public final int getBeginColumn() {
- return bufcolumn[tokenBegin];
- }
-
- public final int getBeginLine() {
- return bufline[tokenBegin];
- }
-
- public final void backup(int amount) {
-
- inBuf += amount;
- if ((bufpos -= amount) < 0)
- bufpos += bufsize;
- }
-
- public UCode_CharStream(java.io.Reader dstream,
- int startline, int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- nextCharBuf = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
-
-
- public UCode_CharStream(java.io.Reader dstream,
- int startline, int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public void ReInit(java.io.Reader dstream,
- int startline, int startcolumn, int buffersize)
- {
- inputStream = dstream;
- line = startline;
- column = startcolumn - 1;
-
- if (buffer == null || buffersize != buffer.length)
- {
- available = bufsize = buffersize;
- buffer = new char[buffersize];
- nextCharBuf = new char[buffersize];
- bufline = new int[buffersize];
- bufcolumn = new int[buffersize];
- }
- tokenBegin = inBuf = maxNextCharInd = 0;
- nextCharInd = bufpos = -1;
- }
-
- public void ReInit(java.io.Reader dstream,
- int startline, int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
- public UCode_CharStream(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
- }
-
- public UCode_CharStream(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- this(dstream, startline, startcolumn, 4096);
- }
-
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn, int buffersize)
- {
- ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
- }
- public void ReInit(java.io.InputStream dstream, int startline,
- int startcolumn)
- {
- ReInit(dstream, startline, startcolumn, 4096);
- }
-
- public final String GetImage()
- {
- if (bufpos >= tokenBegin)
- return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
- else
- return new String(buffer, tokenBegin, bufsize - tokenBegin) +
- new String(buffer, 0, bufpos + 1);
- }
-
- public final char[] GetSuffix(int len)
- {
- char[] ret = new char[len];
-
- if ((bufpos + 1) >= len)
- System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
- else
- {
- System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
- len - bufpos - 1);
- System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
- }
-
- return ret;
- }
-
- public void Done()
- {
- nextCharBuf = null;
- buffer = null;
- bufline = null;
- bufcolumn = null;
- }
-
- /**
- * Method to adjust line and column numbers for the start of a token.<BR>
- */
- public void adjustBeginLineColumn(int newLine, int newCol)
- {
- int start = tokenBegin;
- int len;
-
- if (bufpos >= tokenBegin)
- {
- len = bufpos - tokenBegin + inBuf + 1;
- }
- else
- {
- len = bufsize - tokenBegin + bufpos + 1 + inBuf;
- }
-
- int i = 0, j = 0, k = 0;
- int nextColDiff = 0, columnDiff = 0;
-
- while (i < len &&
- bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
- {
- bufline[j] = newLine;
- nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
- bufcolumn[j] = newCol + columnDiff;
- columnDiff = nextColDiff;
- i++;
- }
-
- if (i < len)
- {
- bufline[j] = newLine++;
- bufcolumn[j] = newCol + columnDiff;
-
- while (i++ < len)
- {
- if (bufline[j = start % bufsize] != bufline[++start % bufsize])
- bufline[j] = newLine++;
- else
- bufline[j] = newLine;
- }
- }
-
- line = bufline[j];
- column = bufcolumn[j];
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+/* Generated By:JavaCC: Do not edit this line. UCode_CharStream.java Version 0.7pre6 */
+package org.apache.derby.impl.tools.ij;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only Unicode characters.
+ */
+
+public final class UCode_CharStream implements CharStream
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+ public static final boolean staticFlag = false;
+ public int bufpos = -1;
+ int bufsize;
+ int available;
+ int tokenBegin;
+ private int bufline[];
+ private int bufcolumn[];
+
+ private int column = 0;
+ private int line = 1;
+
+ private boolean prevCharIsCR = false;
+ private boolean prevCharIsLF = false;
+
+ private java.io.Reader inputStream;
+
+ private char[] nextCharBuf;
+ private char[] buffer;
+ private int maxNextCharInd = 0;
+ private int nextCharInd = -1;
+
+ private final void ExpandBuff(boolean wrapAround)
+ {
+ char[] newbuffer = new char[bufsize + 2048];
+ int newbufline[] = new int[bufsize + 2048];
+ int newbufcolumn[] = new int[bufsize + 2048];
+
+ try
+ {
+ if (wrapAround)
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ System.arraycopy(buffer, 0, newbuffer,
+ bufsize - tokenBegin, bufpos);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+ bufcolumn = newbufcolumn;
+
+ bufpos += (bufsize - tokenBegin);
+ }
+ else
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ bufcolumn = newbufcolumn;
+
+ bufpos -= tokenBegin;
+ }
+ }
+ catch (Throwable t)
+ {
+ throw new Error(t.getMessage());
+ }
+
+ available = (bufsize += 2048);
+ tokenBegin = 0;
+ }
+
+ private final void FillBuff() throws java.io.IOException
+ {
+ if (maxNextCharInd == 4096)
+ maxNextCharInd = nextCharInd = 0;
+
+ int i;
+ try {
+ if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
+ 4096 - maxNextCharInd)) == -1)
+ {
+ inputStream.close();
+ throw new java.io.IOException();
+ }
+ else
+ maxNextCharInd += i;
+ return;
+ }
+ catch(java.io.IOException e) {
+ if (bufpos != 0)
+ {
+ --bufpos;
+ backup(0);
+ }
+ else
+ {
+ bufline[bufpos] = line;
+ bufcolumn[bufpos] = column;
+ }
+ if (tokenBegin == -1)
+ tokenBegin = bufpos;
+ throw e;
+ }
+ }
+
+ private final char ReadChar() throws java.io.IOException
+ {
+ if (++nextCharInd >= maxNextCharInd)
+ FillBuff();
+
+ return nextCharBuf[nextCharInd];
+ }
+
+ public char BeginToken() throws java.io.IOException
+ {
+ tokenBegin = -1;
+ char c = readChar();
+ tokenBegin = bufpos;
+
+ return c;
+ }
+
+ private final void UpdateLineColumn(char c)
+ {
+ column++;
+
+ if (prevCharIsLF)
+ {
+ prevCharIsLF = false;
+ line += (column = 1);
+ }
+ else if (prevCharIsCR)
+ {
+ prevCharIsCR = false;
+ if (c == '\n')
+ {
+ prevCharIsLF = true;
+ }
+ else
+ line += (column = 1);
+ }
+
+ switch (c)
+ {
+ case '\r' :
+ prevCharIsCR = true;
+ break;
+ case '\n' :
+ prevCharIsLF = true;
+ break;
+ case '\t' :
+ column--;
+ column += (8 - (column & 07));
+ break;
+ default :
+ break;
+ }
+ }
+
+ private int inBuf = 0;
+ public final char readChar() throws java.io.IOException
+ {
+ if (inBuf > 0)
+ {
+ --inBuf;
+ return (char)buffer[(bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos];
+ }
+
+ bufpos++;
+ char c = ReadChar();
+ UpdateLineColumn(c);
+
+ if (bufpos == available)
+ {
+ if (available == bufsize)
+ {
+ if (tokenBegin > 2048)
+ {
+ bufpos = 0;
+ available = tokenBegin;
+ }
+ else if (tokenBegin < 0)
+ bufpos = 0;
+ else
+ ExpandBuff(false);
+ }
+ else if (available > tokenBegin)
+ available = bufsize;
+ else if ((tokenBegin - available) < 2048)
+ ExpandBuff(true);
+ else
+ available = tokenBegin;
+ }
+
+ return (buffer[bufpos] = c);
+ }
+
+ /**
+ * @deprecated
+ * @see #getEndColumn
+ */
+
+ public final int getColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ /**
+ * @deprecated
+ * @see #getEndLine
+ */
+
+ public final int getLine() {
+ return bufline[bufpos];
+ }
+
+ public final int getEndColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ public final int getEndLine() {
+ return bufline[bufpos];
+ }
+
+ public final int getBeginColumn() {
+ return bufcolumn[tokenBegin];
+ }
+
+ public final int getBeginLine() {
+ return bufline[tokenBegin];
+ }
+
+ public final void backup(int amount) {
+
+ inBuf += amount;
+ if ((bufpos -= amount) < 0)
+ bufpos += bufsize;
+ }
+
+ public UCode_CharStream(java.io.Reader dstream,
+ int startline, int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ nextCharBuf = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+
+
+ public UCode_CharStream(java.io.Reader dstream,
+ int startline, int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ public void ReInit(java.io.Reader dstream,
+ int startline, int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ if (buffer == null || buffersize != buffer.length)
+ {
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ nextCharBuf = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+ tokenBegin = inBuf = maxNextCharInd = 0;
+ nextCharInd = bufpos = -1;
+ }
+
+ public void ReInit(java.io.Reader dstream,
+ int startline, int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+ public UCode_CharStream(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+ }
+
+ public UCode_CharStream(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+ }
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+
+ public final String GetImage()
+ {
+ if (bufpos >= tokenBegin)
+ return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+ else
+ return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+ new String(buffer, 0, bufpos + 1);
+ }
+
+ public final char[] GetSuffix(int len)
+ {
+ char[] ret = new char[len];
+
+ if ((bufpos + 1) >= len)
+ System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+ else
+ {
+ System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+ len - bufpos - 1);
+ System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+ }
+
+ return ret;
+ }
+
+ public void Done()
+ {
+ nextCharBuf = null;
+ buffer = null;
+ bufline = null;
+ bufcolumn = null;
+ }
+
+ /**
+ * Method to adjust line and column numbers for the start of a token.<BR>
+ */
+ public void adjustBeginLineColumn(int newLine, int newCol)
+ {
+ int start = tokenBegin;
+ int len;
+
+ if (bufpos >= tokenBegin)
+ {
+ len = bufpos - tokenBegin + inBuf + 1;
+ }
+ else
+ {
+ len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+ }
+
+ int i = 0, j = 0, k = 0;
+ int nextColDiff = 0, columnDiff = 0;
+
+ while (i < len &&
+ bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+ {
+ bufline[j] = newLine;
+ nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+ bufcolumn[j] = newCol + columnDiff;
+ columnDiff = nextColDiff;
+ i++;
+ }
+
+ if (i < len)
+ {
+ bufline[j] = newLine++;
+ bufcolumn[j] = newCol + columnDiff;
+
+ while (i++ < len)
+ {
+ if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+ bufline[j] = newLine++;
+ else
+ bufline[j] = newLine;
+ }
+ }
+
+ line = bufline[j];
+ column = bufcolumn[j];
+ }
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijConnectionResult.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijConnectionResult.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijConnectionResult.java Fri Sep 24 10:33:20 2004
@@ -1,38 +1,38 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-
-/**
- * @author ames
- */
-class ijConnectionResult extends ijResultImpl {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- Connection conn;
-
- ijConnectionResult(Connection c) {
- conn = c;
- }
-
- public boolean isConnection() { return true; }
-
- public Connection getConnection() { return conn; }
-
- public SQLWarning getSQLWarnings() throws SQLException { return conn.getWarnings(); }
- public void clearSQLWarnings() throws SQLException { conn.clearWarnings(); }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+
+/**
+ * @author ames
+ */
+class ijConnectionResult extends ijResultImpl {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ Connection conn;
+
+ ijConnectionResult(Connection c) {
+ conn = c;
+ }
+
+ public boolean isConnection() { return true; }
+
+ public Connection getConnection() { return conn; }
+
+ public SQLWarning getSQLWarnings() throws SQLException { return conn.getWarnings(); }
+ public void clearSQLWarnings() throws SQLException { conn.clearWarnings(); }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijException.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijException.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijException.java Fri Sep 24 10:33:20 2004
@@ -1,148 +1,148 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-import java.io.IOException;
-
-/**
- ijException is used to get messages from the ij parser to
- the main ij loop. Because this is not under the protocol/impl
- umbrella, it does not have available to it the message service.
- At this time, all messages are hard-coded in this file. A more
- serviceable solution may need to be found.
-
- @author ames.
- */
-
-public class ijException extends RuntimeException {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- private final static String IllegalStatementName="IJ_IllegalStatementName";
- private final static String NotYetImplemented="IJ_NotYetImpl";
- private final static String AlreadyHaveConnectionNamed = "IJ_AlreHaveACon";
- private final static String BangException = "IJ_ExceRunnComm";
- private final static String ConnectionGetWarningsFailed = "IJ_UnabToGetWar";
- private final static String ClassNotFoundForProtocol = "IJ_CoulNotLocaC";
- private final static String ClassNotFound = "IJ_CoulNotLocaC_5";
- private final static String DisconnectFailed = "IJ_FailToDisc";
- private final static String DriverNotClassName = "IJ_DrivNotClasN";
- private final static String FileNotFound = "IJ_FileNotFoun";
- private final static String ForwardOnlyCursor = "IJ_IsNotAlloOnA";
- private final static String GetConnectionFailed = "IJ_GetcCallFail";
- private final static String IOException = "IJ_Ioex";
- private final static String NeedToDisconnect = "IJ_NeedToDiscFi";
- private final static String NoSuchAsyncStatement = "IJ_NoAsynStatEx";
- private final static String NoSuchConnection = "IJ_NoConnExisWi";
- private final static String NoSuchProtocol = "IJ_NoProtExisWi";
- private final static String NotJDBC20 = "IJ_IsOnlySuppIn";
- private final static String NoUsingResults = "IJ_UsinClauHadN";
- private final static String ObjectWasNull = "IJ_UnabToEsta";
- private final static String ResultSetGetWarningsFailed = "IJ_UnabToGetWar_19";
- private final static String ResourceNotFound = "IJ_ResoNotFoun";
- private final static String ScrollCursorsNotSupported = "IJ_ScroCursAre1";
- private final static String HoldCursorsNotSupported = "IJ_HoldCursAre4";
- private final static String StatementGetWarningsFailed = "IJ_UnabToGetWar_22";
- private final static String WaitInterrupted = "IJ_WaitForStatI";
- private final static String ZeroInvalidForAbsolute = "IJ_0IsAnInvaVal";
-
- public ijException(String message) {
- super(message);
- }
-
- static ijException notYetImplemented() {
- return new ijException(LocalizedResource.getMessage(NotYetImplemented));
- }
-
- static ijException illegalStatementName(String n) {
- return new ijException(LocalizedResource.getMessage(IllegalStatementName, n));
- }
- static ijException alreadyHaveConnectionNamed(String n) {
- return new ijException(LocalizedResource.getMessage(AlreadyHaveConnectionNamed, n));
- }
- static ijException bangException(Throwable t) {
- return new ijException(LocalizedResource.getMessage(BangException, t.toString()));
- }
- static ijException classNotFoundForProtocol(String p) {
- return new ijException(LocalizedResource.getMessage(ClassNotFoundForProtocol, p));
- }
- static ijException classNotFound(String c) {
- return new ijException(LocalizedResource.getMessage(ClassNotFound, c));
- }
- static ijException connectionGetWarningsFailed() {
- return new ijException(LocalizedResource.getMessage(ConnectionGetWarningsFailed));
- }
- static ijException disconnectFailed() {
- return new ijException(LocalizedResource.getMessage(DisconnectFailed));
- }
- static ijException driverNotClassName(String c) {
- return new ijException(LocalizedResource.getMessage(DriverNotClassName, c));
- }
- static ijException fileNotFound() {
- return new ijException(LocalizedResource.getMessage(FileNotFound));
- }
- static public ijException forwardOnlyCursor(String operation) {
- return new ijException(LocalizedResource.getMessage(ForwardOnlyCursor, operation));
- }
- static ijException resourceNotFound() {
- return new ijException(LocalizedResource.getMessage(ResourceNotFound));
- }
- static ijException getConnectionFailed() {
- return new ijException(LocalizedResource.getMessage(GetConnectionFailed));
- }
- static ijException iOException(IOException t) {
- return new ijException(LocalizedResource.getMessage(IOException, t.getMessage()));
- }
- static ijException needToDisconnect() {
- return new ijException(LocalizedResource.getMessage(NeedToDisconnect));
- }
- static ijException noSuchAsyncStatement(String c) {
- return new ijException(LocalizedResource.getMessage(NoSuchAsyncStatement, c));
- }
- static ijException noSuchConnection(String c) {
- return new ijException(LocalizedResource.getMessage(NoSuchConnection, c));
- }
- static ijException noSuchProtocol(String c) {
- return new ijException(LocalizedResource.getMessage(NoSuchProtocol, c));
- }
- static public ijException notJDBC20(String operation) {
- return new ijException(LocalizedResource.getMessage(NotJDBC20, operation));
- }
- static ijException noUsingResults() {
- return new ijException(LocalizedResource.getMessage(NoUsingResults));
- }
- static public ijException objectWasNull(String objectName) {
- return new ijException(LocalizedResource.getMessage(ObjectWasNull, objectName));
- }
- static ijException resultSetGetWarningsFailed() {
- return new ijException(LocalizedResource.getMessage(ResultSetGetWarningsFailed));
- }
- static ijException scrollCursorsNotSupported() {
- return new ijException(LocalizedResource.getMessage(ScrollCursorsNotSupported));
- }
- //IJImpl20.utilMain can't throw exception for holdable cursors if
- //following not declared public
- public static ijException holdCursorsNotSupported() {
- return new ijException(LocalizedResource.getMessage(HoldCursorsNotSupported));
- }
- static ijException statementGetWarningsFailed() {
- return new ijException(LocalizedResource.getMessage(StatementGetWarningsFailed));
- }
- static ijException waitInterrupted(Throwable t) {
- return new ijException(LocalizedResource.getMessage(WaitInterrupted, t.toString()));
- }
- public static ijException zeroInvalidForAbsolute() {
- return new ijException(LocalizedResource.getMessage(ZeroInvalidForAbsolute));
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+import java.io.IOException;
+
+/**
+ ijException is used to get messages from the ij parser to
+ the main ij loop. Because this is not under the protocol/impl
+ umbrella, it does not have available to it the message service.
+ At this time, all messages are hard-coded in this file. A more
+ serviceable solution may need to be found.
+
+ @author ames.
+ */
+
+public class ijException extends RuntimeException {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ private final static String IllegalStatementName="IJ_IllegalStatementName";
+ private final static String NotYetImplemented="IJ_NotYetImpl";
+ private final static String AlreadyHaveConnectionNamed = "IJ_AlreHaveACon";
+ private final static String BangException = "IJ_ExceRunnComm";
+ private final static String ConnectionGetWarningsFailed = "IJ_UnabToGetWar";
+ private final static String ClassNotFoundForProtocol = "IJ_CoulNotLocaC";
+ private final static String ClassNotFound = "IJ_CoulNotLocaC_5";
+ private final static String DisconnectFailed = "IJ_FailToDisc";
+ private final static String DriverNotClassName = "IJ_DrivNotClasN";
+ private final static String FileNotFound = "IJ_FileNotFoun";
+ private final static String ForwardOnlyCursor = "IJ_IsNotAlloOnA";
+ private final static String GetConnectionFailed = "IJ_GetcCallFail";
+ private final static String IOException = "IJ_Ioex";
+ private final static String NeedToDisconnect = "IJ_NeedToDiscFi";
+ private final static String NoSuchAsyncStatement = "IJ_NoAsynStatEx";
+ private final static String NoSuchConnection = "IJ_NoConnExisWi";
+ private final static String NoSuchProtocol = "IJ_NoProtExisWi";
+ private final static String NotJDBC20 = "IJ_IsOnlySuppIn";
+ private final static String NoUsingResults = "IJ_UsinClauHadN";
+ private final static String ObjectWasNull = "IJ_UnabToEsta";
+ private final static String ResultSetGetWarningsFailed = "IJ_UnabToGetWar_19";
+ private final static String ResourceNotFound = "IJ_ResoNotFoun";
+ private final static String ScrollCursorsNotSupported = "IJ_ScroCursAre1";
+ private final static String HoldCursorsNotSupported = "IJ_HoldCursAre4";
+ private final static String StatementGetWarningsFailed = "IJ_UnabToGetWar_22";
+ private final static String WaitInterrupted = "IJ_WaitForStatI";
+ private final static String ZeroInvalidForAbsolute = "IJ_0IsAnInvaVal";
+
+ public ijException(String message) {
+ super(message);
+ }
+
+ static ijException notYetImplemented() {
+ return new ijException(LocalizedResource.getMessage(NotYetImplemented));
+ }
+
+ static ijException illegalStatementName(String n) {
+ return new ijException(LocalizedResource.getMessage(IllegalStatementName, n));
+ }
+ static ijException alreadyHaveConnectionNamed(String n) {
+ return new ijException(LocalizedResource.getMessage(AlreadyHaveConnectionNamed, n));
+ }
+ static ijException bangException(Throwable t) {
+ return new ijException(LocalizedResource.getMessage(BangException, t.toString()));
+ }
+ static ijException classNotFoundForProtocol(String p) {
+ return new ijException(LocalizedResource.getMessage(ClassNotFoundForProtocol, p));
+ }
+ static ijException classNotFound(String c) {
+ return new ijException(LocalizedResource.getMessage(ClassNotFound, c));
+ }
+ static ijException connectionGetWarningsFailed() {
+ return new ijException(LocalizedResource.getMessage(ConnectionGetWarningsFailed));
+ }
+ static ijException disconnectFailed() {
+ return new ijException(LocalizedResource.getMessage(DisconnectFailed));
+ }
+ static ijException driverNotClassName(String c) {
+ return new ijException(LocalizedResource.getMessage(DriverNotClassName, c));
+ }
+ static ijException fileNotFound() {
+ return new ijException(LocalizedResource.getMessage(FileNotFound));
+ }
+ static public ijException forwardOnlyCursor(String operation) {
+ return new ijException(LocalizedResource.getMessage(ForwardOnlyCursor, operation));
+ }
+ static ijException resourceNotFound() {
+ return new ijException(LocalizedResource.getMessage(ResourceNotFound));
+ }
+ static ijException getConnectionFailed() {
+ return new ijException(LocalizedResource.getMessage(GetConnectionFailed));
+ }
+ static ijException iOException(IOException t) {
+ return new ijException(LocalizedResource.getMessage(IOException, t.getMessage()));
+ }
+ static ijException needToDisconnect() {
+ return new ijException(LocalizedResource.getMessage(NeedToDisconnect));
+ }
+ static ijException noSuchAsyncStatement(String c) {
+ return new ijException(LocalizedResource.getMessage(NoSuchAsyncStatement, c));
+ }
+ static ijException noSuchConnection(String c) {
+ return new ijException(LocalizedResource.getMessage(NoSuchConnection, c));
+ }
+ static ijException noSuchProtocol(String c) {
+ return new ijException(LocalizedResource.getMessage(NoSuchProtocol, c));
+ }
+ static public ijException notJDBC20(String operation) {
+ return new ijException(LocalizedResource.getMessage(NotJDBC20, operation));
+ }
+ static ijException noUsingResults() {
+ return new ijException(LocalizedResource.getMessage(NoUsingResults));
+ }
+ static public ijException objectWasNull(String objectName) {
+ return new ijException(LocalizedResource.getMessage(ObjectWasNull, objectName));
+ }
+ static ijException resultSetGetWarningsFailed() {
+ return new ijException(LocalizedResource.getMessage(ResultSetGetWarningsFailed));
+ }
+ static ijException scrollCursorsNotSupported() {
+ return new ijException(LocalizedResource.getMessage(ScrollCursorsNotSupported));
+ }
+ //IJImpl20.utilMain can't throw exception for holdable cursors if
+ //following not declared public
+ public static ijException holdCursorsNotSupported() {
+ return new ijException(LocalizedResource.getMessage(HoldCursorsNotSupported));
+ }
+ static ijException statementGetWarningsFailed() {
+ return new ijException(LocalizedResource.getMessage(StatementGetWarningsFailed));
+ }
+ static ijException waitInterrupted(Throwable t) {
+ return new ijException(LocalizedResource.getMessage(WaitInterrupted, t.toString()));
+ }
+ public static ijException zeroInvalidForAbsolute() {
+ return new ijException(LocalizedResource.getMessage(ZeroInvalidForAbsolute));
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijExceptionResult.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijExceptionResult.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijExceptionResult.java Fri Sep 24 10:33:20 2004
@@ -1,40 +1,40 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-
-/**
- * This is an impl for just returning errors from
- * JDBC statements. Used by Async to capture its result
- * for WaitFor.
- *
- * @author ames
- */
-class ijExceptionResult extends ijResultImpl {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- SQLException except;
-
- ijExceptionResult(SQLException e) {
- except = e;
- }
-
- public boolean isException() { return true; }
- public SQLException getException() { return except; }
-
- public SQLWarning getSQLWarnings() { return null; }
- public void clearSQLWarnings() { }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+
+/**
+ * This is an impl for just returning errors from
+ * JDBC statements. Used by Async to capture its result
+ * for WaitFor.
+ *
+ * @author ames
+ */
+class ijExceptionResult extends ijResultImpl {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ SQLException except;
+
+ ijExceptionResult(SQLException e) {
+ except = e;
+ }
+
+ public boolean isException() { return true; }
+ public SQLException getException() { return except; }
+
+ public SQLWarning getSQLWarnings() { return null; }
+ public void clearSQLWarnings() { }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijFatalException.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijFatalException.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijFatalException.java Fri Sep 24 10:33:20 2004
@@ -1,50 +1,50 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-import java.io.IOException;
-import java.sql.SQLException;
-/**
- * Used for fatal IJ exceptions
- */
-
-public class ijFatalException extends RuntimeException {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- private final static String FatalException = LocalizedResource.getMessage("IJ_FataExceTerm");
- private SQLException e;
-
- public ijFatalException()
- {
- super(FatalException);
- e = null;
- }
-
- public ijFatalException(SQLException e)
- {
- super(FatalException);
- this.e = e;
- }
-
- public String getSQLState()
- {
- return e.getSQLState();
- }
-
- public String toString()
- {
- return LocalizedResource.getMessage("IJ_Fata01",e.getSQLState(),e.getMessage());
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+import java.io.IOException;
+import java.sql.SQLException;
+/**
+ * Used for fatal IJ exceptions
+ */
+
+public class ijFatalException extends RuntimeException {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ private final static String FatalException = LocalizedResource.getMessage("IJ_FataExceTerm");
+ private SQLException e;
+
+ public ijFatalException()
+ {
+ super(FatalException);
+ e = null;
+ }
+
+ public ijFatalException(SQLException e)
+ {
+ super(FatalException);
+ this.e = e;
+ }
+
+ public String getSQLState()
+ {
+ return e.getSQLState();
+ }
+
+ public String toString()
+ {
+ return LocalizedResource.getMessage("IJ_Fata01",e.getSQLState(),e.getMessage());
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijMultiResult.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijMultiResult.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijMultiResult.java Fri Sep 24 10:33:20 2004
@@ -1,60 +1,60 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.util.Vector;
-
-/**
- * This is an impl for a statement execution; the result
- * is either an update count or result set depending
- * on what was executed.
- *
- * @author ames
- */
-class ijMultiResult extends ijResultImpl {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- Vector results = new Vector();
- Statement statement;
- ResultSet rs;
- boolean closeWhenDone;
-
- ijMultiResult(Statement s, ResultSet rs, boolean c) {
- statement = s;
- this.rs = rs;
- closeWhenDone = c;
- }
-
- public void addStatementResult(Statement s) throws SQLException {
-System.out.println("adding statement "+results.size()+1);
- if (s.getUpdateCount() >=0)
- results.addElement(new Integer(s.getUpdateCount()));
- else
- results.addElement(s.getResultSet());
- }
-
- public boolean isMulti() { return true; }
-
- public Statement getStatement() { return statement; }
- public ResultSet getResultSet() { return rs; }
- public void closeStatement() throws SQLException { if (closeWhenDone) statement.close(); }
-
- public SQLWarning getSQLWarnings() { return null; }
- public void clearSQLWarnings() { }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.util.Vector;
+
+/**
+ * This is an impl for a statement execution; the result
+ * is either an update count or result set depending
+ * on what was executed.
+ *
+ * @author ames
+ */
+class ijMultiResult extends ijResultImpl {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ Vector results = new Vector();
+ Statement statement;
+ ResultSet rs;
+ boolean closeWhenDone;
+
+ ijMultiResult(Statement s, ResultSet rs, boolean c) {
+ statement = s;
+ this.rs = rs;
+ closeWhenDone = c;
+ }
+
+ public void addStatementResult(Statement s) throws SQLException {
+System.out.println("adding statement "+results.size()+1);
+ if (s.getUpdateCount() >=0)
+ results.addElement(new Integer(s.getUpdateCount()));
+ else
+ results.addElement(s.getResultSet());
+ }
+
+ public boolean isMulti() { return true; }
+
+ public Statement getStatement() { return statement; }
+ public ResultSet getResultSet() { return rs; }
+ public void closeStatement() throws SQLException { if (closeWhenDone) statement.close(); }
+
+ public SQLWarning getSQLWarnings() { return null; }
+ public void clearSQLWarnings() { }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijResult.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijResult.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijResult.java Fri Sep 24 10:33:20 2004
@@ -1,59 +1,59 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.util.Vector;
-
-/**
- * This is a wrapper for results coming out of the
- * ij parser.
- *
- * @author ames
- *
- */
-public interface ijResult {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- boolean isConnection();
- boolean isStatement();
- boolean isResultSet() throws SQLException;
- boolean isUpdateCount() throws SQLException;
- boolean isNextRowOfResultSet();
- boolean isVector();
- boolean isMulti();
- boolean isException();
- boolean hasWarnings() throws SQLException ;
-
- Connection getConnection();
- Statement getStatement();
- int getUpdateCount() throws SQLException;
- ResultSet getResultSet() throws SQLException;
- ResultSet getNextRowOfResultSet();
- Vector getVector();
- SQLException getException();
-
- void closeStatement() throws SQLException ;
-
- /*
- Since they will all need to do warning calls/clears, may as
- well stick it here.
- */
- SQLWarning getSQLWarnings() throws SQLException ;
- void clearSQLWarnings() throws SQLException ;
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.util.Vector;
+
+/**
+ * This is a wrapper for results coming out of the
+ * ij parser.
+ *
+ * @author ames
+ *
+ */
+public interface ijResult {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ boolean isConnection();
+ boolean isStatement();
+ boolean isResultSet() throws SQLException;
+ boolean isUpdateCount() throws SQLException;
+ boolean isNextRowOfResultSet();
+ boolean isVector();
+ boolean isMulti();
+ boolean isException();
+ boolean hasWarnings() throws SQLException ;
+
+ Connection getConnection();
+ Statement getStatement();
+ int getUpdateCount() throws SQLException;
+ ResultSet getResultSet() throws SQLException;
+ ResultSet getNextRowOfResultSet();
+ Vector getVector();
+ SQLException getException();
+
+ void closeStatement() throws SQLException ;
+
+ /*
+ Since they will all need to do warning calls/clears, may as
+ well stick it here.
+ */
+ SQLWarning getSQLWarnings() throws SQLException ;
+ void clearSQLWarnings() throws SQLException ;
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijVectorResult.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijVectorResult.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijVectorResult.java Fri Sep 24 10:33:20 2004
@@ -1,41 +1,41 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.util.Vector;
-import java.sql.SQLWarning;
-
-/**
- * This is an impl for a simple Vector of strings.
- *
- * @author ames
- */
-class ijVectorResult extends ijResultImpl {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- Vector vec;
- SQLWarning warns;
-
- ijVectorResult(Vector v, SQLWarning w) {
- vec = v;
- warns = w;
- }
-
- public boolean isVector() { return true; }
-
- public Vector getVector() { return vec; }
-
- public SQLWarning getSQLWarnings() { return warns; }
- public void clearSQLWarnings() { warns = null; }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.util.Vector;
+import java.sql.SQLWarning;
+
+/**
+ * This is an impl for a simple Vector of strings.
+ *
+ * @author ames
+ */
+class ijVectorResult extends ijResultImpl {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ Vector vec;
+ SQLWarning warns;
+
+ ijVectorResult(Vector v, SQLWarning w) {
+ vec = v;
+ warns = w;
+ }
+
+ public boolean isVector() { return true; }
+
+ public Vector getVector() { return vec; }
+
+ public SQLWarning getSQLWarnings() { return warns; }
+ public void clearSQLWarnings() { warns = null; }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijWarningResult.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijWarningResult.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/ijWarningResult.java Fri Sep 24 10:33:20 2004
@@ -1,41 +1,41 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-
-/**
- * This is an impl for just returning warnings from
- * JDBC objects we don't want the caller to touch.
- * They are already cleared from the underlying
- * objects, doing clearSQLWarnings here is redundant.
- *
- * @author ames
- */
-class ijWarningResult extends ijResultImpl {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- SQLWarning warn;
-
- ijWarningResult(SQLWarning w) {
- warn = w;
- }
-
- public SQLWarning getSQLWarnings() { return warn; }
- public void clearSQLWarnings() { warn = null; }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+
+/**
+ * This is an impl for just returning warnings from
+ * JDBC objects we don't want the caller to touch.
+ * They are already cleared from the underlying
+ * objects, doing clearSQLWarnings here is redundant.
+ *
+ * @author ames
+ */
+class ijWarningResult extends ijResultImpl {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ SQLWarning warn;
+
+ ijWarningResult(SQLWarning w) {
+ warn = w;
+ }
+
+ public SQLWarning getSQLWarnings() { return warn; }
+ public void clearSQLWarnings() { warn = null; }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestCase.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestCase.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestCase.java Fri Sep 24 10:33:20 2004
@@ -1,287 +1,287 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.util.Hashtable;
-import java.util.Properties;
-import java.lang.Math;
-import java.io.FileNotFoundException;
-import java.io.BufferedInputStream;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import org.apache.derby.iapi.tools.i18n.*;
-
-/**
- */
-public class mtTestCase
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- public String name = null;
- public String file = null;
- public String propFile = null;
- public float weight = (float).5;
- public Hashtable ignoreErrors = null;
- public String description = null;
-
-
- private int iterations;
- private int attempts;
-
- public void mtTestCase()
- { };
-
- public void setName(String name)
- {
- this.name = name;
- }
- public String getName()
- {
- return name;
- }
-
- public void setFile(String name)
- {
- this.file = name;
- }
-
- public void setInputDir(String dir)
- {
- file = dir + "/" + file;
- }
-
- public String getFile()
- {
- return file;
- }
-
- public void setPropFile(String name)
- {
- this.propFile = name;
- }
-
- public String getPropFile()
- {
- return propFile;
- }
-
- public void setWeight(int weight)
- {
- this.weight = (float)(weight/100.0);
- }
-
- public void setIgnoreErrors(Hashtable t)
- {
- this.ignoreErrors = t;
- }
-
- public void setDescription(String description)
- {
- this.description = description;
- }
-
- /**
- ** Initialize the test case. See initialize(String)
- */
- public synchronized BufferedInputStream initialize()
- throws FileNotFoundException, IOException
- {
- return initialize(null);
- }
-
- /**
- ** Initizalize the test case. Loads up the properties
- ** file and sets the input stream. Used to set up
- ** prior to running the thread.
- */
- public synchronized BufferedInputStream initialize(String inputDir)
- throws FileNotFoundException, IOException
- {
- String filePath;
- BufferedInputStream inStream = null;
-
- // load up properties
- if (propFile != null)
- {
- BufferedInputStream propStream;
- Properties p;
- String propPath = (inputDir == null) ?
- propFile :
- (inputDir + "/" + propFile);
-
- try
- {
- propStream = new BufferedInputStream(new FileInputStream(propPath));
- } catch (FileNotFoundException e)
- {
- System.out.println(name+": unable to find properties file "+propPath);
- throw e;
- }
-
- p = System.getProperties();
- p.load(propStream);
- // for network server need to alter url
- String framework = p.getProperty("framework");
-
- if (framework != null && framework.equals("DB2jNet"))
- {
- String newURLPrefix= "jdbc:derby:net://localhost:1527/";
- updateURLProperties(p,newURLPrefix);
- p.setProperty("ij.user","APP");
- p.setProperty("ij.password","PWD");
- }
- System.setProperties(p);
- }
- // set input stream
- filePath = (inputDir == null) ?
- file : (inputDir + "/" + file);
-
- try
- {
- inStream = new BufferedInputStream(new FileInputStream(filePath),
- utilMain.BUFFEREDFILESIZE);
- } catch (FileNotFoundException e)
- {
- System.out.println("unable to find properties file "+filePath);
- throw e;
- }
- return inStream;
- }
-
- /**
- ** Attempt to grab this test case.
- ** Uses random number and the weight of this
- ** case to determine if the grab was successful.
- **
- ** @return true/false
- */
- public synchronized boolean grab()
- {
- attempts++;
- if (java.lang.Math.random() < weight)
- {
- iterations++;
- return true;
- }
- else
- {
- return false;
- }
- }
-
- /**
- ** Run the test case. Invokes IJ to do our
- ** dirty work.
- */
- public void runMe(LocalizedOutput log, LocalizedOutput out, BufferedInputStream infile)
- {
- utilMain utilInstance;
- LocalizedInput is;
- is = LocalizedResource.getInstance().getNewInput(infile);
-
- LocalizedInput [] in = { is };
-
- out.println("--------------"+file+"-----------------");
- utilInstance = new utilMain(1, out, ignoreErrors);
- utilInstance.setMtUse(true);
- utilInstance.go(in, out, (java.util.Properties) null);
- log.flush();
- out.flush();
- }
-
- public void updateURLProperties(Properties p, String newURLPrefix)
- {
- String[] propsToUpdate = {"ij.database", "ij.protocol",
- "database"};
- for (int i = 0; i < propsToUpdate.length; i++)
- {
- String key = propsToUpdate[i];
- String val = p.getProperty(key);
- if (val != null)
- p.setProperty(key,alterURL(val,newURLPrefix));
- }
- }
-
-
- public String alterURL(String url, String newURLPrefix)
- {
- String urlPrefix = "jdbc:derby:";
-
- if (url.startsWith(newURLPrefix))
- return url;
-
- // If we don't have a URL prefix for this framework
- // just return
- if (newURLPrefix == null)
- return url;
-
- if (url.equals(urlPrefix)) // Replace embedded
- return newURLPrefix;
-
- if (url.startsWith(urlPrefix))
- {
- // replace jdbc:derby: with our url:
- url = newURLPrefix +
- url.substring(urlPrefix.length());
-
- }
- else
- {
- if (! (url.startsWith("jdbc:")))
- {
- url = newURLPrefix + url;
- }
- }
- //System.out.println("New url:" +url);
- return url;
- }
-
-
-// NOTE: tried invoking ij directly, but had some problems,
-// so stick with calling utilMain().
-// /**
-// ** Run the test case. Invokes IJ to do our
-// ** dirty work.
-// */
-// public void runMe(AppStreamWriter log, AppStreamWriter out, BufferedInputStream infile)
-// {
-// ASCII_UCodeESC_CharStream charStream;
-// ijTokenManager ijTokMgr;
-// ij ijParser;
-//
-//
-// out.println("--------------"+file+"-----------------");
-// charStream = new ASCII_UCodeESC_CharStream(in, 1, 1);
-// ijTokMgr = new ijTokenManager(charStream);
-// ijParser = new ij(ijTokMgr, System.out, this);
-// log.flush();
-// out.flush();
-// }
-
- /**
- ** Name says it all
- */
- public String toString()
- {
- return "name: "+name+
- "\n\tfile: "+file+
- "\n\tproperties: "+propFile+
- "\n\tweight: "+weight+
- "\n\tignoreErrors: "+ignoreErrors+
- "\n\tdescription: "+description;
- }
-
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.util.Hashtable;
+import java.util.Properties;
+import java.lang.Math;
+import java.io.FileNotFoundException;
+import java.io.BufferedInputStream;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import org.apache.derby.iapi.tools.i18n.*;
+
+/**
+ */
+public class mtTestCase
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ public String name = null;
+ public String file = null;
+ public String propFile = null;
+ public float weight = (float).5;
+ public Hashtable ignoreErrors = null;
+ public String description = null;
+
+
+ private int iterations;
+ private int attempts;
+
+ public void mtTestCase()
+ { };
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setFile(String name)
+ {
+ this.file = name;
+ }
+
+ public void setInputDir(String dir)
+ {
+ file = dir + "/" + file;
+ }
+
+ public String getFile()
+ {
+ return file;
+ }
+
+ public void setPropFile(String name)
+ {
+ this.propFile = name;
+ }
+
+ public String getPropFile()
+ {
+ return propFile;
+ }
+
+ public void setWeight(int weight)
+ {
+ this.weight = (float)(weight/100.0);
+ }
+
+ public void setIgnoreErrors(Hashtable t)
+ {
+ this.ignoreErrors = t;
+ }
+
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ ** Initialize the test case. See initialize(String)
+ */
+ public synchronized BufferedInputStream initialize()
+ throws FileNotFoundException, IOException
+ {
+ return initialize(null);
+ }
+
+ /**
+ ** Initizalize the test case. Loads up the properties
+ ** file and sets the input stream. Used to set up
+ ** prior to running the thread.
+ */
+ public synchronized BufferedInputStream initialize(String inputDir)
+ throws FileNotFoundException, IOException
+ {
+ String filePath;
+ BufferedInputStream inStream = null;
+
+ // load up properties
+ if (propFile != null)
+ {
+ BufferedInputStream propStream;
+ Properties p;
+ String propPath = (inputDir == null) ?
+ propFile :
+ (inputDir + "/" + propFile);
+
+ try
+ {
+ propStream = new BufferedInputStream(new FileInputStream(propPath));
+ } catch (FileNotFoundException e)
+ {
+ System.out.println(name+": unable to find properties file "+propPath);
+ throw e;
+ }
+
+ p = System.getProperties();
+ p.load(propStream);
+ // for network server need to alter url
+ String framework = p.getProperty("framework");
+
+ if (framework != null && framework.equals("DB2jNet"))
+ {
+ String newURLPrefix= "jdbc:derby:net://localhost:1527/";
+ updateURLProperties(p,newURLPrefix);
+ p.setProperty("ij.user","APP");
+ p.setProperty("ij.password","PWD");
+ }
+ System.setProperties(p);
+ }
+ // set input stream
+ filePath = (inputDir == null) ?
+ file : (inputDir + "/" + file);
+
+ try
+ {
+ inStream = new BufferedInputStream(new FileInputStream(filePath),
+ utilMain.BUFFEREDFILESIZE);
+ } catch (FileNotFoundException e)
+ {
+ System.out.println("unable to find properties file "+filePath);
+ throw e;
+ }
+ return inStream;
+ }
+
+ /**
+ ** Attempt to grab this test case.
+ ** Uses random number and the weight of this
+ ** case to determine if the grab was successful.
+ **
+ ** @return true/false
+ */
+ public synchronized boolean grab()
+ {
+ attempts++;
+ if (java.lang.Math.random() < weight)
+ {
+ iterations++;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ ** Run the test case. Invokes IJ to do our
+ ** dirty work.
+ */
+ public void runMe(LocalizedOutput log, LocalizedOutput out, BufferedInputStream infile)
+ {
+ utilMain utilInstance;
+ LocalizedInput is;
+ is = LocalizedResource.getInstance().getNewInput(infile);
+
+ LocalizedInput [] in = { is };
+
+ out.println("--------------"+file+"-----------------");
+ utilInstance = new utilMain(1, out, ignoreErrors);
+ utilInstance.setMtUse(true);
+ utilInstance.go(in, out, (java.util.Properties) null);
+ log.flush();
+ out.flush();
+ }
+
+ public void updateURLProperties(Properties p, String newURLPrefix)
+ {
+ String[] propsToUpdate = {"ij.database", "ij.protocol",
+ "database"};
+ for (int i = 0; i < propsToUpdate.length; i++)
+ {
+ String key = propsToUpdate[i];
+ String val = p.getProperty(key);
+ if (val != null)
+ p.setProperty(key,alterURL(val,newURLPrefix));
+ }
+ }
+
+
+ public String alterURL(String url, String newURLPrefix)
+ {
+ String urlPrefix = "jdbc:derby:";
+
+ if (url.startsWith(newURLPrefix))
+ return url;
+
+ // If we don't have a URL prefix for this framework
+ // just return
+ if (newURLPrefix == null)
+ return url;
+
+ if (url.equals(urlPrefix)) // Replace embedded
+ return newURLPrefix;
+
+ if (url.startsWith(urlPrefix))
+ {
+ // replace jdbc:derby: with our url:
+ url = newURLPrefix +
+ url.substring(urlPrefix.length());
+
+ }
+ else
+ {
+ if (! (url.startsWith("jdbc:")))
+ {
+ url = newURLPrefix + url;
+ }
+ }
+ //System.out.println("New url:" +url);
+ return url;
+ }
+
+
+// NOTE: tried invoking ij directly, but had some problems,
+// so stick with calling utilMain().
+// /**
+// ** Run the test case. Invokes IJ to do our
+// ** dirty work.
+// */
+// public void runMe(AppStreamWriter log, AppStreamWriter out, BufferedInputStream infile)
+// {
+// ASCII_UCodeESC_CharStream charStream;
+// ijTokenManager ijTokMgr;
+// ij ijParser;
+//
+//
+// out.println("--------------"+file+"-----------------");
+// charStream = new ASCII_UCodeESC_CharStream(in, 1, 1);
+// ijTokMgr = new ijTokenManager(charStream);
+// ijParser = new ij(ijTokMgr, System.out, this);
+// log.flush();
+// out.flush();
+// }
+
+ /**
+ ** Name says it all
+ */
+ public String toString()
+ {
+ return "name: "+name+
+ "\n\tfile: "+file+
+ "\n\tproperties: "+propFile+
+ "\n\tweight: "+weight+
+ "\n\tignoreErrors: "+ignoreErrors+
+ "\n\tdescription: "+description;
+ }
+
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestSuite.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestSuite.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTestSuite.java Fri Sep 24 10:33:20 2004
@@ -1,180 +1,180 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.util.Vector;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.Math;
-
-/**
- */
-public class mtTestSuite
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- private Vector cases;
- private Vector last;
- private Vector init;
- private mtTime time;
- private int numThreads;
- private String rootDir = null;
-
-
- mtTestSuite(int numThreads, mtTime time,
- Vector initCases, Vector testCases, Vector finalCases)
- {
- this.numThreads = numThreads;
- this.time = time;
- this.cases = testCases;
- this.init = initCases;
- this.last = finalCases;
- }
-
- public void init()
- {
- boolean loadInitFailed = loadCases(init);
- boolean loadTestsFailed = loadCases(cases);
- boolean loadLastFailed = loadCases(last);
-
- if ((loadInitFailed == true) ||
- (loadTestsFailed == true) ||
- (loadLastFailed == true))
- {
- throw new Error("Initialization Error");
- }
- }
-
- /**
- ** @return boolean indicates if there was a problem loading
- ** the file
- */
- private boolean loadCases(Vector cases)
- {
- if (cases == null)
- return false;
-
- boolean gotError = false;
- Enumeration e = cases.elements();
- mtTestCase tcase;
-
- while (e.hasMoreElements())
- {
- tcase = (mtTestCase)e.nextElement();
- try
- {
- tcase.initialize(rootDir);
- }
- catch (Throwable t)
- {
- gotError = true;
- }
- }
-
- return gotError;
- }
-
- public void setRoot(String rootDir)
- {
- this.rootDir = rootDir;
- }
-
- public String getRoot()
- {
- return rootDir;
- }
-
- public int getNumThreads()
- {
- return numThreads;
- }
-
- public Vector getCases()
- {
- return cases;
- }
-
- public Vector getInitCases()
- {
- return init;
- }
-
- public Vector getFinalCases()
- {
- return last;
- }
-
- public mtTime getTime()
- {
- return time;
- }
-
- public long getTimeMillis()
- {
- return ((time.hours * 360) +
- (time.minutes * 60) +
- (time.seconds)) * 1000;
- }
-
- public String toString()
- {
- String str;
- int len;
- int i;
-
- str = "TEST CASES\nNumber of Threads: "+numThreads;
- str +="\nTime: "+time;
- str +="\nNumber of Initializers: "+init.size()+"\n";
- for (i = 0, len = init.size(); i < len; i++)
- {
- str += init.elementAt(i).toString() + "\n";
- }
-
- str +="\nNumber of Cases: "+cases.size()+"\n";
- for (i = 0, len = cases.size(); i < len; i++)
- {
- str += cases.elementAt(i).toString() + "\n";
- }
-
- str +="\nNumber of Final Cases: "+last.size()+"\n";
- for (i = 0, len = last.size(); i < len; i++)
- {
- str += last.elementAt(i).toString() + "\n";
- }
-
- return str;
- }
-
- /*
- ** Grab a test case. Pick one randomly and
- ** try to grab that case. If we get it we are
- ** done. Otherwise, try try again.
- */
- public mtTestCase grabTestCase()
- {
- int numCases = cases.size();
- int caseNum;
- mtTestCase testCase;
-
- do
- {
- caseNum = (int)((java.lang.Math.random() * 1311) % numCases);
- testCase = (mtTestCase)cases.elementAt(caseNum);
- }
- while (testCase.grab() == false);
-
- return testCase;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.Math;
+
+/**
+ */
+public class mtTestSuite
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ private Vector cases;
+ private Vector last;
+ private Vector init;
+ private mtTime time;
+ private int numThreads;
+ private String rootDir = null;
+
+
+ mtTestSuite(int numThreads, mtTime time,
+ Vector initCases, Vector testCases, Vector finalCases)
+ {
+ this.numThreads = numThreads;
+ this.time = time;
+ this.cases = testCases;
+ this.init = initCases;
+ this.last = finalCases;
+ }
+
+ public void init()
+ {
+ boolean loadInitFailed = loadCases(init);
+ boolean loadTestsFailed = loadCases(cases);
+ boolean loadLastFailed = loadCases(last);
+
+ if ((loadInitFailed == true) ||
+ (loadTestsFailed == true) ||
+ (loadLastFailed == true))
+ {
+ throw new Error("Initialization Error");
+ }
+ }
+
+ /**
+ ** @return boolean indicates if there was a problem loading
+ ** the file
+ */
+ private boolean loadCases(Vector cases)
+ {
+ if (cases == null)
+ return false;
+
+ boolean gotError = false;
+ Enumeration e = cases.elements();
+ mtTestCase tcase;
+
+ while (e.hasMoreElements())
+ {
+ tcase = (mtTestCase)e.nextElement();
+ try
+ {
+ tcase.initialize(rootDir);
+ }
+ catch (Throwable t)
+ {
+ gotError = true;
+ }
+ }
+
+ return gotError;
+ }
+
+ public void setRoot(String rootDir)
+ {
+ this.rootDir = rootDir;
+ }
+
+ public String getRoot()
+ {
+ return rootDir;
+ }
+
+ public int getNumThreads()
+ {
+ return numThreads;
+ }
+
+ public Vector getCases()
+ {
+ return cases;
+ }
+
+ public Vector getInitCases()
+ {
+ return init;
+ }
+
+ public Vector getFinalCases()
+ {
+ return last;
+ }
+
+ public mtTime getTime()
+ {
+ return time;
+ }
+
+ public long getTimeMillis()
+ {
+ return ((time.hours * 360) +
+ (time.minutes * 60) +
+ (time.seconds)) * 1000;
+ }
+
+ public String toString()
+ {
+ String str;
+ int len;
+ int i;
+
+ str = "TEST CASES\nNumber of Threads: "+numThreads;
+ str +="\nTime: "+time;
+ str +="\nNumber of Initializers: "+init.size()+"\n";
+ for (i = 0, len = init.size(); i < len; i++)
+ {
+ str += init.elementAt(i).toString() + "\n";
+ }
+
+ str +="\nNumber of Cases: "+cases.size()+"\n";
+ for (i = 0, len = cases.size(); i < len; i++)
+ {
+ str += cases.elementAt(i).toString() + "\n";
+ }
+
+ str +="\nNumber of Final Cases: "+last.size()+"\n";
+ for (i = 0, len = last.size(); i < len; i++)
+ {
+ str += last.elementAt(i).toString() + "\n";
+ }
+
+ return str;
+ }
+
+ /*
+ ** Grab a test case. Pick one randomly and
+ ** try to grab that case. If we get it we are
+ ** done. Otherwise, try try again.
+ */
+ public mtTestCase grabTestCase()
+ {
+ int numCases = cases.size();
+ int caseNum;
+ mtTestCase testCase;
+
+ do
+ {
+ caseNum = (int)((java.lang.Math.random() * 1311) % numCases);
+ testCase = (mtTestCase)cases.elementAt(caseNum);
+ }
+ while (testCase.grab() == false);
+
+ return testCase;
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTester.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTester.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTester.java Fri Sep 24 10:33:20 2004
@@ -1,113 +1,113 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import java.util.Vector;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.io.BufferedInputStream;
-import java.util.Date;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
-
-/**
- * mtTester grabs test and runs them forever.
- * The spawner of tester is responsible for
- * killing it.
- */
-public class mtTester implements Runnable
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- private mtTestSuite suite;
- private String name;
- private LocalizedOutput log;
- private LocalizedOutput out;
- private boolean stop = false;
-
- public mtTester(String name, mtTestSuite suite, LocalizedOutput out, LocalizedOutput log)
- {
- this.name = name;
- this.suite = suite;
- this.log = log;
- this.out = out;
- log.println("...initialized "+ name + " at " + new Date());
- }
-
- /**
- ** Run until killed or until there is a problem.
- ** If we get other than 'connection closed' we'll
- ** signal that we recieved a fatal error before
- ** quittiing; otherwise, we are silent.
- */
- public void run()
- {
- int numIterations = 0;
-
- try
- {
- mtTestCase testCase;
- BufferedInputStream in;
-
- // loop until we get an error or
- // are killed.
- while (!stop)
- {
- numIterations++;
- testCase = suite.grabTestCase();
- try
- {
- in = testCase.initialize(suite.getRoot());
- } catch (FileNotFoundException e)
- {
- System.out.println(e);
- return;
- }
- catch (IOException e)
- {
- System.out.println(e);
- return;
- }
-
- log.println(name + ": "+ testCase.getName() + " " + new Date());
- testCase.runMe(log, out, in);
- }
- }
- catch (ijFatalException e)
- {
-
- /*
- ** If we got connection closed (XJ010), we'll
- ** assume that we were deliberately killed
- ** via a Thread.stop() and it was caught by
- ** jbms. Otherwise, we'll print out an
- ** error message.
- */
- if (e.getSQLState() == null || !(e.getSQLState().equals("XJ010")))
- {
- log.println(name + ": TERMINATING due to unexpected error:\n"+e);
- throw new ThreadDeath();
- }
- }
- if (stop)
- {
- log.println(name + ": stopping on request after " + numIterations +
- " iterations");
- }
- }
-
- public void stop()
- {
- stop = true;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import java.util.Vector;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.BufferedInputStream;
+import java.util.Date;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
+
+/**
+ * mtTester grabs test and runs them forever.
+ * The spawner of tester is responsible for
+ * killing it.
+ */
+public class mtTester implements Runnable
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ private mtTestSuite suite;
+ private String name;
+ private LocalizedOutput log;
+ private LocalizedOutput out;
+ private boolean stop = false;
+
+ public mtTester(String name, mtTestSuite suite, LocalizedOutput out, LocalizedOutput log)
+ {
+ this.name = name;
+ this.suite = suite;
+ this.log = log;
+ this.out = out;
+ log.println("...initialized "+ name + " at " + new Date());
+ }
+
+ /**
+ ** Run until killed or until there is a problem.
+ ** If we get other than 'connection closed' we'll
+ ** signal that we recieved a fatal error before
+ ** quittiing; otherwise, we are silent.
+ */
+ public void run()
+ {
+ int numIterations = 0;
+
+ try
+ {
+ mtTestCase testCase;
+ BufferedInputStream in;
+
+ // loop until we get an error or
+ // are killed.
+ while (!stop)
+ {
+ numIterations++;
+ testCase = suite.grabTestCase();
+ try
+ {
+ in = testCase.initialize(suite.getRoot());
+ } catch (FileNotFoundException e)
+ {
+ System.out.println(e);
+ return;
+ }
+ catch (IOException e)
+ {
+ System.out.println(e);
+ return;
+ }
+
+ log.println(name + ": "+ testCase.getName() + " " + new Date());
+ testCase.runMe(log, out, in);
+ }
+ }
+ catch (ijFatalException e)
+ {
+
+ /*
+ ** If we got connection closed (XJ010), we'll
+ ** assume that we were deliberately killed
+ ** via a Thread.stop() and it was caught by
+ ** jbms. Otherwise, we'll print out an
+ ** error message.
+ */
+ if (e.getSQLState() == null || !(e.getSQLState().equals("XJ010")))
+ {
+ log.println(name + ": TERMINATING due to unexpected error:\n"+e);
+ throw new ThreadDeath();
+ }
+ }
+ if (stop)
+ {
+ log.println(name + ": stopping on request after " + numIterations +
+ " iterations");
+ }
+ }
+
+ public void stop()
+ {
+ stop = true;
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTime.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTime.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/mtTime.java Fri Sep 24 10:33:20 2004
@@ -1,36 +1,36 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-/**
- */
-public class mtTime
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
- public int hours;
- public int minutes;
- public int seconds;
-
- mtTime(int hours, int minutes, int seconds)
- {
- this.hours = hours;
- this.minutes = minutes;
- this.seconds = seconds;
- }
-
- public String toString()
- {
- return hours+":"+minutes+":"+seconds;
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+/**
+ */
+public class mtTime
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+ public int hours;
+ public int minutes;
+ public int seconds;
+
+ mtTime(int hours, int minutes, int seconds)
+ {
+ this.hours = hours;
+ this.minutes = minutes;
+ this.seconds = seconds;
+ }
+
+ public String toString()
+ {
+ return hours+":"+minutes+":"+seconds;
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/util.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/util.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/util.java Fri Sep 24 10:33:20 2004
@@ -1,735 +1,735 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.tools.JDBCDisplayUtil;
-import org.apache.derby.iapi.tools.i18n.*;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.IOException;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Statement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Types;
-
-import java.util.Properties;
-import java.util.Vector;
-import java.util.Stack;
-import java.math.BigDecimal;
-
-/**
- Methods used to control setup for apps as
- well as display some internal ij structures.
-
- @see org.apache.derby.tools.JDBCDisplayUtil
- @author ames
- */
-public class util implements java.security.PrivilegedAction {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- private util() {}
-
- //-----------------------------------------------------------------
- // Methods for starting up JBMS
-
- /**
- * Find the argument that follows the specified parameter.
- *
- * @param param the parameter (e.g. "-p")
- * @param args the argument list to consider.
- *
- * @return the argument that follows the parameter, or null if not found
- */
- static public String getArg(String param, String[] args)
- {
- int pLocn;
- Properties p;
-
- if (args == null) return null;
-
- for (pLocn=0; pLocn<args.length; pLocn++) {
- if (param.equals(args[pLocn])) break;
- }
- if (pLocn >= (args.length-1)) // not found or no file
- return null;
-
- return args[pLocn+1];
- }
-
- /**
- ij is started with "-p[r] file OtherArgs";
- the file contains properties to control the driver and database
- used to run ij, and can provide additional system properties.
- <p>
- getPropertyArg will look at the args and take out a "-p <file>" pair,
- reading the file into the system properties.
- <p>
- If there was a -p without a following <file>, no action is taken.
-
- @exception IOException thrown if file not found
-
- @param args the argument list to consider.
- @return true if a property item was found and loaded.
- */
- static public boolean getPropertyArg(String[] args) throws IOException {
- String n;
- InputStream in1;
- Properties p;
-
- if ((n = getArg("-p", args))!= null){
- in1 = new FileInputStream(n);
- in1 = new BufferedInputStream(in1);
- }
- else if ((n = getArg("-pr", args)) != null) {
- in1 = getResourceAsStream(n);
- if (in1 == null) throw ijException.resourceNotFound();
- }
- else
- return false;
-
- p = System.getProperties();
-
- // Trim off excess whitespace in property file, if any, and
- // then load those properties into 'p'.
- util.loadWithTrimmedValues(in1, p);
-
- return true;
- }
-
- /**
- ij is started with "-ca[r] file OtherArgs";
- the file contains connection attibute properties
- to pass to getConnection
- <p>
- getConnAttributeArg will look at the args and take out a
- "-ca[r] <file>" pair and returning the Properties
- <p>
-
- @exception IOException thrown if file not found
-
- @param args the argument list to consider.
- @return properties in the file
- */
- static public Properties getConnAttributeArg(String[] args)
- throws IOException
- {
- String n;
- InputStream in1;
- Properties p = new Properties();
-
- if ((n = getArg("-ca", args))!= null){
- in1 = new FileInputStream(n);
- in1 = new BufferedInputStream(in1);
- }
- else if ((n = getArg("-car", args)) != null) {
- in1 = getResourceAsStream(n);
- if (in1 == null) throw ijException.resourceNotFound();
- }
- else
- return null;
-
- // Trim off excess whitespace in property file, if any, and
- // then load those properties into 'p'.
- util.loadWithTrimmedValues(in1, p);
-
- return p;
- }
-
-
-
- /**
- Convenience routine to qualify a resource name with "ij.defaultPackageName"
- if it is not qualified (does not begin with a "/").
-
- @param absolute true means return null if the name is not absolute and false
- means return partial names.
- */
- static String qualifyResourceName(String resourceName, boolean absolute)
- {
- resourceName=resourceName.trim();
- if (resourceName.startsWith("/"))
- {
- return resourceName;
- }
- else
- {
- String pName = util.getSystemProperty("ij.defaultResourcePackage").trim();
- if (pName == null) return null;
- if ((pName).endsWith("/"))
- resourceName = pName+resourceName;
- else
- resourceName = pName+"/"+resourceName;
- if (absolute && !resourceName.startsWith("/"))
- return null;
- else
- return resourceName;
- }
- }
- /**
- Convenience routine to get a resource as a BufferedInputStream. If the
- resourceName is not absolute (does not begin with a "/") this qualifies
- the name with the "ij.defaultResourcePackage" name.
-
- @param String the name of the resource
- @return a buffered stream for the resource if it exists and null otherwise.
- */
- static public InputStream getResourceAsStream(String resourceName)
- {
- Class c= util.class;
- resourceName = qualifyResourceName(resourceName,true);
- if (resourceName == null)
- return null;
- InputStream is = c.getResourceAsStream(resourceName);
- if (is != null)
- is = new BufferedInputStream(is, utilMain.BUFFEREDFILESIZE);
- return is;
- }
-
- /**
- Return the name of the ij command file or null if none is
- specified. The command file may be proceeded with -f flag on
- the command line. Alternatively, the command file may be
- specified without a -f flag. In this case we assume the first
- unknown argument is the command file.
-
- <P>
- This should only be called after calling invalidArgs.
-
- <p>
- If there is no such argument, a null is returned.
-
- @param args the argument list to consider.
- @return the name of the first argument not preceded by "-p",
- null if none found.
-
- @exception IOException thrown if file not found
- */
- static public String getFileArg(String[] args) throws IOException {
- String fileName;
- int fLocn;
- boolean foundP = false;
-
- if (args == null) return null;
- if ((fileName=getArg("-f",args))!=null) return fileName;
- //
- //The first unknown arg is the file
- for (int ix=0; ix < args.length; ix++)
- if(args[ix].equals("-f") ||
- args[ix].equals("-fr") ||
- args[ix].equals("-ca") ||
- args[ix].equals("-car") ||
- args[ix].equals("-p") ||
- args[ix].equals("-pr"))
- ix++; //skip the parameter to these args
- else
- return args[ix];
- return null;
- }
-
- /**
- Return the name of a resource containing input commands or
- null iff none has been specified.
- */
- static public String getInputResourceNameArg(String[] args) {
- return getArg("-fr", args);
- }
-
- /**
- Verify the ij line arguments command arguments.
- @return true if the args are invalid
- <UL>
- <LI>Only legal argument provided.
- <LI>Only specify a quantity once.
- </UL>
- */
- static public boolean invalidArgs(String[] args, boolean gotProp, String file,
- String inputResourceName) {
- int countSupported = 0;
- boolean haveInput = false;
- for (int ix=0; ix < args.length; ix++)
- {
- //
- //If the arguemnt is a supported flag skip the flags argument
- if(!haveInput && (args[ix].equals("-f") || args[ix].equals("-fr")))
- {
- haveInput = true;
- ix++;
- if (ix >= args.length) return true;
- }
-
- else if ((args[ix].equals("-p") || args[ix].equals("-pr") ||
- args[ix].equals("-ca") || args[ix].equals("-car") ))
- {
- // next arg is the file/resource name
- ix++;
- if (ix >= args.length) return true;
- }
-
-
- //
- //Assume the first unknown arg is a file name.
- else if (!haveInput)
- {
- haveInput = true;
- }
-
- else
- {
- return true;
- }
- }
- return false;
- }
-
- /**
- * print a usage message for invocations of main().
- */
- static void Usage(LocalizedOutput out) {
- out.println(
- LocalizedResource.getMessage("IJ_UsageJavaComCloudToolsIjPPropeInput"));
- out.flush();
- }
-
-
- private static final Class[] STRING_P = { "".getClass() };
- private static final Class[] INT_P = { Integer.TYPE };
-
-
- static public void setupDataSource(Object ds) throws Exception {
- // Loop over set methods on Datasource object, if there is a property
- // then call the method with corresponding value.
- java.lang.reflect.Method[] methods = ds.getClass().getMethods();
- for (int i = 0; i < methods.length; i++) {
- java.lang.reflect.Method m = methods[i];
- String name = m.getName();
- if (name.startsWith("set") && (name.length() > "set".length())) {
- String property = name.substring("set".length()); // setXyyyZwww
- property = "ij.dataSource."+property.substring(0,1).toLowerCase(java.util.Locale.ENGLISH)+ property.substring(1); // xyyyZwww
- String value = util.getSystemProperty(property);
- //System.out.println("setupDateSource: method="+name+" property="+property+" value="+((value==null)?"null":value));
- if (value != null) {
- try {
- // call string method
- m.invoke(ds, new Object[] {value});
- } catch (Throwable ignore) {
- // failed, assume it's an integer parameter
- m.invoke(ds, new Object[] {Integer.valueOf(value)});
- }
- }
- }
- }
- }
-
- /**
- This will look for the System properties "ij.driver" and "ij.database"
- and return a java.sql.Connection if it successfully connects.
- The deprecated driver and database properties are examined first.
- <p>
- If no connection was possible, it will return a null.
- <p>
- Failure to load the driver class is quietly ignored.
-
- @param defaultDriver the driver to use if no property value found
- @param defaultURL the database URL to use if no property value found
- @param connInfo Connection attributes to pass to getConnection
- @return a connection to the defaultURL if possible; null if not.
- @exception SQLException on failure to connect.
- @exception ClassNotFoundException on failure to load driver.
- @exception InstantiationException on failure to load driver.
- @exception IllegalAccessException on failure to load driver.
- */
- static public Connection startJBMS(String defaultDriver, String defaultURL,
- Properties connInfo)
- throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException
- {
- Connection con = null;
- String driverName;
- String databaseURL;
-
- // deprecate the non-ij prefix. actually, we should defer to jdbc.drivers...
- driverName = util.getSystemProperty("driver");
- if (driverName == null) driverName = util.getSystemProperty("ij.driver");
- if (driverName == null || driverName.length()==0) driverName = defaultDriver;
- if (driverName != null) {
- util.loadDriver(driverName);
- }
-
- String jdbcProtocol = util.getSystemProperty("ij.protocol");
- if (jdbcProtocol != null)
- util.loadDriverIfKnown(jdbcProtocol);
-
- // deprecate the non-ij prefix name
- databaseURL = util.getSystemProperty("database");
- if (databaseURL == null) databaseURL = util.getSystemProperty("ij.database");
- if (databaseURL == null || databaseURL.length()==0) databaseURL = defaultURL;
- if (databaseURL != null) {
- // add protocol if might help find driver.
- boolean noDriver = false;
- try {
- // if have full URL, load driver for it
- if (databaseURL.startsWith("jdbc:"))
- util.loadDriverIfKnown(databaseURL);
- DriverManager.getDriver(databaseURL);
- } catch (SQLException se) {
- noDriver = true;
- }
- if (noDriver && jdbcProtocol != null)
- databaseURL = jdbcProtocol+databaseURL;
-
- String user = util.getSystemProperty("ij.user");
- String password = util.getSystemProperty("ij.password");
-
- // Update connInfo for ij system properties and
- // framework network server
-
- connInfo = updateConnInfo(user, password,connInfo);
-
- // JDBC driver
- String driver = System.getProperty("driver");
- if (driver == null) {
- driver = "org.apache.derby.jdbc.EmbeddedDriver";
- }
-
- // handle datasource property
- String dsName = System.getProperty("ij.dataSource");
- if (dsName == null) {
- loadDriver(driver);
- con = DriverManager.getConnection(databaseURL,connInfo);
- return con;
-
- } else { // a datasource
- // Get a new proxied connection through DataSource
- Object ds = null; // really javax.sql.DataSource
- try {
- Class dc = Class.forName(dsName);
- ds = dc.newInstance();
-
- // set datasource properties
- setupDataSource(ds);
-
- // Java method call "by hand" { con = ds.getConnection(); }
- {
- java.lang.reflect.Method m = dc.getMethod("getConnection", null);
- con = (java.sql.Connection) m.invoke(ds, new Object[] {});
- }
- } catch (Throwable error) {
- error.printStackTrace(System.out);
- }
- return con;
- } // datasource
- }
- // failed
- return null;
- }
-
-
- public static Properties updateConnInfo(String user, String password, Properties connInfo)
- {
- String framework = util.getSystemProperty("framework");
- String ijGetMessages = util.getSystemProperty("ij.retrieveMessagesFromServerOnGetMessage");
- boolean retrieveMessages = false;
-
-
- // For JCC make sure we set it to retrieve messages
- if (framework != null && ((framework.equals("DB2jNet")
- || framework.equals("DB2jcc"))))
- retrieveMessages = true;
-
- if (ijGetMessages != null)
- {
- if (ijGetMessages.equals("false"))
- retrieveMessages = false;
- else
- retrieveMessages = true;
-
- }
-
- if (connInfo == null)
- connInfo = new Properties();
-
- if (retrieveMessages == true)
- {
- connInfo.put("retrieveMessagesFromServerOnGetMessage",
- "true");
- }
- if (user != null)
- connInfo.put("user",user);
- if (password != null)
- connInfo.put("password", password);
-
- return connInfo;
- }
-
- /**
- Utility interface that defaults driver and database to null.
-
- @return a connection to the defaultURL if possible; null if not.
- @exception SQLException on failure to connect.
- @exception ClassNotFoundException on failure to load driver.
- @exception InstantiationException on failure to load driver.
- @exception IllegalAccessException on failure to load driver.
- */
- static public Connection startJBMS() throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
- return startJBMS(null,null);
- }
-
- /**
- Utility interface that defaults connInfo to null
- <p>
-
-
- @param defaultDriver the driver to use if no property value found
- @param defaultURL the database URL to use if no property value found
- @return a connection to the defaultURL if possible; null if not.
- @exception SQLException on failure to connect.
- @exception ClassNotFoundException on failure to load driver.
- @exception InstantiationException on failure to load driver.
- @exception IllegalAccessException on failure to load driver.
- */
- static public Connection startJBMS(String defaultDriver, String defaultURL)
- throws SQLException, ClassNotFoundException, InstantiationException,
- IllegalAccessException {
- return startJBMS(defaultDriver,defaultURL,null);
-
- }
- //-----------------------------------------------------------------
- // Methods for displaying and checking results
- // See org.apache.derby.tools.JDBCDisplayUtil for more general displays.
-
-
- /**
- Display a vector of strings to the out stream.
- */
- public static void DisplayVector(LocalizedOutput out, Vector v) {
- int l = v.size();
- for (int i=0;i<l;i++)
- out.println(v.elementAt(i));
- }
-
- /**
- Display a vector of statements to the out stream.
- public static void DisplayVector(AppStreamWriter out, Vector v, Connection conn) throws SQLException {
- int l = v.size();
-AppUI.out.println("SIZE="+l);
- for (int i=0;i<l;i++) {
- Object o = v.elementAt(i);
- if (o instanceof Integer) { // update count
- JDBCDisplayUtil.DisplayUpdateCount(out,((Integer)o).intValue());
- } else { // o instanceof ResultSet
- JDBCDisplayUtil.DisplayResults(out,(ResultSet)o,conn);
- ((ResultSet)o).close(); // release the result set
- }
- }
- }
- */
-
- /**
- Display a statement that takes parameters by
- stuffing it with rows from the result set and
- displaying each result each time through.
- Deal with autocommit behavior along the way.
-
- @exception SQLException thrown on db error
- @exception ijException thrown on ij error
- */
- public static void DisplayMulti(LocalizedOutput out, PreparedStatement ps,
- ResultSet rs, Connection conn) throws SQLException, ijException {
-
- boolean autoCommited = false; // mark if autocommit in place
- boolean exec = false; // mark the first time through
- boolean anotherUsingRow = false; // remember if there's another row
- // from using.
- ResultSetMetaData rsmd = rs.getMetaData();
- int numCols = rsmd.getColumnCount();
-
- /* NOTE: We need to close the USING RS first
- * so that RunTimeStatistic gets info from
- * the user query.
- */
- anotherUsingRow = rs.next();
-
- while (! autoCommited && anotherUsingRow) {
- // note the first time through
- if (!exec) {
- exec = true;
-
- // send a warning if additional results may be lost
- if (conn.getAutoCommit()) {
- out.println(LocalizedResource.getMessage("IJ_IjWarniAutocMayCloseUsingResulSet"));
- autoCommited = true;
- }
- }
-
- // We need to make sure we pass along the scale, because
- // setObject assumes a scale of zero (beetle 4365)
- for (int c=1; c<=numCols; c++) {
- ps.setObject(c,rs.getObject(c),
- rsmd.getColumnType(c),
- rsmd.getScale(c));
- }
-
-
- // Advance in the USING RS
- anotherUsingRow = rs.next();
- // Close the USING RS when exhausted and appropriate
- // NOTE: Close before the user query
- if (! anotherUsingRow || conn.getAutoCommit()) //if no more rows or if auto commit is on, close the resultset
- {
- rs.close();
- }
-
- /*
- 4. execute the statement against those parameters
- */
-
- ps.execute();
- JDBCDisplayUtil.DisplayResults(out,ps,conn);
-
- /*
- 5. clear the parameters
- */
- ps.clearParameters();
- }
- if (!exec) {
- rs.close(); //this means, using clause didn't qualify any rows. Just close the resultset associated with using clause
- throw ijException.noUsingResults();
- }
- // REMIND: any way to look for more rsUsing rows if autoCommit?
- // perhaps just document the behavior...
- }
-
- public static final String getSystemProperty(String propertyName) {
- try
- {
- if (propertyName.startsWith("ij.") || propertyName.startsWith("derby."))
- {
- util u = new util();
- u.key = propertyName;
- return (String) java.security.AccessController.doPrivileged(u);
- }
- else
- {
- return System.getProperty(propertyName);
- }
- } catch (SecurityException se) {
- return null;
- }
- }
-
- private String key;
-
- public final Object run() {
- return System.getProperty(key);
- }
- /**
- * Read a set of properties from the received input stream, strip
- * off any excess white space that exists in those property values,
- * and then add those newly-read properties to the received
- * Properties object; not explicitly removing the whitespace here can
- * lead to problems.
- *
- * This method exists because of the manner in which the jvm reads
- * properties from file--extra spaces are ignored after a _key_, but
- * if they exist at the _end_ of a property decl line (i.e. as part
- * of a _value_), they are preserved, as outlined in the Java API:
- *
- * "Any whitespace after the key is skipped; if the first non-
- * whitespace character after the key is = or :, then it is ignored
- * and any whitespace characters after it are also skipped. All
- * remaining characters on the line become part of the associated
- * element string."
- *
- * @param iStr: An input stream from which the new properties are to be
- * loaded (should already be initialized).
- * @param prop: A set of properties to which the properties from
- * iStr will be added (should already be initialized).
- * @return A final properties set consisting of 'prop' plus all
- * properties loaded from 'iStr' (with the extra whitespace (if any)
- * removed from all values), will be returned via the parameter.
- *
- Copied here to avoid dependency on an engine class.
- **/
- private static void loadWithTrimmedValues(InputStream iStr,
- Properties prop) throws IOException {
-
- // load the properties from the received input stream.
- Properties p = new Properties();
- p.load(iStr);
-
- // Now, trim off any excess whitespace, if any, and then
- // add the properties from file to the received Properties
- // set.
- for (java.util.Enumeration propKeys = p.propertyNames();
- propKeys.hasMoreElements();) {
- // get the value, trim off the whitespace, then store it
- // in the received properties object.
- String tmpKey = (String)propKeys.nextElement();
- String tmpValue = p.getProperty(tmpKey);
- tmpValue = tmpValue.trim();
- prop.put(tmpKey, tmpValue);
- }
-
- return;
-
- }
-
- private static final String[][] protocolDrivers =
- {
- { "jdbc:derby:net:", "com.ibm.db2.jcc.DB2Driver"},
- { "jdbc:derby:", "org.apache.derby.jdbc.EmbeddedDriver" },
- };
-
- /**
- Find the appropriate driver and load it, given a JDBC URL.
- No action if no driver known for a given URL.
-
- @param jdbcProtocol the protocol to try.
-
- @exception ClassNotFoundException if unable to
- locate class for driver.
- @exception InstantiationException if unable to
- create an instance.
- @exception IllegalAccessException if driver class constructor not visible.
- */
- public static void loadDriverIfKnown(String jdbcProtocol) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
- for (int i=0; i < protocolDrivers.length; i++) {
- if (jdbcProtocol.startsWith(protocolDrivers[i][0])) {
- loadDriver(protocolDrivers[i][1]);
- break; // only want the first one
- }
- }
- }
-
- /**
- Load a driver given a class name.
-
- @exception ClassNotFoundException if unable to
- locate class for driver.
- @exception InstantiationException if unable to
- create an instance.
- @exception IllegalAccessException if driver class constructor not visible.
- */
- public static void loadDriver(String driverClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
- Class.forName(driverClass).newInstance();
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.tools.JDBCDisplayUtil;
+import org.apache.derby.iapi.tools.i18n.*;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Types;
+
+import java.util.Properties;
+import java.util.Vector;
+import java.util.Stack;
+import java.math.BigDecimal;
+
+/**
+ Methods used to control setup for apps as
+ well as display some internal ij structures.
+
+ @see org.apache.derby.tools.JDBCDisplayUtil
+ @author ames
+ */
+public class util implements java.security.PrivilegedAction {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ private util() {}
+
+ //-----------------------------------------------------------------
+ // Methods for starting up JBMS
+
+ /**
+ * Find the argument that follows the specified parameter.
+ *
+ * @param param the parameter (e.g. "-p")
+ * @param args the argument list to consider.
+ *
+ * @return the argument that follows the parameter, or null if not found
+ */
+ static public String getArg(String param, String[] args)
+ {
+ int pLocn;
+ Properties p;
+
+ if (args == null) return null;
+
+ for (pLocn=0; pLocn<args.length; pLocn++) {
+ if (param.equals(args[pLocn])) break;
+ }
+ if (pLocn >= (args.length-1)) // not found or no file
+ return null;
+
+ return args[pLocn+1];
+ }
+
+ /**
+ ij is started with "-p[r] file OtherArgs";
+ the file contains properties to control the driver and database
+ used to run ij, and can provide additional system properties.
+ <p>
+ getPropertyArg will look at the args and take out a "-p <file>" pair,
+ reading the file into the system properties.
+ <p>
+ If there was a -p without a following <file>, no action is taken.
+
+ @exception IOException thrown if file not found
+
+ @param args the argument list to consider.
+ @return true if a property item was found and loaded.
+ */
+ static public boolean getPropertyArg(String[] args) throws IOException {
+ String n;
+ InputStream in1;
+ Properties p;
+
+ if ((n = getArg("-p", args))!= null){
+ in1 = new FileInputStream(n);
+ in1 = new BufferedInputStream(in1);
+ }
+ else if ((n = getArg("-pr", args)) != null) {
+ in1 = getResourceAsStream(n);
+ if (in1 == null) throw ijException.resourceNotFound();
+ }
+ else
+ return false;
+
+ p = System.getProperties();
+
+ // Trim off excess whitespace in property file, if any, and
+ // then load those properties into 'p'.
+ util.loadWithTrimmedValues(in1, p);
+
+ return true;
+ }
+
+ /**
+ ij is started with "-ca[r] file OtherArgs";
+ the file contains connection attibute properties
+ to pass to getConnection
+ <p>
+ getConnAttributeArg will look at the args and take out a
+ "-ca[r] <file>" pair and returning the Properties
+ <p>
+
+ @exception IOException thrown if file not found
+
+ @param args the argument list to consider.
+ @return properties in the file
+ */
+ static public Properties getConnAttributeArg(String[] args)
+ throws IOException
+ {
+ String n;
+ InputStream in1;
+ Properties p = new Properties();
+
+ if ((n = getArg("-ca", args))!= null){
+ in1 = new FileInputStream(n);
+ in1 = new BufferedInputStream(in1);
+ }
+ else if ((n = getArg("-car", args)) != null) {
+ in1 = getResourceAsStream(n);
+ if (in1 == null) throw ijException.resourceNotFound();
+ }
+ else
+ return null;
+
+ // Trim off excess whitespace in property file, if any, and
+ // then load those properties into 'p'.
+ util.loadWithTrimmedValues(in1, p);
+
+ return p;
+ }
+
+
+
+ /**
+ Convenience routine to qualify a resource name with "ij.defaultPackageName"
+ if it is not qualified (does not begin with a "/").
+
+ @param absolute true means return null if the name is not absolute and false
+ means return partial names.
+ */
+ static String qualifyResourceName(String resourceName, boolean absolute)
+ {
+ resourceName=resourceName.trim();
+ if (resourceName.startsWith("/"))
+ {
+ return resourceName;
+ }
+ else
+ {
+ String pName = util.getSystemProperty("ij.defaultResourcePackage").trim();
+ if (pName == null) return null;
+ if ((pName).endsWith("/"))
+ resourceName = pName+resourceName;
+ else
+ resourceName = pName+"/"+resourceName;
+ if (absolute && !resourceName.startsWith("/"))
+ return null;
+ else
+ return resourceName;
+ }
+ }
+ /**
+ Convenience routine to get a resource as a BufferedInputStream. If the
+ resourceName is not absolute (does not begin with a "/") this qualifies
+ the name with the "ij.defaultResourcePackage" name.
+
+ @param String the name of the resource
+ @return a buffered stream for the resource if it exists and null otherwise.
+ */
+ static public InputStream getResourceAsStream(String resourceName)
+ {
+ Class c= util.class;
+ resourceName = qualifyResourceName(resourceName,true);
+ if (resourceName == null)
+ return null;
+ InputStream is = c.getResourceAsStream(resourceName);
+ if (is != null)
+ is = new BufferedInputStream(is, utilMain.BUFFEREDFILESIZE);
+ return is;
+ }
+
+ /**
+ Return the name of the ij command file or null if none is
+ specified. The command file may be proceeded with -f flag on
+ the command line. Alternatively, the command file may be
+ specified without a -f flag. In this case we assume the first
+ unknown argument is the command file.
+
+ <P>
+ This should only be called after calling invalidArgs.
+
+ <p>
+ If there is no such argument, a null is returned.
+
+ @param args the argument list to consider.
+ @return the name of the first argument not preceded by "-p",
+ null if none found.
+
+ @exception IOException thrown if file not found
+ */
+ static public String getFileArg(String[] args) throws IOException {
+ String fileName;
+ int fLocn;
+ boolean foundP = false;
+
+ if (args == null) return null;
+ if ((fileName=getArg("-f",args))!=null) return fileName;
+ //
+ //The first unknown arg is the file
+ for (int ix=0; ix < args.length; ix++)
+ if(args[ix].equals("-f") ||
+ args[ix].equals("-fr") ||
+ args[ix].equals("-ca") ||
+ args[ix].equals("-car") ||
+ args[ix].equals("-p") ||
+ args[ix].equals("-pr"))
+ ix++; //skip the parameter to these args
+ else
+ return args[ix];
+ return null;
+ }
+
+ /**
+ Return the name of a resource containing input commands or
+ null iff none has been specified.
+ */
+ static public String getInputResourceNameArg(String[] args) {
+ return getArg("-fr", args);
+ }
+
+ /**
+ Verify the ij line arguments command arguments.
+ @return true if the args are invalid
+ <UL>
+ <LI>Only legal argument provided.
+ <LI>Only specify a quantity once.
+ </UL>
+ */
+ static public boolean invalidArgs(String[] args, boolean gotProp, String file,
+ String inputResourceName) {
+ int countSupported = 0;
+ boolean haveInput = false;
+ for (int ix=0; ix < args.length; ix++)
+ {
+ //
+ //If the arguemnt is a supported flag skip the flags argument
+ if(!haveInput && (args[ix].equals("-f") || args[ix].equals("-fr")))
+ {
+ haveInput = true;
+ ix++;
+ if (ix >= args.length) return true;
+ }
+
+ else if ((args[ix].equals("-p") || args[ix].equals("-pr") ||
+ args[ix].equals("-ca") || args[ix].equals("-car") ))
+ {
+ // next arg is the file/resource name
+ ix++;
+ if (ix >= args.length) return true;
+ }
+
+
+ //
+ //Assume the first unknown arg is a file name.
+ else if (!haveInput)
+ {
+ haveInput = true;
+ }
+
+ else
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * print a usage message for invocations of main().
+ */
+ static void Usage(LocalizedOutput out) {
+ out.println(
+ LocalizedResource.getMessage("IJ_UsageJavaComCloudToolsIjPPropeInput"));
+ out.flush();
+ }
+
+
+ private static final Class[] STRING_P = { "".getClass() };
+ private static final Class[] INT_P = { Integer.TYPE };
+
+
+ static public void setupDataSource(Object ds) throws Exception {
+ // Loop over set methods on Datasource object, if there is a property
+ // then call the method with corresponding value.
+ java.lang.reflect.Method[] methods = ds.getClass().getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ java.lang.reflect.Method m = methods[i];
+ String name = m.getName();
+ if (name.startsWith("set") && (name.length() > "set".length())) {
+ String property = name.substring("set".length()); // setXyyyZwww
+ property = "ij.dataSource."+property.substring(0,1).toLowerCase(java.util.Locale.ENGLISH)+ property.substring(1); // xyyyZwww
+ String value = util.getSystemProperty(property);
+ //System.out.println("setupDateSource: method="+name+" property="+property+" value="+((value==null)?"null":value));
+ if (value != null) {
+ try {
+ // call string method
+ m.invoke(ds, new Object[] {value});
+ } catch (Throwable ignore) {
+ // failed, assume it's an integer parameter
+ m.invoke(ds, new Object[] {Integer.valueOf(value)});
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ This will look for the System properties "ij.driver" and "ij.database"
+ and return a java.sql.Connection if it successfully connects.
+ The deprecated driver and database properties are examined first.
+ <p>
+ If no connection was possible, it will return a null.
+ <p>
+ Failure to load the driver class is quietly ignored.
+
+ @param defaultDriver the driver to use if no property value found
+ @param defaultURL the database URL to use if no property value found
+ @param connInfo Connection attributes to pass to getConnection
+ @return a connection to the defaultURL if possible; null if not.
+ @exception SQLException on failure to connect.
+ @exception ClassNotFoundException on failure to load driver.
+ @exception InstantiationException on failure to load driver.
+ @exception IllegalAccessException on failure to load driver.
+ */
+ static public Connection startJBMS(String defaultDriver, String defaultURL,
+ Properties connInfo)
+ throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException
+ {
+ Connection con = null;
+ String driverName;
+ String databaseURL;
+
+ // deprecate the non-ij prefix. actually, we should defer to jdbc.drivers...
+ driverName = util.getSystemProperty("driver");
+ if (driverName == null) driverName = util.getSystemProperty("ij.driver");
+ if (driverName == null || driverName.length()==0) driverName = defaultDriver;
+ if (driverName != null) {
+ util.loadDriver(driverName);
+ }
+
+ String jdbcProtocol = util.getSystemProperty("ij.protocol");
+ if (jdbcProtocol != null)
+ util.loadDriverIfKnown(jdbcProtocol);
+
+ // deprecate the non-ij prefix name
+ databaseURL = util.getSystemProperty("database");
+ if (databaseURL == null) databaseURL = util.getSystemProperty("ij.database");
+ if (databaseURL == null || databaseURL.length()==0) databaseURL = defaultURL;
+ if (databaseURL != null) {
+ // add protocol if might help find driver.
+ boolean noDriver = false;
+ try {
+ // if have full URL, load driver for it
+ if (databaseURL.startsWith("jdbc:"))
+ util.loadDriverIfKnown(databaseURL);
+ DriverManager.getDriver(databaseURL);
+ } catch (SQLException se) {
+ noDriver = true;
+ }
+ if (noDriver && jdbcProtocol != null)
+ databaseURL = jdbcProtocol+databaseURL;
+
+ String user = util.getSystemProperty("ij.user");
+ String password = util.getSystemProperty("ij.password");
+
+ // Update connInfo for ij system properties and
+ // framework network server
+
+ connInfo = updateConnInfo(user, password,connInfo);
+
+ // JDBC driver
+ String driver = System.getProperty("driver");
+ if (driver == null) {
+ driver = "org.apache.derby.jdbc.EmbeddedDriver";
+ }
+
+ // handle datasource property
+ String dsName = System.getProperty("ij.dataSource");
+ if (dsName == null) {
+ loadDriver(driver);
+ con = DriverManager.getConnection(databaseURL,connInfo);
+ return con;
+
+ } else { // a datasource
+ // Get a new proxied connection through DataSource
+ Object ds = null; // really javax.sql.DataSource
+ try {
+ Class dc = Class.forName(dsName);
+ ds = dc.newInstance();
+
+ // set datasource properties
+ setupDataSource(ds);
+
+ // Java method call "by hand" { con = ds.getConnection(); }
+ {
+ java.lang.reflect.Method m = dc.getMethod("getConnection", null);
+ con = (java.sql.Connection) m.invoke(ds, new Object[] {});
+ }
+ } catch (Throwable error) {
+ error.printStackTrace(System.out);
+ }
+ return con;
+ } // datasource
+ }
+ // failed
+ return null;
+ }
+
+
+ public static Properties updateConnInfo(String user, String password, Properties connInfo)
+ {
+ String framework = util.getSystemProperty("framework");
+ String ijGetMessages = util.getSystemProperty("ij.retrieveMessagesFromServerOnGetMessage");
+ boolean retrieveMessages = false;
+
+
+ // For JCC make sure we set it to retrieve messages
+ if (framework != null && ((framework.equals("DB2jNet")
+ || framework.equals("DB2jcc"))))
+ retrieveMessages = true;
+
+ if (ijGetMessages != null)
+ {
+ if (ijGetMessages.equals("false"))
+ retrieveMessages = false;
+ else
+ retrieveMessages = true;
+
+ }
+
+ if (connInfo == null)
+ connInfo = new Properties();
+
+ if (retrieveMessages == true)
+ {
+ connInfo.put("retrieveMessagesFromServerOnGetMessage",
+ "true");
+ }
+ if (user != null)
+ connInfo.put("user",user);
+ if (password != null)
+ connInfo.put("password", password);
+
+ return connInfo;
+ }
+
+ /**
+ Utility interface that defaults driver and database to null.
+
+ @return a connection to the defaultURL if possible; null if not.
+ @exception SQLException on failure to connect.
+ @exception ClassNotFoundException on failure to load driver.
+ @exception InstantiationException on failure to load driver.
+ @exception IllegalAccessException on failure to load driver.
+ */
+ static public Connection startJBMS() throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
+ return startJBMS(null,null);
+ }
+
+ /**
+ Utility interface that defaults connInfo to null
+ <p>
+
+
+ @param defaultDriver the driver to use if no property value found
+ @param defaultURL the database URL to use if no property value found
+ @return a connection to the defaultURL if possible; null if not.
+ @exception SQLException on failure to connect.
+ @exception ClassNotFoundException on failure to load driver.
+ @exception InstantiationException on failure to load driver.
+ @exception IllegalAccessException on failure to load driver.
+ */
+ static public Connection startJBMS(String defaultDriver, String defaultURL)
+ throws SQLException, ClassNotFoundException, InstantiationException,
+ IllegalAccessException {
+ return startJBMS(defaultDriver,defaultURL,null);
+
+ }
+ //-----------------------------------------------------------------
+ // Methods for displaying and checking results
+ // See org.apache.derby.tools.JDBCDisplayUtil for more general displays.
+
+
+ /**
+ Display a vector of strings to the out stream.
+ */
+ public static void DisplayVector(LocalizedOutput out, Vector v) {
+ int l = v.size();
+ for (int i=0;i<l;i++)
+ out.println(v.elementAt(i));
+ }
+
+ /**
+ Display a vector of statements to the out stream.
+ public static void DisplayVector(AppStreamWriter out, Vector v, Connection conn) throws SQLException {
+ int l = v.size();
+AppUI.out.println("SIZE="+l);
+ for (int i=0;i<l;i++) {
+ Object o = v.elementAt(i);
+ if (o instanceof Integer) { // update count
+ JDBCDisplayUtil.DisplayUpdateCount(out,((Integer)o).intValue());
+ } else { // o instanceof ResultSet
+ JDBCDisplayUtil.DisplayResults(out,(ResultSet)o,conn);
+ ((ResultSet)o).close(); // release the result set
+ }
+ }
+ }
+ */
+
+ /**
+ Display a statement that takes parameters by
+ stuffing it with rows from the result set and
+ displaying each result each time through.
+ Deal with autocommit behavior along the way.
+
+ @exception SQLException thrown on db error
+ @exception ijException thrown on ij error
+ */
+ public static void DisplayMulti(LocalizedOutput out, PreparedStatement ps,
+ ResultSet rs, Connection conn) throws SQLException, ijException {
+
+ boolean autoCommited = false; // mark if autocommit in place
+ boolean exec = false; // mark the first time through
+ boolean anotherUsingRow = false; // remember if there's another row
+ // from using.
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int numCols = rsmd.getColumnCount();
+
+ /* NOTE: We need to close the USING RS first
+ * so that RunTimeStatistic gets info from
+ * the user query.
+ */
+ anotherUsingRow = rs.next();
+
+ while (! autoCommited && anotherUsingRow) {
+ // note the first time through
+ if (!exec) {
+ exec = true;
+
+ // send a warning if additional results may be lost
+ if (conn.getAutoCommit()) {
+ out.println(LocalizedResource.getMessage("IJ_IjWarniAutocMayCloseUsingResulSet"));
+ autoCommited = true;
+ }
+ }
+
+ // We need to make sure we pass along the scale, because
+ // setObject assumes a scale of zero (beetle 4365)
+ for (int c=1; c<=numCols; c++) {
+ ps.setObject(c,rs.getObject(c),
+ rsmd.getColumnType(c),
+ rsmd.getScale(c));
+ }
+
+
+ // Advance in the USING RS
+ anotherUsingRow = rs.next();
+ // Close the USING RS when exhausted and appropriate
+ // NOTE: Close before the user query
+ if (! anotherUsingRow || conn.getAutoCommit()) //if no more rows or if auto commit is on, close the resultset
+ {
+ rs.close();
+ }
+
+ /*
+ 4. execute the statement against those parameters
+ */
+
+ ps.execute();
+ JDBCDisplayUtil.DisplayResults(out,ps,conn);
+
+ /*
+ 5. clear the parameters
+ */
+ ps.clearParameters();
+ }
+ if (!exec) {
+ rs.close(); //this means, using clause didn't qualify any rows. Just close the resultset associated with using clause
+ throw ijException.noUsingResults();
+ }
+ // REMIND: any way to look for more rsUsing rows if autoCommit?
+ // perhaps just document the behavior...
+ }
+
+ public static final String getSystemProperty(String propertyName) {
+ try
+ {
+ if (propertyName.startsWith("ij.") || propertyName.startsWith("derby."))
+ {
+ util u = new util();
+ u.key = propertyName;
+ return (String) java.security.AccessController.doPrivileged(u);
+ }
+ else
+ {
+ return System.getProperty(propertyName);
+ }
+ } catch (SecurityException se) {
+ return null;
+ }
+ }
+
+ private String key;
+
+ public final Object run() {
+ return System.getProperty(key);
+ }
+ /**
+ * Read a set of properties from the received input stream, strip
+ * off any excess white space that exists in those property values,
+ * and then add those newly-read properties to the received
+ * Properties object; not explicitly removing the whitespace here can
+ * lead to problems.
+ *
+ * This method exists because of the manner in which the jvm reads
+ * properties from file--extra spaces are ignored after a _key_, but
+ * if they exist at the _end_ of a property decl line (i.e. as part
+ * of a _value_), they are preserved, as outlined in the Java API:
+ *
+ * "Any whitespace after the key is skipped; if the first non-
+ * whitespace character after the key is = or :, then it is ignored
+ * and any whitespace characters after it are also skipped. All
+ * remaining characters on the line become part of the associated
+ * element string."
+ *
+ * @param iStr: An input stream from which the new properties are to be
+ * loaded (should already be initialized).
+ * @param prop: A set of properties to which the properties from
+ * iStr will be added (should already be initialized).
+ * @return A final properties set consisting of 'prop' plus all
+ * properties loaded from 'iStr' (with the extra whitespace (if any)
+ * removed from all values), will be returned via the parameter.
+ *
+ Copied here to avoid dependency on an engine class.
+ **/
+ private static void loadWithTrimmedValues(InputStream iStr,
+ Properties prop) throws IOException {
+
+ // load the properties from the received input stream.
+ Properties p = new Properties();
+ p.load(iStr);
+
+ // Now, trim off any excess whitespace, if any, and then
+ // add the properties from file to the received Properties
+ // set.
+ for (java.util.Enumeration propKeys = p.propertyNames();
+ propKeys.hasMoreElements();) {
+ // get the value, trim off the whitespace, then store it
+ // in the received properties object.
+ String tmpKey = (String)propKeys.nextElement();
+ String tmpValue = p.getProperty(tmpKey);
+ tmpValue = tmpValue.trim();
+ prop.put(tmpKey, tmpValue);
+ }
+
+ return;
+
+ }
+
+ private static final String[][] protocolDrivers =
+ {
+ { "jdbc:derby:net:", "com.ibm.db2.jcc.DB2Driver"},
+ { "jdbc:derby:", "org.apache.derby.jdbc.EmbeddedDriver" },
+ };
+
+ /**
+ Find the appropriate driver and load it, given a JDBC URL.
+ No action if no driver known for a given URL.
+
+ @param jdbcProtocol the protocol to try.
+
+ @exception ClassNotFoundException if unable to
+ locate class for driver.
+ @exception InstantiationException if unable to
+ create an instance.
+ @exception IllegalAccessException if driver class constructor not visible.
+ */
+ public static void loadDriverIfKnown(String jdbcProtocol) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ for (int i=0; i < protocolDrivers.length; i++) {
+ if (jdbcProtocol.startsWith(protocolDrivers[i][0])) {
+ loadDriver(protocolDrivers[i][1]);
+ break; // only want the first one
+ }
+ }
+ }
+
+ /**
+ Load a driver given a class name.
+
+ @exception ClassNotFoundException if unable to
+ locate class for driver.
+ @exception InstantiationException if unable to
+ create an instance.
+ @exception IllegalAccessException if driver class constructor not visible.
+ */
+ public static void loadDriver(String driverClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ Class.forName(driverClass).newInstance();
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain.java Fri Sep 24 10:33:20 2004
@@ -1,929 +1,929 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.iapi.reference.JDBC20Translation;
-import org.apache.derby.iapi.reference.JDBC30Translation;
-
-import org.apache.derby.tools.JDBCDisplayUtil;
-import org.apache.derby.iapi.tools.i18n.*;
-
-import org.apache.derby.iapi.services.info.ProductVersionHolder;
-import org.apache.derby.iapi.services.info.ProductGenusNames;
-
-import org.apache.derby.iapi.error.PublicAPI;
-import org.apache.derby.iapi.error.StandardException;
-
-import java.util.Stack;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import java.io.InputStream;
-import java.io.FileInputStream;
-import java.io.BufferedInputStream;
-import java.io.FileNotFoundException;
-import java.io.StringReader;
-import java.sql.DriverManager;
-import java.sql.Driver;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.sql.PreparedStatement;
-
-import java.lang.reflect.*;
-
-/**
- This class is utilities specific to the two ij Main's.
- This factoring enables sharing the functionality for
- single and dual connection ij runs.
-
- @author jerry
- */
-public class utilMain implements java.security.PrivilegedAction {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
-
- private static Class[] CONN_PARAM = { Integer.TYPE };
- private static Object[] CONN_ARG = { new Integer(JDBC30Translation.CLOSE_CURSORS_AT_COMMIT)};
-
- StatementFinder[] commandGrabber;
- UCode_CharStream charStream;
- ijTokenManager ijTokMgr;
- ij ijParser;
- ConnectionEnv[] connEnv;
- int currCE;
- private int numConnections;
- private boolean fileInput;
- private boolean initialFileInput;
- private boolean mtUse;
- private boolean firstRun = true;
- private LocalizedOutput out = null;
- private Properties connAttributeDefaults;
- private Hashtable ignoreErrors;
-
- protected boolean isJCC; //The driver being used is JCC
-
- /*
- In the goodness of time, this could be an ij property
- */
- public static final int BUFFEREDFILESIZE = 2048;
-
- /*
- * command can be redirected, so we stack up command
- * grabbers as needed.
- */
- Stack oldGrabbers = new Stack();
-
- LocalizedResource langUtil = LocalizedResource.getInstance();
- /**
- * Set up the test to run with 'numConnections' connections/users.
- *
- * @param numConnections The number of connections/users to test.
- */
- public utilMain(int numConnections, LocalizedOutput out)
- throws ijFatalException
- {
- this(numConnections, out, (Hashtable)null);
- }
-
- /**
- * Set up the test to run with 'numConnections' connections/users.
- *
- * @param numConnections The number of connections/users to test.
- * @param ignoreErrors A list of errors to ignore. If null,
- * all errors are printed out and nothing
- * is fatal. If non-null, if an error is
- * hit and it is in this list, it is silently
- * ignore. Otherwise, an ijFatalException is
- * thrown. ignoreErrors is used for stress
- * tests.
- */
- public utilMain(int numConnections, LocalizedOutput out, Hashtable ignoreErrors)
- throws ijFatalException
- {
- String framework_property = util.getSystemProperty("framework");
-
- if (framework_property != null)
- {
- if (framework_property.equals("DB2jNet")
- || framework_property.equals("DB2jcc"))
- isJCC = true;
- }
- /* init the parser; give it no input to start with.
- * (1 parser for entire test.)
- */
- charStream = new UCode_CharStream(
- new StringReader(" "), 1, 1);
- ijTokMgr = new ijTokenManager(charStream);
- ijParser = new ij(ijTokMgr, getUtilMain());
- this.out = out;
- this.ignoreErrors = ignoreErrors;
-
- this.numConnections = numConnections;
- /* 1 StatementFinder and ConnectionEnv per connection/user. */
- commandGrabber = new StatementFinder[numConnections];
- connEnv = new ConnectionEnv[numConnections];
-
- for (int ictr = 0; ictr < numConnections; ictr++)
- {
- commandGrabber[ictr] = new StatementFinder(langUtil.getNewInput(System.in));
- connEnv[ictr] = new ConnectionEnv(ictr, (numConnections > 1), (numConnections == 1));
- try {
- connEnv[ictr].init(out);
- } catch (SQLException s) {
- JDBCDisplayUtil.ShowException(out, s); // will continue past connect failure
- } catch (ClassNotFoundException c) {
- JDBCDisplayUtil.ShowException(out, c); // will continue past driver failure
- } catch (InstantiationException i) {
- JDBCDisplayUtil.ShowException(out, i); // will continue past driver failure
- } catch (IllegalAccessException ia) {
- JDBCDisplayUtil.ShowException(out, ia); // will continue past driver failure
- }
- }
-
- /* Start with connection/user 0 */
- currCE = 0;
- fileInput = false;
- initialFileInput = false;
- firstRun = true;
- }
-
-
- /**
- * run ij over the specified input, sending output to the
- * specified output. Any prior input and output will be lost.
- *
- * @param in source for input to ij
- * @param out sink for output from ij
- * @param connAttributeDefaults connection attributes from -ca ij arg
- */
- public void go(LocalizedInput[] in, LocalizedOutput out,
- Properties connAttributeDefaults) throws ijFatalException
- {
- boolean done = false;
-
- String command = null;
-
- this.out = out;
- this.connAttributeDefaults = connAttributeDefaults;
-
- ijParser.setConnection(connEnv[currCE], (numConnections > 1));
- fileInput = initialFileInput = (!in[currCE].isStandardInput());
-
- for (int ictr = 0; ictr < commandGrabber.length; ictr++) {
- commandGrabber[ictr].ReInit(in[ictr]);
- }
-
- if (firstRun) {
-
- // figure out which version this is
- InputStream versionStream = (InputStream) java.security.AccessController.doPrivileged(this);
-
- // figure out which version this is
- ProductVersionHolder ijVersion =
- ProductVersionHolder.getProductVersionHolderFromMyEnv(versionStream);
-
- String version;
- if (ijVersion != null)
- {
- version = "" + ijVersion.getMajorVersion() + "." +
- ijVersion.getMinorVersion();
- }
- else
- {
- version = "?";
- }
-
- out.println(langUtil.getTextMessage("IJ_IjVers30C199", version));
- for (int i=connEnv.length-1;i>=0;i--) { // print out any initial warnings...
- Connection c = connEnv[i].getConnection();
- if (c!=null) {
- JDBCDisplayUtil.ShowWarnings(out,c);
- }
- }
- firstRun = false;
-
- //check if the property is set to not show select count and set the static variable
- //accordingly.
- boolean showNoCountForSelect = Boolean.getBoolean("ij.showNoCountForSelect");
- JDBCDisplayUtil.showSelectCount = !showNoCountForSelect;
-
- //check if the property is set to not show initial connections and accordingly set the
- //static variable.
- boolean showNoConnectionsAtStart = Boolean.getBoolean("ij.showNoConnectionsAtStart");
- if (!(showNoConnectionsAtStart)) {
- try {
- ijResult result = ijParser.showConnectionsMethod(true);
- displayResult(out,result,connEnv[currCE].getConnection());
- } catch (SQLException ex) {
- handleSQLException(out,ex);
- }
- }
- }
-
- while (!ijParser.exit && !done) {
- try{
- ijParser.setConnection(connEnv[currCE], (numConnections > 1));
- } catch(Throwable t){
- //do nothing
- }
-
- connEnv[currCE].doPrompt(true, out);
- try {
- command = null;
-
- out.flush();
- command = commandGrabber[currCE].nextStatement();
-
- // if there is no next statement,
- // pop back to the top saved grabber.
- while (command == null && ! oldGrabbers.empty()) {
- // close the old input file if not System.in
- if (fileInput) commandGrabber[currCE].close();
- commandGrabber[currCE] = (StatementFinder)oldGrabbers.pop();
- if (oldGrabbers.empty())
- fileInput = initialFileInput;
- command = commandGrabber[currCE].nextStatement();
- }
-
- // if there are no grabbers left,
- // we are done.
- if (command == null && oldGrabbers.empty()) {
- done = true;
- }
- else {
- boolean elapsedTimeOn = ijParser.getElapsedTimeState();
- long beginTime = 0;
- long endTime;
-
- if (fileInput) {
- out.println(command+";");
- out.flush();
- }
-
- charStream.ReInit(new StringReader(command), 1, 1);
- ijTokMgr.ReInit(charStream);
- ijParser.ReInit(ijTokMgr);
-
- if (elapsedTimeOn) {
- beginTime = System.currentTimeMillis();
- }
-
- ijResult result = ijParser.ijStatement();
- displayResult(out,result,connEnv[currCE].getConnection());
-
- // if something went wrong, an SQLException or ijException was thrown.
- // we can keep going to the next statement on those (see catches below).
- // ijParseException means we try the SQL parser.
-
- /* Print the elapsed time if appropriate */
- if (elapsedTimeOn) {
- endTime = System.currentTimeMillis();
- out.println(langUtil.getTextMessage("IJ_ElapTime0Mil",
- langUtil.getNumberAsString(endTime - beginTime)));
- }
-
- // would like when it completes a statement
- // to see if there is stuff after the ;
- // and before the <EOL> that we will IGNORE
- // (with a warning to that effect)
- }
-
- } catch (ParseException e) {
- if (command != null) doCatch(command);
- } catch (TokenMgrError e) {
- if (command != null) doCatch(command);
- } catch (SQLException e) {
- // SQL exception occurred in ij's actions; print and continue
- // unless it is considered fatal.
- handleSQLException(out,e);
- } catch (ijException e) {
- // exception occurred in ij's actions; print and continue
- out.println(langUtil.getTextMessage("IJ_IjErro0",e.getMessage()));
- doTrace(e);
- } catch (Throwable e) {
- out.println(langUtil.getTextMessage("IJ_JavaErro0",e.toString()));
- doTrace(e);
- }
-
- /* Go to the next connection/user, if there is one */
- currCE = ++currCE % connEnv.length;
- }
-
- // we need to close all sessions when done; otherwise we have
- // a problem when a single VM runs successive IJ threads
- try {
- for (int i = 0; i < connEnv.length; i++) {
- connEnv[i].removeAllSessions();
- }
- } catch (SQLException se ) {
- handleSQLException(out,se);
- }
- // similarly must close input files
- for (int i = 0; i < numConnections; i++) {
- try {
- if (!in[i].isStandardInput() )
- in[i].close();
- } catch (Exception e ) {
- out.println(langUtil.getTextMessage("IJ_CannotCloseInFile",
- e.toString()));
- }
- }
-
- /*
- If an exit was requested, then we will be shutting down.
- */
- if (ijParser.exit || (initialFileInput && !mtUse)) {
- Driver d = null;
- try {
- d = DriverManager.getDriver("jdbc:derby:");
- } catch (Exception e) {
- d = null;
- }
- if (d!=null) { // do we have a driver running? shutdown on exit.
- try {
- DriverManager.getConnection("jdbc:derby:;shutdown=true");
- } catch (SQLException e) {
- // ignore the errors, they are expected.
- }
- }
- }
- }
-
- private void displayResult(LocalizedOutput out, ijResult result, Connection conn) throws SQLException {
- // display the result, if appropriate.
- if (result!=null) {
- if (result.isConnection()) {
- if (result.hasWarnings()) {
- JDBCDisplayUtil.ShowWarnings(out,result.getSQLWarnings());
- result.clearSQLWarnings();
- }
- } else if (result.isStatement()) {
- Statement s = result.getStatement();
- try {
- JDBCDisplayUtil.DisplayResults(out,s,connEnv[currCE].getConnection());
- } catch (SQLException se) {
- result.closeStatement();
- throw se;
- }
- result.closeStatement();
- } else if (result.isNextRowOfResultSet()) {
- ResultSet r = result.getNextRowOfResultSet();
- JDBCDisplayUtil.DisplayCurrentRow(out,r,connEnv[currCE].getConnection());
- } else if (result.isVector()) {
- util.DisplayVector(out,result.getVector());
- if (result.hasWarnings()) {
- JDBCDisplayUtil.ShowWarnings(out,result.getSQLWarnings());
- result.clearSQLWarnings();
- }
- } else if (result.isMulti()) {
- try {
- util.DisplayMulti(out,(PreparedStatement)result.getStatement(),result.getResultSet(),connEnv[currCE].getConnection());
- } catch (SQLException se) {
- result.closeStatement();
- throw se;
- }
- result.closeStatement(); // done with the statement now
- if (result.hasWarnings()) {
- JDBCDisplayUtil.ShowWarnings(out,result.getSQLWarnings());
- result.clearSQLWarnings();
- }
- } else if (result.isException()) {
- JDBCDisplayUtil.ShowException(out,result.getException());
- }
- }
- }
-
- /**
- * catch processing on failed commands. This really ought to
- * be in ij somehow, but it was easier to catch in Main.
- */
- private void doCatch(String command) {
- // this retries the failed statement
- // as a JSQL statement; it uses the
- // ijParser since that maintains our
- // connection and state.
-
- try {
- boolean elapsedTimeOn = ijParser.getElapsedTimeState();
- long beginTime = 0;
- long endTime;
-
- if (elapsedTimeOn) {
- beginTime = System.currentTimeMillis();
- }
-
- ijResult result = ijParser.executeImmediate(command);
- displayResult(out,result,connEnv[currCE].getConnection());
-
- /* Print the elapsed time if appropriate */
- if (elapsedTimeOn) {
- endTime = System.currentTimeMillis();
- out.println(langUtil.getTextMessage("IJ_ElapTime0Mil_4",
- langUtil.getNumberAsString(endTime - beginTime)));
- }
-
- } catch (SQLException e) {
- // SQL exception occurred in ij's actions; print and continue
- // unless it is considered fatal.
- handleSQLException(out,e);
- } catch (ijException i) {
- out.println(langUtil.getTextMessage("IJ_IjErro0_5", i.getMessage()));
- doTrace(i);
- } catch (ijTokenException ie) {
- out.println(langUtil.getTextMessage("IJ_IjErro0_6", ie.getMessage()));
- doTrace(ie);
- } catch (Throwable t) {
- out.println(langUtil.getTextMessage("IJ_JavaErro0_7", t.toString()));
- doTrace(t);
- }
- }
-
- /**
- * This routine displays SQL exceptions and decides whether they
- * are fatal or not, based on the ignoreErrors field. If they
- * are fatal, an ijFatalException is thrown.
- * Lifted from ij/util.java:ShowSQLException
- */
- public void handleSQLException(LocalizedOutput out, SQLException e)
- throws ijFatalException
- {
- String errorCode;
- String sqlState = null;
- SQLException fatalException = null;
-
- if (Boolean.getBoolean("ij.showErrorCode")) {
- errorCode = langUtil.getTextMessage("IJ_Erro0",
- langUtil.getNumberAsString(e.getErrorCode()));
- }
- else {
- errorCode = "";
- }
-
- for (; e!=null; e=e.getNextException())
- {
- /*
- ** If we are to throw errors, then throw the exceptions
- ** that aren't in the ignoreErrors list. If
- ** the ignoreErrors list is null we don't throw
- ** any errors.
- */
- if (ignoreErrors != null)
- {
- sqlState = e.getSQLState();
- if ((sqlState != null) &&
- (ignoreErrors.get(sqlState) != null))
- {
- continue;
- }
- else
- {
- fatalException = e;
- }
- }
-
- String st1 = JDBCDisplayUtil.mapNull(e.getSQLState(),langUtil.getTextMessage("IJ_NoSqls"));
- String st2 = JDBCDisplayUtil.mapNull(e.getMessage(),langUtil.getTextMessage("IJ_NoMess"));
- out.println(langUtil.getTextMessage("IJ_Erro012", st1, st2, errorCode));
- JDBCDisplayUtil.doTrace(out, e);
- }
- if (fatalException != null)
- {
- throw new ijFatalException(fatalException);
- }
- }
-
- /**
- * stack trace dumper
- */
- private void doTrace(Throwable t) {
- if (util.getSystemProperty("ij.exceptionTrace") != null) {
- t.printStackTrace(out);
- }
- out.flush();
- }
-
- void newInput(String fileName) {
- FileInputStream newFile = null;
- try {
- newFile = new FileInputStream(fileName);
- } catch (FileNotFoundException e) {
- throw ijException.fileNotFound();
- }
- if (newFile == null) return;
-
- // if the file was opened, move to use it for input.
- oldGrabbers.push(commandGrabber[currCE]);
- commandGrabber[currCE] =
- new StatementFinder(langUtil.getNewInput(new BufferedInputStream(newFile, BUFFEREDFILESIZE)));
- fileInput = true;
- }
-
- void newResourceInput(String resourceName) {
- InputStream is = util.getResourceAsStream(resourceName);
- if (is==null) throw ijException.resourceNotFound();
- oldGrabbers.push(commandGrabber[currCE]);
- commandGrabber[currCE] =
- new StatementFinder(langUtil.getNewInput(new BufferedInputStream(is, BUFFEREDFILESIZE)));
- fileInput = true;
- }
-
- /**
- * REMIND: eventually this might be part of StatementFinder,
- * used at each carriage return to show that it is still "live"
- * when it is reading multi-line input.
- */
- static void doPrompt(boolean newStatement, LocalizedOutput out, String tag)
- {
- if (newStatement) {
- out.print("ij"+(tag==null?"":tag)+"> ");
- }
- else {
- out.print("> ");
- }
- out.flush();
- }
-
- void setMtUse(boolean b) {
- mtUse = b;
- }
-
- // JDBC 2.0 support
-
- /**
- * Return the right utilMain to use. (JDBC 1.1 or 2.0)
- *
- */
- public utilMain getUtilMain()
- {
- return this;
- }
-
- /**
- * Connections by default create ResultSet objects with holdability true. This method can be used
- * to change the holdability of the connection by passing one of ResultSet.HOLD_CURSORS_OVER_COMMIT
- * or ResultSet.CLOSE_CURSORS_AT_COMMIT. We implement this using reflection in jdk13 and lower
- *
- * @param conn The connection.
- * @param holdType The new holdability for the Connection object.
- *
- * @return The connection object with holdability set to passed value.
- */
- public Connection setHoldability(Connection conn, int holdType)
- throws SQLException
- {
- //Prior to db2 compatibility work, the default holdability for connections was close cursors over commit and all the tests
- //were written based on that assumption
- //Later, as part of db2 compatibility, we changed the default holdability for connection to hold cursors over commit.
- //But in order for the existing tests to work fine, the tests needed a way to set the holdability to close cursors for connections
- //Since there is no direct jdbc api in jdk13 and lower to do that, we are using reflection to set the holdability to close cursors
- try { //for jdks prior to jdk14, need to use reflection to set holdability to false.
- Method sh = conn.getClass().getMethod("setHoldability", CONN_PARAM);
- sh.invoke(conn, CONN_ARG);
- } catch( Exception e) {
- throw PublicAPI.wrapStandardException( StandardException.plainWrapException( e));
- }
- return conn;
- }
-
- /**
- * Retrieves the current holdability of ResultSet objects created using this
- * Connection object. We implement this using reflection in jdk13 and lower
- *
- * @return The holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
- * or ResultSet.CLOSE_CURSORS_AT_COMMIT
- *
- */
- public int getHoldability(Connection conn)
- throws SQLException
- {
- //this method is used to make sure we are not trying to create a statement with holdability different than the connection holdability
- //This is because jdk13 and lower does not have support for that.
- //The holdability of connection and statement can differ if connection holdability is set to close cursor on commit using reflection
- //and statement is getting created with holdability true
- //Another instance of holdability of connection and statement not being same is when connection holdability is hold cursor
- //over commit and statement is being created with holdability false
- int defaultHoldability = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
- try {
- Method sh = conn.getClass().getMethod("getHoldability", null);
- defaultHoldability = ((Integer)sh.invoke(conn, null)).intValue();
- } catch( Exception e) {
- throw PublicAPI.wrapStandardException( StandardException.plainWrapException( e));
- }
- return defaultHoldability;
- }
-
- /**
- * Create the right kind of statement (scrolling or not)
- * off of the specified connection.
- *
- * @param conn The connection.
- * @param scrollType The scroll type of the cursor.
- *
- * @return The statement.
- */
- public Statement createStatement(Connection conn, int scrollType, int holdType)
- throws SQLException
- {
- //following if is used to make sure we are not trying to create a statement with holdability different that the connection
- //holdability. This is because jdk13 and lower does not have support for that.
- //The holdability of connection and statement can differ if connection holdability is set to close cursor on commit using reflection
- //and statement is getting created with holdability true
- //Another instance of holdability of connection and statement not being same is when connection holdability is hold cursor
- //over commit and statement is being created with holdability false
- if (holdType != getHoldability(conn))
- {
- throw ijException.holdCursorsNotSupported();
- }
-
- Statement stmt;
- try {
- stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY);
- } catch(AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- stmt = conn.createStatement();
- }
- return stmt;
- }
-
- /**
- * Position on the specified row of the specified ResultSet.
- *
- * @param rs The specified ResultSet.
- * @param row The row # to move to.
- * (Negative means from the end of the result set.)
- *
- * @return NULL.
- *
- * @exception SQLException thrown on error.
- * (absolute() not supported pre-JDBC2.0)
- */
- public ijResult absolute(ResultSet rs, int row)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- // absolute is only allowed on scroll cursors
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("ABSOLUTE");
- }
-
- // 0 is an invalid value for row
- if (row == 0)
- {
- throw ijException.zeroInvalidForAbsolute();
- }
-
- return new ijRowResult(rs, rs.absolute(row));
- }
-
- /**
- * Move the cursor position by the specified amount.
- *
- * @param rs The specified ResultSet.
- * @param row The # of rows to move.
- * (Negative means toward the beginning of the result set.)
- *
- * @return NULL.
- *
- * @exception SQLException thrown on error.
- * (relative() not supported pre-JDBC2.0)
- */
- public ijResult relative(ResultSet rs, int row)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- // relative is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("RELATIVE");
- }
-
- return new ijRowResult(rs, rs.relative(row));
- }
-
- /**
- * Position before the first row of the specified ResultSet
- * and return NULL to the user.
- *
- * @param rs The specified ResultSet.
- *
- * @return NULL.
- *
- * @exception SQLException thrown on error.
- * (beforeFirst() not supported pre-JDBC2.0)
- */
- public ijResult beforeFirst(ResultSet rs)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- // before first is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("BEFORE FIRST");
- }
-
- rs.beforeFirst();
- return new ijRowResult(rs, false);
- }
-
- /**
- * Position on the first row of the specified ResultSet
- * and return that row to the user.
- *
- * @param rs The specified ResultSet.
- *
- * @return The first row of the ResultSet.
- *
- * @exception SQLException thrown on error.
- * (first() not supported pre-JDBC2.0)
- */
- public ijResult first(ResultSet rs)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- // first is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("FIRST");
- }
-
- return new ijRowResult(rs, rs.first());
- }
-
- /**
- * Position after the last row of the specified ResultSet
- * and return NULL to the user.
- *
- * @param rs The specified ResultSet.
- *
- * @return NULL.
- *
- * @exception SQLException thrown on error.
- * (afterLast() not supported pre-JDBC2.0)
- */
- public ijResult afterLast(ResultSet rs)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- // after last is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("AFTER LAST");
- }
-
- rs.afterLast();
- return new ijRowResult(rs, false);
- }
-
- /**
- * Position on the last row of the specified ResultSet
- * and return that row to the user.
- *
- * @param rs The specified ResultSet.
- *
- * @return The last row of the ResultSet.
- *
- * @exception SQLException thrown on error.
- * (last() not supported pre-JDBC2.0)
- */
- public ijResult last(ResultSet rs)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- // last is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("LAST");
- }
-
- return new ijRowResult(rs, rs.last());
- }
-
- /**
- * Position on the previous row of the specified ResultSet
- * and return that row to the user.
- *
- * @param rs The specified ResultSet.
- *
- * @return The previous row of the ResultSet.
- *
- * @exception SQLException thrown on error.
- * (previous() not supported pre-JDBC2.0)
- */
- public ijResult previous(ResultSet rs)
- throws SQLException
- {
- boolean forwardOnly;
- try {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
- // first is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("PREVIOUS");
- }
-
- return new ijRowResult(rs, rs.previous());
- }
-
- /**
- * Get the current row number
- *
- * @param rs The specified ResultSet.
- *
- * @return The current row number
- *
- * @exception SQLException thrown on error.
- * (getRow() not supported pre-JDBC2.0)
- */
- public int getCurrentRowNumber(ResultSet rs)
- throws SQLException
- {
- boolean forwardOnly;
- try
- {
- forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
- } catch (AbstractMethodError ame)
- {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
- //to jdbc 1.x functionality
- forwardOnly = true;
- }
-
- // getCurrentRow is only allowed on scroll cursors
- if (forwardOnly)
- {
- throw ijException.forwardOnlyCursor("GETCURRENTROWNUMBER");
- }
-
- return rs.getRow();
- }
-
- public Properties getConnAttributeDefaults ()
- {
- return connAttributeDefaults;
- }
-
- public final Object run() {
- return getClass().getResourceAsStream(ProductGenusNames.TOOLS_INFO);
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1997, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.iapi.reference.JDBC20Translation;
+import org.apache.derby.iapi.reference.JDBC30Translation;
+
+import org.apache.derby.tools.JDBCDisplayUtil;
+import org.apache.derby.iapi.tools.i18n.*;
+
+import org.apache.derby.iapi.services.info.ProductVersionHolder;
+import org.apache.derby.iapi.services.info.ProductGenusNames;
+
+import org.apache.derby.iapi.error.PublicAPI;
+import org.apache.derby.iapi.error.StandardException;
+
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.StringReader;
+import java.sql.DriverManager;
+import java.sql.Driver;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+
+import java.lang.reflect.*;
+
+/**
+ This class is utilities specific to the two ij Main's.
+ This factoring enables sharing the functionality for
+ single and dual connection ij runs.
+
+ @author jerry
+ */
+public class utilMain implements java.security.PrivilegedAction {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1997_2004;
+
+ private static Class[] CONN_PARAM = { Integer.TYPE };
+ private static Object[] CONN_ARG = { new Integer(JDBC30Translation.CLOSE_CURSORS_AT_COMMIT)};
+
+ StatementFinder[] commandGrabber;
+ UCode_CharStream charStream;
+ ijTokenManager ijTokMgr;
+ ij ijParser;
+ ConnectionEnv[] connEnv;
+ int currCE;
+ private int numConnections;
+ private boolean fileInput;
+ private boolean initialFileInput;
+ private boolean mtUse;
+ private boolean firstRun = true;
+ private LocalizedOutput out = null;
+ private Properties connAttributeDefaults;
+ private Hashtable ignoreErrors;
+
+ protected boolean isJCC; //The driver being used is JCC
+
+ /*
+ In the goodness of time, this could be an ij property
+ */
+ public static final int BUFFEREDFILESIZE = 2048;
+
+ /*
+ * command can be redirected, so we stack up command
+ * grabbers as needed.
+ */
+ Stack oldGrabbers = new Stack();
+
+ LocalizedResource langUtil = LocalizedResource.getInstance();
+ /**
+ * Set up the test to run with 'numConnections' connections/users.
+ *
+ * @param numConnections The number of connections/users to test.
+ */
+ public utilMain(int numConnections, LocalizedOutput out)
+ throws ijFatalException
+ {
+ this(numConnections, out, (Hashtable)null);
+ }
+
+ /**
+ * Set up the test to run with 'numConnections' connections/users.
+ *
+ * @param numConnections The number of connections/users to test.
+ * @param ignoreErrors A list of errors to ignore. If null,
+ * all errors are printed out and nothing
+ * is fatal. If non-null, if an error is
+ * hit and it is in this list, it is silently
+ * ignore. Otherwise, an ijFatalException is
+ * thrown. ignoreErrors is used for stress
+ * tests.
+ */
+ public utilMain(int numConnections, LocalizedOutput out, Hashtable ignoreErrors)
+ throws ijFatalException
+ {
+ String framework_property = util.getSystemProperty("framework");
+
+ if (framework_property != null)
+ {
+ if (framework_property.equals("DB2jNet")
+ || framework_property.equals("DB2jcc"))
+ isJCC = true;
+ }
+ /* init the parser; give it no input to start with.
+ * (1 parser for entire test.)
+ */
+ charStream = new UCode_CharStream(
+ new StringReader(" "), 1, 1);
+ ijTokMgr = new ijTokenManager(charStream);
+ ijParser = new ij(ijTokMgr, getUtilMain());
+ this.out = out;
+ this.ignoreErrors = ignoreErrors;
+
+ this.numConnections = numConnections;
+ /* 1 StatementFinder and ConnectionEnv per connection/user. */
+ commandGrabber = new StatementFinder[numConnections];
+ connEnv = new ConnectionEnv[numConnections];
+
+ for (int ictr = 0; ictr < numConnections; ictr++)
+ {
+ commandGrabber[ictr] = new StatementFinder(langUtil.getNewInput(System.in));
+ connEnv[ictr] = new ConnectionEnv(ictr, (numConnections > 1), (numConnections == 1));
+ try {
+ connEnv[ictr].init(out);
+ } catch (SQLException s) {
+ JDBCDisplayUtil.ShowException(out, s); // will continue past connect failure
+ } catch (ClassNotFoundException c) {
+ JDBCDisplayUtil.ShowException(out, c); // will continue past driver failure
+ } catch (InstantiationException i) {
+ JDBCDisplayUtil.ShowException(out, i); // will continue past driver failure
+ } catch (IllegalAccessException ia) {
+ JDBCDisplayUtil.ShowException(out, ia); // will continue past driver failure
+ }
+ }
+
+ /* Start with connection/user 0 */
+ currCE = 0;
+ fileInput = false;
+ initialFileInput = false;
+ firstRun = true;
+ }
+
+
+ /**
+ * run ij over the specified input, sending output to the
+ * specified output. Any prior input and output will be lost.
+ *
+ * @param in source for input to ij
+ * @param out sink for output from ij
+ * @param connAttributeDefaults connection attributes from -ca ij arg
+ */
+ public void go(LocalizedInput[] in, LocalizedOutput out,
+ Properties connAttributeDefaults) throws ijFatalException
+ {
+ boolean done = false;
+
+ String command = null;
+
+ this.out = out;
+ this.connAttributeDefaults = connAttributeDefaults;
+
+ ijParser.setConnection(connEnv[currCE], (numConnections > 1));
+ fileInput = initialFileInput = (!in[currCE].isStandardInput());
+
+ for (int ictr = 0; ictr < commandGrabber.length; ictr++) {
+ commandGrabber[ictr].ReInit(in[ictr]);
+ }
+
+ if (firstRun) {
+
+ // figure out which version this is
+ InputStream versionStream = (InputStream) java.security.AccessController.doPrivileged(this);
+
+ // figure out which version this is
+ ProductVersionHolder ijVersion =
+ ProductVersionHolder.getProductVersionHolderFromMyEnv(versionStream);
+
+ String version;
+ if (ijVersion != null)
+ {
+ version = "" + ijVersion.getMajorVersion() + "." +
+ ijVersion.getMinorVersion();
+ }
+ else
+ {
+ version = "?";
+ }
+
+ out.println(langUtil.getTextMessage("IJ_IjVers30C199", version));
+ for (int i=connEnv.length-1;i>=0;i--) { // print out any initial warnings...
+ Connection c = connEnv[i].getConnection();
+ if (c!=null) {
+ JDBCDisplayUtil.ShowWarnings(out,c);
+ }
+ }
+ firstRun = false;
+
+ //check if the property is set to not show select count and set the static variable
+ //accordingly.
+ boolean showNoCountForSelect = Boolean.getBoolean("ij.showNoCountForSelect");
+ JDBCDisplayUtil.showSelectCount = !showNoCountForSelect;
+
+ //check if the property is set to not show initial connections and accordingly set the
+ //static variable.
+ boolean showNoConnectionsAtStart = Boolean.getBoolean("ij.showNoConnectionsAtStart");
+ if (!(showNoConnectionsAtStart)) {
+ try {
+ ijResult result = ijParser.showConnectionsMethod(true);
+ displayResult(out,result,connEnv[currCE].getConnection());
+ } catch (SQLException ex) {
+ handleSQLException(out,ex);
+ }
+ }
+ }
+
+ while (!ijParser.exit && !done) {
+ try{
+ ijParser.setConnection(connEnv[currCE], (numConnections > 1));
+ } catch(Throwable t){
+ //do nothing
+ }
+
+ connEnv[currCE].doPrompt(true, out);
+ try {
+ command = null;
+
+ out.flush();
+ command = commandGrabber[currCE].nextStatement();
+
+ // if there is no next statement,
+ // pop back to the top saved grabber.
+ while (command == null && ! oldGrabbers.empty()) {
+ // close the old input file if not System.in
+ if (fileInput) commandGrabber[currCE].close();
+ commandGrabber[currCE] = (StatementFinder)oldGrabbers.pop();
+ if (oldGrabbers.empty())
+ fileInput = initialFileInput;
+ command = commandGrabber[currCE].nextStatement();
+ }
+
+ // if there are no grabbers left,
+ // we are done.
+ if (command == null && oldGrabbers.empty()) {
+ done = true;
+ }
+ else {
+ boolean elapsedTimeOn = ijParser.getElapsedTimeState();
+ long beginTime = 0;
+ long endTime;
+
+ if (fileInput) {
+ out.println(command+";");
+ out.flush();
+ }
+
+ charStream.ReInit(new StringReader(command), 1, 1);
+ ijTokMgr.ReInit(charStream);
+ ijParser.ReInit(ijTokMgr);
+
+ if (elapsedTimeOn) {
+ beginTime = System.currentTimeMillis();
+ }
+
+ ijResult result = ijParser.ijStatement();
+ displayResult(out,result,connEnv[currCE].getConnection());
+
+ // if something went wrong, an SQLException or ijException was thrown.
+ // we can keep going to the next statement on those (see catches below).
+ // ijParseException means we try the SQL parser.
+
+ /* Print the elapsed time if appropriate */
+ if (elapsedTimeOn) {
+ endTime = System.currentTimeMillis();
+ out.println(langUtil.getTextMessage("IJ_ElapTime0Mil",
+ langUtil.getNumberAsString(endTime - beginTime)));
+ }
+
+ // would like when it completes a statement
+ // to see if there is stuff after the ;
+ // and before the <EOL> that we will IGNORE
+ // (with a warning to that effect)
+ }
+
+ } catch (ParseException e) {
+ if (command != null) doCatch(command);
+ } catch (TokenMgrError e) {
+ if (command != null) doCatch(command);
+ } catch (SQLException e) {
+ // SQL exception occurred in ij's actions; print and continue
+ // unless it is considered fatal.
+ handleSQLException(out,e);
+ } catch (ijException e) {
+ // exception occurred in ij's actions; print and continue
+ out.println(langUtil.getTextMessage("IJ_IjErro0",e.getMessage()));
+ doTrace(e);
+ } catch (Throwable e) {
+ out.println(langUtil.getTextMessage("IJ_JavaErro0",e.toString()));
+ doTrace(e);
+ }
+
+ /* Go to the next connection/user, if there is one */
+ currCE = ++currCE % connEnv.length;
+ }
+
+ // we need to close all sessions when done; otherwise we have
+ // a problem when a single VM runs successive IJ threads
+ try {
+ for (int i = 0; i < connEnv.length; i++) {
+ connEnv[i].removeAllSessions();
+ }
+ } catch (SQLException se ) {
+ handleSQLException(out,se);
+ }
+ // similarly must close input files
+ for (int i = 0; i < numConnections; i++) {
+ try {
+ if (!in[i].isStandardInput() )
+ in[i].close();
+ } catch (Exception e ) {
+ out.println(langUtil.getTextMessage("IJ_CannotCloseInFile",
+ e.toString()));
+ }
+ }
+
+ /*
+ If an exit was requested, then we will be shutting down.
+ */
+ if (ijParser.exit || (initialFileInput && !mtUse)) {
+ Driver d = null;
+ try {
+ d = DriverManager.getDriver("jdbc:derby:");
+ } catch (Exception e) {
+ d = null;
+ }
+ if (d!=null) { // do we have a driver running? shutdown on exit.
+ try {
+ DriverManager.getConnection("jdbc:derby:;shutdown=true");
+ } catch (SQLException e) {
+ // ignore the errors, they are expected.
+ }
+ }
+ }
+ }
+
+ private void displayResult(LocalizedOutput out, ijResult result, Connection conn) throws SQLException {
+ // display the result, if appropriate.
+ if (result!=null) {
+ if (result.isConnection()) {
+ if (result.hasWarnings()) {
+ JDBCDisplayUtil.ShowWarnings(out,result.getSQLWarnings());
+ result.clearSQLWarnings();
+ }
+ } else if (result.isStatement()) {
+ Statement s = result.getStatement();
+ try {
+ JDBCDisplayUtil.DisplayResults(out,s,connEnv[currCE].getConnection());
+ } catch (SQLException se) {
+ result.closeStatement();
+ throw se;
+ }
+ result.closeStatement();
+ } else if (result.isNextRowOfResultSet()) {
+ ResultSet r = result.getNextRowOfResultSet();
+ JDBCDisplayUtil.DisplayCurrentRow(out,r,connEnv[currCE].getConnection());
+ } else if (result.isVector()) {
+ util.DisplayVector(out,result.getVector());
+ if (result.hasWarnings()) {
+ JDBCDisplayUtil.ShowWarnings(out,result.getSQLWarnings());
+ result.clearSQLWarnings();
+ }
+ } else if (result.isMulti()) {
+ try {
+ util.DisplayMulti(out,(PreparedStatement)result.getStatement(),result.getResultSet(),connEnv[currCE].getConnection());
+ } catch (SQLException se) {
+ result.closeStatement();
+ throw se;
+ }
+ result.closeStatement(); // done with the statement now
+ if (result.hasWarnings()) {
+ JDBCDisplayUtil.ShowWarnings(out,result.getSQLWarnings());
+ result.clearSQLWarnings();
+ }
+ } else if (result.isException()) {
+ JDBCDisplayUtil.ShowException(out,result.getException());
+ }
+ }
+ }
+
+ /**
+ * catch processing on failed commands. This really ought to
+ * be in ij somehow, but it was easier to catch in Main.
+ */
+ private void doCatch(String command) {
+ // this retries the failed statement
+ // as a JSQL statement; it uses the
+ // ijParser since that maintains our
+ // connection and state.
+
+ try {
+ boolean elapsedTimeOn = ijParser.getElapsedTimeState();
+ long beginTime = 0;
+ long endTime;
+
+ if (elapsedTimeOn) {
+ beginTime = System.currentTimeMillis();
+ }
+
+ ijResult result = ijParser.executeImmediate(command);
+ displayResult(out,result,connEnv[currCE].getConnection());
+
+ /* Print the elapsed time if appropriate */
+ if (elapsedTimeOn) {
+ endTime = System.currentTimeMillis();
+ out.println(langUtil.getTextMessage("IJ_ElapTime0Mil_4",
+ langUtil.getNumberAsString(endTime - beginTime)));
+ }
+
+ } catch (SQLException e) {
+ // SQL exception occurred in ij's actions; print and continue
+ // unless it is considered fatal.
+ handleSQLException(out,e);
+ } catch (ijException i) {
+ out.println(langUtil.getTextMessage("IJ_IjErro0_5", i.getMessage()));
+ doTrace(i);
+ } catch (ijTokenException ie) {
+ out.println(langUtil.getTextMessage("IJ_IjErro0_6", ie.getMessage()));
+ doTrace(ie);
+ } catch (Throwable t) {
+ out.println(langUtil.getTextMessage("IJ_JavaErro0_7", t.toString()));
+ doTrace(t);
+ }
+ }
+
+ /**
+ * This routine displays SQL exceptions and decides whether they
+ * are fatal or not, based on the ignoreErrors field. If they
+ * are fatal, an ijFatalException is thrown.
+ * Lifted from ij/util.java:ShowSQLException
+ */
+ public void handleSQLException(LocalizedOutput out, SQLException e)
+ throws ijFatalException
+ {
+ String errorCode;
+ String sqlState = null;
+ SQLException fatalException = null;
+
+ if (Boolean.getBoolean("ij.showErrorCode")) {
+ errorCode = langUtil.getTextMessage("IJ_Erro0",
+ langUtil.getNumberAsString(e.getErrorCode()));
+ }
+ else {
+ errorCode = "";
+ }
+
+ for (; e!=null; e=e.getNextException())
+ {
+ /*
+ ** If we are to throw errors, then throw the exceptions
+ ** that aren't in the ignoreErrors list. If
+ ** the ignoreErrors list is null we don't throw
+ ** any errors.
+ */
+ if (ignoreErrors != null)
+ {
+ sqlState = e.getSQLState();
+ if ((sqlState != null) &&
+ (ignoreErrors.get(sqlState) != null))
+ {
+ continue;
+ }
+ else
+ {
+ fatalException = e;
+ }
+ }
+
+ String st1 = JDBCDisplayUtil.mapNull(e.getSQLState(),langUtil.getTextMessage("IJ_NoSqls"));
+ String st2 = JDBCDisplayUtil.mapNull(e.getMessage(),langUtil.getTextMessage("IJ_NoMess"));
+ out.println(langUtil.getTextMessage("IJ_Erro012", st1, st2, errorCode));
+ JDBCDisplayUtil.doTrace(out, e);
+ }
+ if (fatalException != null)
+ {
+ throw new ijFatalException(fatalException);
+ }
+ }
+
+ /**
+ * stack trace dumper
+ */
+ private void doTrace(Throwable t) {
+ if (util.getSystemProperty("ij.exceptionTrace") != null) {
+ t.printStackTrace(out);
+ }
+ out.flush();
+ }
+
+ void newInput(String fileName) {
+ FileInputStream newFile = null;
+ try {
+ newFile = new FileInputStream(fileName);
+ } catch (FileNotFoundException e) {
+ throw ijException.fileNotFound();
+ }
+ if (newFile == null) return;
+
+ // if the file was opened, move to use it for input.
+ oldGrabbers.push(commandGrabber[currCE]);
+ commandGrabber[currCE] =
+ new StatementFinder(langUtil.getNewInput(new BufferedInputStream(newFile, BUFFEREDFILESIZE)));
+ fileInput = true;
+ }
+
+ void newResourceInput(String resourceName) {
+ InputStream is = util.getResourceAsStream(resourceName);
+ if (is==null) throw ijException.resourceNotFound();
+ oldGrabbers.push(commandGrabber[currCE]);
+ commandGrabber[currCE] =
+ new StatementFinder(langUtil.getNewInput(new BufferedInputStream(is, BUFFEREDFILESIZE)));
+ fileInput = true;
+ }
+
+ /**
+ * REMIND: eventually this might be part of StatementFinder,
+ * used at each carriage return to show that it is still "live"
+ * when it is reading multi-line input.
+ */
+ static void doPrompt(boolean newStatement, LocalizedOutput out, String tag)
+ {
+ if (newStatement) {
+ out.print("ij"+(tag==null?"":tag)+"> ");
+ }
+ else {
+ out.print("> ");
+ }
+ out.flush();
+ }
+
+ void setMtUse(boolean b) {
+ mtUse = b;
+ }
+
+ // JDBC 2.0 support
+
+ /**
+ * Return the right utilMain to use. (JDBC 1.1 or 2.0)
+ *
+ */
+ public utilMain getUtilMain()
+ {
+ return this;
+ }
+
+ /**
+ * Connections by default create ResultSet objects with holdability true. This method can be used
+ * to change the holdability of the connection by passing one of ResultSet.HOLD_CURSORS_OVER_COMMIT
+ * or ResultSet.CLOSE_CURSORS_AT_COMMIT. We implement this using reflection in jdk13 and lower
+ *
+ * @param conn The connection.
+ * @param holdType The new holdability for the Connection object.
+ *
+ * @return The connection object with holdability set to passed value.
+ */
+ public Connection setHoldability(Connection conn, int holdType)
+ throws SQLException
+ {
+ //Prior to db2 compatibility work, the default holdability for connections was close cursors over commit and all the tests
+ //were written based on that assumption
+ //Later, as part of db2 compatibility, we changed the default holdability for connection to hold cursors over commit.
+ //But in order for the existing tests to work fine, the tests needed a way to set the holdability to close cursors for connections
+ //Since there is no direct jdbc api in jdk13 and lower to do that, we are using reflection to set the holdability to close cursors
+ try { //for jdks prior to jdk14, need to use reflection to set holdability to false.
+ Method sh = conn.getClass().getMethod("setHoldability", CONN_PARAM);
+ sh.invoke(conn, CONN_ARG);
+ } catch( Exception e) {
+ throw PublicAPI.wrapStandardException( StandardException.plainWrapException( e));
+ }
+ return conn;
+ }
+
+ /**
+ * Retrieves the current holdability of ResultSet objects created using this
+ * Connection object. We implement this using reflection in jdk13 and lower
+ *
+ * @return The holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
+ * or ResultSet.CLOSE_CURSORS_AT_COMMIT
+ *
+ */
+ public int getHoldability(Connection conn)
+ throws SQLException
+ {
+ //this method is used to make sure we are not trying to create a statement with holdability different than the connection holdability
+ //This is because jdk13 and lower does not have support for that.
+ //The holdability of connection and statement can differ if connection holdability is set to close cursor on commit using reflection
+ //and statement is getting created with holdability true
+ //Another instance of holdability of connection and statement not being same is when connection holdability is hold cursor
+ //over commit and statement is being created with holdability false
+ int defaultHoldability = JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
+ try {
+ Method sh = conn.getClass().getMethod("getHoldability", null);
+ defaultHoldability = ((Integer)sh.invoke(conn, null)).intValue();
+ } catch( Exception e) {
+ throw PublicAPI.wrapStandardException( StandardException.plainWrapException( e));
+ }
+ return defaultHoldability;
+ }
+
+ /**
+ * Create the right kind of statement (scrolling or not)
+ * off of the specified connection.
+ *
+ * @param conn The connection.
+ * @param scrollType The scroll type of the cursor.
+ *
+ * @return The statement.
+ */
+ public Statement createStatement(Connection conn, int scrollType, int holdType)
+ throws SQLException
+ {
+ //following if is used to make sure we are not trying to create a statement with holdability different that the connection
+ //holdability. This is because jdk13 and lower does not have support for that.
+ //The holdability of connection and statement can differ if connection holdability is set to close cursor on commit using reflection
+ //and statement is getting created with holdability true
+ //Another instance of holdability of connection and statement not being same is when connection holdability is hold cursor
+ //over commit and statement is being created with holdability false
+ if (holdType != getHoldability(conn))
+ {
+ throw ijException.holdCursorsNotSupported();
+ }
+
+ Statement stmt;
+ try {
+ stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY);
+ } catch(AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ stmt = conn.createStatement();
+ }
+ return stmt;
+ }
+
+ /**
+ * Position on the specified row of the specified ResultSet.
+ *
+ * @param rs The specified ResultSet.
+ * @param row The row # to move to.
+ * (Negative means from the end of the result set.)
+ *
+ * @return NULL.
+ *
+ * @exception SQLException thrown on error.
+ * (absolute() not supported pre-JDBC2.0)
+ */
+ public ijResult absolute(ResultSet rs, int row)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ // absolute is only allowed on scroll cursors
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("ABSOLUTE");
+ }
+
+ // 0 is an invalid value for row
+ if (row == 0)
+ {
+ throw ijException.zeroInvalidForAbsolute();
+ }
+
+ return new ijRowResult(rs, rs.absolute(row));
+ }
+
+ /**
+ * Move the cursor position by the specified amount.
+ *
+ * @param rs The specified ResultSet.
+ * @param row The # of rows to move.
+ * (Negative means toward the beginning of the result set.)
+ *
+ * @return NULL.
+ *
+ * @exception SQLException thrown on error.
+ * (relative() not supported pre-JDBC2.0)
+ */
+ public ijResult relative(ResultSet rs, int row)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ // relative is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("RELATIVE");
+ }
+
+ return new ijRowResult(rs, rs.relative(row));
+ }
+
+ /**
+ * Position before the first row of the specified ResultSet
+ * and return NULL to the user.
+ *
+ * @param rs The specified ResultSet.
+ *
+ * @return NULL.
+ *
+ * @exception SQLException thrown on error.
+ * (beforeFirst() not supported pre-JDBC2.0)
+ */
+ public ijResult beforeFirst(ResultSet rs)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ // before first is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("BEFORE FIRST");
+ }
+
+ rs.beforeFirst();
+ return new ijRowResult(rs, false);
+ }
+
+ /**
+ * Position on the first row of the specified ResultSet
+ * and return that row to the user.
+ *
+ * @param rs The specified ResultSet.
+ *
+ * @return The first row of the ResultSet.
+ *
+ * @exception SQLException thrown on error.
+ * (first() not supported pre-JDBC2.0)
+ */
+ public ijResult first(ResultSet rs)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ // first is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("FIRST");
+ }
+
+ return new ijRowResult(rs, rs.first());
+ }
+
+ /**
+ * Position after the last row of the specified ResultSet
+ * and return NULL to the user.
+ *
+ * @param rs The specified ResultSet.
+ *
+ * @return NULL.
+ *
+ * @exception SQLException thrown on error.
+ * (afterLast() not supported pre-JDBC2.0)
+ */
+ public ijResult afterLast(ResultSet rs)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ // after last is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("AFTER LAST");
+ }
+
+ rs.afterLast();
+ return new ijRowResult(rs, false);
+ }
+
+ /**
+ * Position on the last row of the specified ResultSet
+ * and return that row to the user.
+ *
+ * @param rs The specified ResultSet.
+ *
+ * @return The last row of the ResultSet.
+ *
+ * @exception SQLException thrown on error.
+ * (last() not supported pre-JDBC2.0)
+ */
+ public ijResult last(ResultSet rs)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ // last is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("LAST");
+ }
+
+ return new ijRowResult(rs, rs.last());
+ }
+
+ /**
+ * Position on the previous row of the specified ResultSet
+ * and return that row to the user.
+ *
+ * @param rs The specified ResultSet.
+ *
+ * @return The previous row of the ResultSet.
+ *
+ * @exception SQLException thrown on error.
+ * (previous() not supported pre-JDBC2.0)
+ */
+ public ijResult previous(ResultSet rs)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+ // first is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("PREVIOUS");
+ }
+
+ return new ijRowResult(rs, rs.previous());
+ }
+
+ /**
+ * Get the current row number
+ *
+ * @param rs The specified ResultSet.
+ *
+ * @return The current row number
+ *
+ * @exception SQLException thrown on error.
+ * (getRow() not supported pre-JDBC2.0)
+ */
+ public int getCurrentRowNumber(ResultSet rs)
+ throws SQLException
+ {
+ boolean forwardOnly;
+ try
+ {
+ forwardOnly = (rs.getStatement().getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY);
+ } catch (AbstractMethodError ame)
+ {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need to go back
+ //to jdbc 1.x functionality
+ forwardOnly = true;
+ }
+
+ // getCurrentRow is only allowed on scroll cursors
+ if (forwardOnly)
+ {
+ throw ijException.forwardOnlyCursor("GETCURRENTROWNUMBER");
+ }
+
+ return rs.getRow();
+ }
+
+ public Properties getConnAttributeDefaults ()
+ {
+ return connAttributeDefaults;
+ }
+
+ public final Object run() {
+ return getClass().getResourceAsStream(ProductGenusNames.TOOLS_INFO);
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain14.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain14.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/utilMain14.java Fri Sep 24 10:33:20 2004
@@ -1,145 +1,145 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 2002, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.iapi.reference.JDBC20Translation;
-import org.apache.derby.iapi.reference.JDBC30Translation;
-
-import java.util.Hashtable;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
-/**
- This class is utilities specific to the two ij Main's.
- This factoring enables sharing the functionality for
- single and dual connection ij runs.
-
- @author jerry
- */
-public class utilMain14 extends utilMain
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2002_2004;
- private static final String JDBC_NOTSUPPORTED = "JDBC 3 method called - not yet supported";
- /**
- * Set up the test to run with 'numConnections' connections/users.
- *
- * @param numConnections The number of connections/users to test.
- *
- * @return Nothing.
- */
- public utilMain14(int numConnections, LocalizedOutput out)
- throws ijFatalException
- {
- super(numConnections, out, (Hashtable)null);
- }
-
- /**
- * Set up the test to run with 'numConnections' connections/users.
- *
- * @param numConnections The number of connections/users to test.
- * @param ignoreErrors A list of errors to ignore. If null,
- * all errors are printed out and nothing
- * is fatal. If non-null, if an error is
- * hit and it is in this list, it is silently
- * ignore. Otherwise, an ijFatalException is
- * thrown. ignoreErrors is used for stress
- * tests.
- *
- * @return Nothing.
- */
- public utilMain14(int numConnections, LocalizedOutput out, Hashtable ignoreErrors)
- throws ijFatalException
- {
- super(numConnections, out, ignoreErrors);
- }
-
- /**
- * Return the right utilMain to use. (JDBC 1.1 or 2.0 or 3.0)
- *
- */
- public utilMain getUtilMain()
- {
- return this;
- }
-
- /**
- * Connections by default create ResultSet objects with holdability true. This method can be used
- * to change the holdability of the connection by passing one of ResultSet.HOLD_CURSORS_OVER_COMMIT
- * or ResultSet.CLOSE_CURSORS_AT_COMMIT
- *
- * @param conn The connection.
- * @param holdType The new holdability for the Connection object.
- *
- * @return The connection object with holdability set to passed value.
- */
- public Connection setHoldability(Connection conn, int holdType)
- throws SQLException
- {
- conn.setHoldability(holdType);
- return conn;
- }
-
- /**
- JDBC 3.0
- * Retrieves the current holdability of ResultSet objects created using this
- * Connection object.
- *
- *
- * @return The holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
- * or ResultSet.CLOSE_CURSORS_AT_COMMIT
- *
- */
- public int getHoldability(Connection conn)
- throws SQLException
- {
- return conn.getHoldability();
- }
-
- /**
- * Create the right kind of statement (scrolling or not)
- * off of the specified connection.
- *
- * @param conn The connection.
- * @param scrollType The scroll type of the cursor.
- *
- * @return The statement.
- */
- public Statement createStatement(Connection conn, int scrollType, int holdType)
- throws SQLException
- {
- Statement stmt;
- try {
- stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY, holdType);
- }catch(SQLException se) {
- //since jcc doesn't yet support JDBC3.0 we have to go back to JDBC2.0
- if (isJCC && se.getMessage().equals(JDBC_NOTSUPPORTED))
- stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY);
- else
- throw se;
- }
- catch(AbstractMethodError ame) {
- //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need
- //to go back to jdbc 1.x functionality
- //The jcc obfuscated jar gets this error
- if (isJCC)
- stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY);
- else
- stmt = conn.createStatement();
- }
- return stmt;
- }
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 2002, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.iapi.reference.JDBC20Translation;
+import org.apache.derby.iapi.reference.JDBC30Translation;
+
+import java.util.Hashtable;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
+/**
+ This class is utilities specific to the two ij Main's.
+ This factoring enables sharing the functionality for
+ single and dual connection ij runs.
+
+ @author jerry
+ */
+public class utilMain14 extends utilMain
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2002_2004;
+ private static final String JDBC_NOTSUPPORTED = "JDBC 3 method called - not yet supported";
+ /**
+ * Set up the test to run with 'numConnections' connections/users.
+ *
+ * @param numConnections The number of connections/users to test.
+ *
+ * @return Nothing.
+ */
+ public utilMain14(int numConnections, LocalizedOutput out)
+ throws ijFatalException
+ {
+ super(numConnections, out, (Hashtable)null);
+ }
+
+ /**
+ * Set up the test to run with 'numConnections' connections/users.
+ *
+ * @param numConnections The number of connections/users to test.
+ * @param ignoreErrors A list of errors to ignore. If null,
+ * all errors are printed out and nothing
+ * is fatal. If non-null, if an error is
+ * hit and it is in this list, it is silently
+ * ignore. Otherwise, an ijFatalException is
+ * thrown. ignoreErrors is used for stress
+ * tests.
+ *
+ * @return Nothing.
+ */
+ public utilMain14(int numConnections, LocalizedOutput out, Hashtable ignoreErrors)
+ throws ijFatalException
+ {
+ super(numConnections, out, ignoreErrors);
+ }
+
+ /**
+ * Return the right utilMain to use. (JDBC 1.1 or 2.0 or 3.0)
+ *
+ */
+ public utilMain getUtilMain()
+ {
+ return this;
+ }
+
+ /**
+ * Connections by default create ResultSet objects with holdability true. This method can be used
+ * to change the holdability of the connection by passing one of ResultSet.HOLD_CURSORS_OVER_COMMIT
+ * or ResultSet.CLOSE_CURSORS_AT_COMMIT
+ *
+ * @param conn The connection.
+ * @param holdType The new holdability for the Connection object.
+ *
+ * @return The connection object with holdability set to passed value.
+ */
+ public Connection setHoldability(Connection conn, int holdType)
+ throws SQLException
+ {
+ conn.setHoldability(holdType);
+ return conn;
+ }
+
+ /**
+ JDBC 3.0
+ * Retrieves the current holdability of ResultSet objects created using this
+ * Connection object.
+ *
+ *
+ * @return The holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
+ * or ResultSet.CLOSE_CURSORS_AT_COMMIT
+ *
+ */
+ public int getHoldability(Connection conn)
+ throws SQLException
+ {
+ return conn.getHoldability();
+ }
+
+ /**
+ * Create the right kind of statement (scrolling or not)
+ * off of the specified connection.
+ *
+ * @param conn The connection.
+ * @param scrollType The scroll type of the cursor.
+ *
+ * @return The statement.
+ */
+ public Statement createStatement(Connection conn, int scrollType, int holdType)
+ throws SQLException
+ {
+ Statement stmt;
+ try {
+ stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY, holdType);
+ }catch(SQLException se) {
+ //since jcc doesn't yet support JDBC3.0 we have to go back to JDBC2.0
+ if (isJCC && se.getMessage().equals(JDBC_NOTSUPPORTED))
+ stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY);
+ else
+ throw se;
+ }
+ catch(AbstractMethodError ame) {
+ //because weblogic 4.5 doesn't yet implement jdbc 2.0 interfaces, need
+ //to go back to jdbc 1.x functionality
+ //The jcc obfuscated jar gets this error
+ if (isJCC)
+ stmt = conn.createStatement(scrollType, JDBC20Translation.CONCUR_READ_ONLY);
+ else
+ stmt = conn.createStatement();
+ }
+ return stmt;
+ }
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaAbstractHelper.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaAbstractHelper.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaAbstractHelper.java Fri Sep 24 10:33:20 2004
@@ -1,48 +1,48 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-
-import java.sql.SQLException;
-import java.sql.Connection;
-
-/*
- An interface for running xa tests.
- The real implementation is only loaded if the requisite javax classes are
- in the classpath.
- */
-interface xaAbstractHelper
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
-
- void XADataSourceStatement(ij parser, Token dbname, Token shut, String create) throws SQLException;
- void XAConnectStatement(ij parser, Token user, Token pass, String id) throws SQLException;
- void XADisconnectStatement(ij parser, String n) throws SQLException;
- Connection XAGetConnectionStatement(ij parser, String n) throws SQLException;
- void CommitStatement(ij parser, Token onePhase, Token twoPhase, int xid) throws SQLException;
- void EndStatement(ij parser, int flag, int xid) throws SQLException;
- void ForgetStatement(ij parser, int xid) throws SQLException;
- void PrepareStatement(ij parser, int xid) throws SQLException;
- ijResult RecoverStatement(ij parser, int flag) throws SQLException;
- void RollbackStatement(ij parser, int xid) throws SQLException;
- void StartStatement(ij parser, int flag, int xid) throws SQLException;
- Connection DataSourceStatement(ij parser, Token dbname, Token protocol,
- Token userT, Token passT, String id) throws SQLException;
- void CPDataSourceStatement(ij parser, Token dbname, Token protocol) throws SQLException;
- void CPConnectStatement(ij parser, Token userT, Token passT, String n) throws SQLException;
- Connection CPGetConnectionStatement(ij parser, String n) throws SQLException;
- void CPDisconnectStatement(ij parser, String n) throws SQLException;
- void setFramework(String framework);
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+
+import java.sql.SQLException;
+import java.sql.Connection;
+
+/*
+ An interface for running xa tests.
+ The real implementation is only loaded if the requisite javax classes are
+ in the classpath.
+ */
+interface xaAbstractHelper
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
+
+ void XADataSourceStatement(ij parser, Token dbname, Token shut, String create) throws SQLException;
+ void XAConnectStatement(ij parser, Token user, Token pass, String id) throws SQLException;
+ void XADisconnectStatement(ij parser, String n) throws SQLException;
+ Connection XAGetConnectionStatement(ij parser, String n) throws SQLException;
+ void CommitStatement(ij parser, Token onePhase, Token twoPhase, int xid) throws SQLException;
+ void EndStatement(ij parser, int flag, int xid) throws SQLException;
+ void ForgetStatement(ij parser, int xid) throws SQLException;
+ void PrepareStatement(ij parser, int xid) throws SQLException;
+ ijResult RecoverStatement(ij parser, int flag) throws SQLException;
+ void RollbackStatement(ij parser, int xid) throws SQLException;
+ void StartStatement(ij parser, int flag, int xid) throws SQLException;
+ Connection DataSourceStatement(ij parser, Token dbname, Token protocol,
+ Token userT, Token passT, String id) throws SQLException;
+ void CPDataSourceStatement(ij parser, Token dbname, Token protocol) throws SQLException;
+ void CPConnectStatement(ij parser, Token userT, Token passT, String n) throws SQLException;
+ Connection CPGetConnectionStatement(ij parser, String n) throws SQLException;
+ void CPDisconnectStatement(ij parser, String n) throws SQLException;
+ void setFramework(String framework);
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaHelper.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaHelper.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/ij/xaHelper.java Fri Sep 24 10:33:20 2004
@@ -1,528 +1,528 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.ij
- (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.ij;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Locale;
-import java.util.Vector;
-
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.XAException;
-import javax.sql.PooledConnection;
-import javax.sql.XAConnection;
-import javax.sql.XADataSource;
-import javax.sql.DataSource;
-import javax.sql.ConnectionPoolDataSource;
-
-/*
- * The real xa helper class. Load this class only if we know the javax classes
- * are in the class path.
- */
-class xaHelper implements xaAbstractHelper
-{
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
-
- private XADataSource currentXADataSource;
- private XAConnection currentXAConnection;
-
- private String databaseName;
-
- // non xa stuff
- private DataSource currentDataSource;
- private ConnectionPoolDataSource currentCPDataSource;
- private PooledConnection currentPooledConnection;
-
- private String framework_property;
-
- xaHelper()
- {
- }
-
-
- public void setFramework(String framework)
- {
- this.framework_property = framework_property;
- }
-
- private Xid makeXid(int xid)
- {
- return new ijXid(xid, databaseName.getBytes());
- }
-
- public void XADataSourceStatement(ij parser, Token dbname, Token shutdown,
- String create)
- throws SQLException
- {
- try
- {
- currentXADataSource = (XADataSource) getXADataSource();
-
- databaseName = parser.stringValue(dbname.image);
- xaHelper.setDataSourceProperty(currentXADataSource, "databaseName", databaseName);
- xaHelper.setDataSourceProperty(currentXADataSource, "dataSourceName", databaseName);
-
- if (shutdown != null && shutdown.toString().toLowerCase(Locale.ENGLISH).equals("shutdown"))
- {
- xaHelper.setDataSourceProperty(currentXADataSource, "shutdownDatabase", "shutdown");
-
- // do a getXAConnection to shut it down */
- currentXADataSource.getXAConnection().getConnection();
-
- currentXADataSource = null;
- currentXAConnection = null;
- }
- else if (create != null)
- {
- if (create.toLowerCase(java.util.Locale.ENGLISH).equals("create"))
- {
- xaHelper.setDataSourceProperty(currentXADataSource, "createDatabase", "create");
-
- /* do a getXAConnection to create it */
- XAConnection conn = currentXADataSource.getXAConnection();
- conn.close();
-
- xaHelper.setDataSourceProperty(currentXADataSource, "createDatabase", null);
- }
- }
- }
- catch (Throwable t)
- {
- handleException(t);
- }
- }
-
-
- public void XAConnectStatement(ij parser, Token user, Token pass, String id)
- throws SQLException
- {
- try
- {
- if (currentXAConnection != null)
- {
- try {
- currentXAConnection.close();
- } catch (SQLException sqle) {
- }
-
- currentXAConnection = null;
- }
-
- String username = null;
- String password = "";
-
- if (pass != null)
- password = parser.stringValue(pass.image);
-
- if (user != null)
- {
- username = parser.stringValue(user.image);
-
- currentXAConnection =
- currentXADataSource.getXAConnection(username, password);
- }
- else
- {
-
- currentXAConnection = currentXADataSource.getXAConnection();
- }
-
- }
- catch (Throwable t)
- {
- handleException(t);
- }
- }
-
- public void XADisconnectStatement(ij parser, String n) throws SQLException
- {
- if (currentXAConnection == null)
- throw ijException.noSuchConnection("XAConnection");
- currentXAConnection.close();
- currentXAConnection = null;
- }
-
- public Connection XAGetConnectionStatement(ij parser, String n) throws SQLException
- {
- try
- {
- return currentXAConnection.getConnection();
- }
- catch(Throwable t)
- {
- handleException(t);
- }
- return null;
- }
-
- public void CommitStatement(ij parser, Token onePhase, Token twoPhase,
- int xid)
- throws SQLException
- {
- try
- {
- currentXAConnection.getXAResource().commit(makeXid(xid), (onePhase != null));
- }
- catch(Throwable t)
- {
- handleException(t);
- }
- }
-
- public void EndStatement(ij parser, int flag, int xid) throws SQLException
- {
- try
- {
- currentXAConnection.getXAResource().end(makeXid(xid), flag);
- }
- catch(Throwable t)
- {
- handleException(t);
- }
- }
-
- public void ForgetStatement(ij parser, int xid) throws SQLException
- {
- try
- {
- currentXAConnection.getXAResource().forget(makeXid(xid));
- }
- catch(Throwable t)
- {
- handleException(t);
- }
- }
-
- public void PrepareStatement(ij parser, int xid) throws SQLException
- {
- try
- {
- currentXAConnection.getXAResource().prepare(makeXid(xid));
- }
- catch(Throwable t)
- {
- handleException(t);
- }
- }
-
- public ijResult RecoverStatement(ij parser, int flag) throws SQLException
- {
- Object[] val = null;
-
- try
- {
- val = currentXAConnection.getXAResource().recover(flag);
- }
- catch(Throwable t)
- {
- handleException(t);
- }
-
- Vector v = new Vector();
- v.addElement("");
- v.addElement(LocalizedResource.getMessage("IJ_Reco0InDoubT", LocalizedResource.getNumber(val.length)));
- v.addElement("");
- for (int i = 0; i < val.length; i++)
- v.addElement(LocalizedResource.getMessage("IJ_Tran01", LocalizedResource.getNumber(i+1), val[i].toString()));
-
- return new ijVectorResult(v,null);
-
- }
-
- public void RollbackStatement(ij parser, int xid) throws SQLException
- {
- try
- {
- currentXAConnection.getXAResource().rollback(makeXid(xid));
- }
- catch(Throwable t)
- {
- handleException(t);
- }
-
- }
-
- public void StartStatement(ij parser, int flag, int xid) throws SQLException
- {
- try
- {
- currentXAConnection.getXAResource().start(makeXid(xid), flag);
- }
- catch(Throwable t)
- {
- handleException(t);
- }
- }
-
- private void handleException(Throwable t) throws SQLException
- {
- if (t instanceof SQLException)
- {
- // let ij handle it
- throw (SQLException)t;
- }
- if (t instanceof XAException)
- {
- int errorCode = ((XAException)t).errorCode;
- String error = LocalizedResource.getMessage("IJ_IlleValu");
-
- // XA_RBBASE 100
- // XA_RBROLLBACK 100
- // XA_RBCOMMFAIL 101
- // XA_RBDEADLOCK 102
- // XA_RBINTEGRITY 103
- // XA_RBOTHER 104
- // XA_RBPROTO 105
- // XA_RBTIMEOUT 106
- // XA_RBTRANSIENT 107
- // XA_RBEND 107
- //
- // XA_RDONLY 3
- // XA_RETRY 4
- // XA_HEURMIX 5
- // XA_HEURRB 6
- // XA_HEURCOM 7
- // XA_HEURHAZ 8
- // XA_NOMIGRATE 9
- //
- // XAER_ASYNC -2
- // XAER_RMERR -3
- // XAER_NOTA -4
- // XAER_INVAL -5
- // XAER_PROTO -6
- // XAER_RMFAIL -7
- // XAER_DUPID -8
- // XAER_OUTSIDE -9
-
- switch(errorCode)
- {
- case XAException.XA_HEURCOM : error = "XA_HEURCOM "; break;
- case XAException.XA_HEURHAZ : error = "XA_HEURHAZ"; break;
- case XAException.XA_HEURMIX : error = "XA_HEURMIX"; break;
- case XAException.XA_HEURRB : error = "XA_HEURRB "; break;
- case XAException.XA_NOMIGRATE : error = "XA_NOMIGRATE "; break;
- // case XAException.XA_RBBASE : error = "XA_RBBASE "; break;
- case XAException.XA_RBCOMMFAIL : error = "XA_RBCOMMFAIL "; break;
- case XAException.XA_RBDEADLOCK : error = "XA_RBDEADLOCK "; break;
- // case XAException.XA_RBEND : error = "XA_RBEND "; break;
- case XAException.XA_RBINTEGRITY : error = "XA_RBINTEGRITY "; break;
- case XAException.XA_RBOTHER : error = "XA_RBOTHER "; break;
- case XAException.XA_RBPROTO : error = "XA_RBPROTO "; break;
- case XAException.XA_RBROLLBACK : error = "XA_RBROLLBACK "; break;
- case XAException.XA_RBTIMEOUT : error = "XA_RBTIMEOUT "; break;
- case XAException.XA_RBTRANSIENT : error = "XA_RBTRANSIENT "; break;
- case XAException.XA_RDONLY : error = "XA_RDONLY "; break;
- case XAException.XA_RETRY : error = "XA_RETRY "; break;
- case XAException.XAER_ASYNC : error = "XAER_ASYNC "; break;
- case XAException.XAER_DUPID : error = "XAER_DUPID "; break;
- case XAException.XAER_INVAL : error = "XAER_INVAL "; break;
- case XAException.XAER_NOTA : error = "XAER_NOTA "; break;
- case XAException.XAER_OUTSIDE : error = "XAER_OUTSIDE "; break;
- case XAException.XAER_PROTO : error = "XAER_PROTO "; break;
- case XAException.XAER_RMERR : error = "XAER_RMERR "; break;
- case XAException.XAER_RMFAIL : error = "XAER_RMFAIL "; break;
- }
- throw new ijException(error);
-
- }
- else // StandardException or run time exception, log it first
- {
- String info = LocalizedResource.getMessage("IJ_01SeeClouLog", t.toString(), t.getMessage());
- t.printStackTrace(System.out);
- throw new ijException(info);
- }
- }
-
-
- // non-xa stuff. DataSource and ConnectionPoolDataSource
- public Connection DataSourceStatement(ij parser, Token dbname, Token protocol,
- Token userT, Token passT, String id)
- throws SQLException
- {
-
- try {
- currentDataSource = (DataSource) (Class.forName("org.apache.derby.jdbc.EmbeddedDataSource").newInstance());
- } catch (Exception e) {
- throw new SQLException(e.toString());
- }
- databaseName = parser.stringValue(dbname.image);
- xaHelper.setDataSourceProperty(currentDataSource, "databaseName", databaseName);
-
- // make a connection
- Connection c = null;
- String username = null;
- String password = "";
-
- if (passT != null)
- password = parser.stringValue(passT.image);
-
- if (userT != null)
- {
- username = parser.stringValue(userT.image);
- c = currentDataSource.getConnection(username, password);
- }
- else
- {
- c = currentDataSource.getConnection();
- }
-
- return c;
-
- }
-
- public void CPDataSourceStatement(ij parser, Token dbname, Token protocol)
- throws SQLException
- {
- try {
- currentCPDataSource = (ConnectionPoolDataSource) (Class.forName("org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource").newInstance());
- } catch (Exception e) {
- throw new SQLException(e.toString());
- }
- databaseName = parser.stringValue(dbname.image);
- xaHelper.setDataSourceProperty(currentCPDataSource, "databaseName", databaseName);
- }
-
- public void CPConnectStatement(ij parser, Token userT, Token passT, String n)
- throws SQLException
- {
- String username = null;
- String password = "";
-
- if (passT != null)
- password = parser.stringValue(passT.image);
-
- if (userT != null)
- {
- username = parser.stringValue(userT.image);
- currentPooledConnection =
- currentCPDataSource.getPooledConnection(username, password);
- }
- else
- {
- currentPooledConnection =
- currentCPDataSource.getPooledConnection();
- }
- }
-
- public Connection CPGetConnectionStatement(ij parser, String n)
- throws SQLException
- {
- return currentPooledConnection.getConnection();
- }
-
- public void CPDisconnectStatement(ij parser, String n) throws SQLException
- {
- if (currentPooledConnection == null)
- throw ijException.noSuchConnection(LocalizedResource.getMessage("IJ_Pool"));
- currentPooledConnection.close();
- currentPooledConnection = null;
- }
-
- /**
- * Get a DataSource that supports distributed transactions.
- *
- * @return XADataSource object
- *
- * @exception Exception if XaDataSource is not in class path.
- */
- private XADataSource getXADataSource() throws Exception
- {
- // We need to construct this object in this round about fashion because
- // if we new it directly, then it will the tools.jar file to bloat.
- try
- {
- return (XADataSource)(Class.forName("org.apache.derby.jdbc.EmbeddedXADataSource").newInstance());
- }
- catch(ClassNotFoundException cnfe) {
- throw new ijException(LocalizedResource.getMessage("IJ_XAClass"));
- }
- catch (InstantiationException e) { }
- catch (IllegalAccessException e) { }
-
- throw new ijException(LocalizedResource.getMessage("IJ_XANoI"));
- }
- private static final Class[] STRING_P = { copyrightNotice.getClass() };
- private static final Class[] INT_P = { Integer.TYPE };
-
- private static void setDataSourceProperty(Object ds, String property, String value) throws SQLException {
-
- String methodName =
- "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1);
-
- try {
- java.lang.reflect.Method m = ds.getClass().getMethod(methodName, STRING_P);
- m.invoke(ds, new Object[] {value});
- return;
- } catch (/*NoSuchMethod*/Exception nsme) {
- throw new SQLException(property + " ???");
- //java.lang.reflect.Method m = ds.getClass().getMethod("set" + property, INT_P);
- //m.invoke(ds, new Object[] {Integer.valueOf(value)});
- }
- }
-}
-
-class ijXid implements Xid, java.io.Serializable
-{
- private static final long serialVersionUID = 64467452100036L;
-
- private final int format_id;
- private final byte[] global_id;
- private final byte[] branch_id;
-
-
- ijXid(int xid, byte[] id)
- {
- format_id = xid;
- global_id = id;
- branch_id = id;
-
- }
- /**
- * Obtain the format id part of the Xid.
- * <p>
- *
- * @return Format identifier. O means the OSI CCR format.
- **/
- public int getFormatId()
- {
- return(format_id);
- }
-
- /**
- * Obtain the global transaction identifier part of XID as an array of
- * bytes.
- * <p>
- *
- * @return A byte array containing the global transaction identifier.
- **/
- public byte[] getGlobalTransactionId()
- {
- return(global_id);
- }
-
- /**
- * Obtain the transaction branch qualifier part of the Xid in a byte array.
- * <p>
- *
- * @return A byte array containing the branch qualifier of the transaction.
- **/
- public byte[] getBranchQualifier()
- {
- return(branch_id);
- }
-}
-
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.ij
+ (C) Copyright IBM Corp. 1999, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.ij;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.XAException;
+import javax.sql.PooledConnection;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import javax.sql.DataSource;
+import javax.sql.ConnectionPoolDataSource;
+
+/*
+ * The real xa helper class. Load this class only if we know the javax classes
+ * are in the class path.
+ */
+class xaHelper implements xaAbstractHelper
+{
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1999_2004;
+
+ private XADataSource currentXADataSource;
+ private XAConnection currentXAConnection;
+
+ private String databaseName;
+
+ // non xa stuff
+ private DataSource currentDataSource;
+ private ConnectionPoolDataSource currentCPDataSource;
+ private PooledConnection currentPooledConnection;
+
+ private String framework_property;
+
+ xaHelper()
+ {
+ }
+
+
+ public void setFramework(String framework)
+ {
+ this.framework_property = framework_property;
+ }
+
+ private Xid makeXid(int xid)
+ {
+ return new ijXid(xid, databaseName.getBytes());
+ }
+
+ public void XADataSourceStatement(ij parser, Token dbname, Token shutdown,
+ String create)
+ throws SQLException
+ {
+ try
+ {
+ currentXADataSource = (XADataSource) getXADataSource();
+
+ databaseName = parser.stringValue(dbname.image);
+ xaHelper.setDataSourceProperty(currentXADataSource, "databaseName", databaseName);
+ xaHelper.setDataSourceProperty(currentXADataSource, "dataSourceName", databaseName);
+
+ if (shutdown != null && shutdown.toString().toLowerCase(Locale.ENGLISH).equals("shutdown"))
+ {
+ xaHelper.setDataSourceProperty(currentXADataSource, "shutdownDatabase", "shutdown");
+
+ // do a getXAConnection to shut it down */
+ currentXADataSource.getXAConnection().getConnection();
+
+ currentXADataSource = null;
+ currentXAConnection = null;
+ }
+ else if (create != null)
+ {
+ if (create.toLowerCase(java.util.Locale.ENGLISH).equals("create"))
+ {
+ xaHelper.setDataSourceProperty(currentXADataSource, "createDatabase", "create");
+
+ /* do a getXAConnection to create it */
+ XAConnection conn = currentXADataSource.getXAConnection();
+ conn.close();
+
+ xaHelper.setDataSourceProperty(currentXADataSource, "createDatabase", null);
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+
+ public void XAConnectStatement(ij parser, Token user, Token pass, String id)
+ throws SQLException
+ {
+ try
+ {
+ if (currentXAConnection != null)
+ {
+ try {
+ currentXAConnection.close();
+ } catch (SQLException sqle) {
+ }
+
+ currentXAConnection = null;
+ }
+
+ String username = null;
+ String password = "";
+
+ if (pass != null)
+ password = parser.stringValue(pass.image);
+
+ if (user != null)
+ {
+ username = parser.stringValue(user.image);
+
+ currentXAConnection =
+ currentXADataSource.getXAConnection(username, password);
+ }
+ else
+ {
+
+ currentXAConnection = currentXADataSource.getXAConnection();
+ }
+
+ }
+ catch (Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+ public void XADisconnectStatement(ij parser, String n) throws SQLException
+ {
+ if (currentXAConnection == null)
+ throw ijException.noSuchConnection("XAConnection");
+ currentXAConnection.close();
+ currentXAConnection = null;
+ }
+
+ public Connection XAGetConnectionStatement(ij parser, String n) throws SQLException
+ {
+ try
+ {
+ return currentXAConnection.getConnection();
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+ return null;
+ }
+
+ public void CommitStatement(ij parser, Token onePhase, Token twoPhase,
+ int xid)
+ throws SQLException
+ {
+ try
+ {
+ currentXAConnection.getXAResource().commit(makeXid(xid), (onePhase != null));
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+ public void EndStatement(ij parser, int flag, int xid) throws SQLException
+ {
+ try
+ {
+ currentXAConnection.getXAResource().end(makeXid(xid), flag);
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+ public void ForgetStatement(ij parser, int xid) throws SQLException
+ {
+ try
+ {
+ currentXAConnection.getXAResource().forget(makeXid(xid));
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+ public void PrepareStatement(ij parser, int xid) throws SQLException
+ {
+ try
+ {
+ currentXAConnection.getXAResource().prepare(makeXid(xid));
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+ public ijResult RecoverStatement(ij parser, int flag) throws SQLException
+ {
+ Object[] val = null;
+
+ try
+ {
+ val = currentXAConnection.getXAResource().recover(flag);
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+
+ Vector v = new Vector();
+ v.addElement("");
+ v.addElement(LocalizedResource.getMessage("IJ_Reco0InDoubT", LocalizedResource.getNumber(val.length)));
+ v.addElement("");
+ for (int i = 0; i < val.length; i++)
+ v.addElement(LocalizedResource.getMessage("IJ_Tran01", LocalizedResource.getNumber(i+1), val[i].toString()));
+
+ return new ijVectorResult(v,null);
+
+ }
+
+ public void RollbackStatement(ij parser, int xid) throws SQLException
+ {
+ try
+ {
+ currentXAConnection.getXAResource().rollback(makeXid(xid));
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+
+ }
+
+ public void StartStatement(ij parser, int flag, int xid) throws SQLException
+ {
+ try
+ {
+ currentXAConnection.getXAResource().start(makeXid(xid), flag);
+ }
+ catch(Throwable t)
+ {
+ handleException(t);
+ }
+ }
+
+ private void handleException(Throwable t) throws SQLException
+ {
+ if (t instanceof SQLException)
+ {
+ // let ij handle it
+ throw (SQLException)t;
+ }
+ if (t instanceof XAException)
+ {
+ int errorCode = ((XAException)t).errorCode;
+ String error = LocalizedResource.getMessage("IJ_IlleValu");
+
+ // XA_RBBASE 100
+ // XA_RBROLLBACK 100
+ // XA_RBCOMMFAIL 101
+ // XA_RBDEADLOCK 102
+ // XA_RBINTEGRITY 103
+ // XA_RBOTHER 104
+ // XA_RBPROTO 105
+ // XA_RBTIMEOUT 106
+ // XA_RBTRANSIENT 107
+ // XA_RBEND 107
+ //
+ // XA_RDONLY 3
+ // XA_RETRY 4
+ // XA_HEURMIX 5
+ // XA_HEURRB 6
+ // XA_HEURCOM 7
+ // XA_HEURHAZ 8
+ // XA_NOMIGRATE 9
+ //
+ // XAER_ASYNC -2
+ // XAER_RMERR -3
+ // XAER_NOTA -4
+ // XAER_INVAL -5
+ // XAER_PROTO -6
+ // XAER_RMFAIL -7
+ // XAER_DUPID -8
+ // XAER_OUTSIDE -9
+
+ switch(errorCode)
+ {
+ case XAException.XA_HEURCOM : error = "XA_HEURCOM "; break;
+ case XAException.XA_HEURHAZ : error = "XA_HEURHAZ"; break;
+ case XAException.XA_HEURMIX : error = "XA_HEURMIX"; break;
+ case XAException.XA_HEURRB : error = "XA_HEURRB "; break;
+ case XAException.XA_NOMIGRATE : error = "XA_NOMIGRATE "; break;
+ // case XAException.XA_RBBASE : error = "XA_RBBASE "; break;
+ case XAException.XA_RBCOMMFAIL : error = "XA_RBCOMMFAIL "; break;
+ case XAException.XA_RBDEADLOCK : error = "XA_RBDEADLOCK "; break;
+ // case XAException.XA_RBEND : error = "XA_RBEND "; break;
+ case XAException.XA_RBINTEGRITY : error = "XA_RBINTEGRITY "; break;
+ case XAException.XA_RBOTHER : error = "XA_RBOTHER "; break;
+ case XAException.XA_RBPROTO : error = "XA_RBPROTO "; break;
+ case XAException.XA_RBROLLBACK : error = "XA_RBROLLBACK "; break;
+ case XAException.XA_RBTIMEOUT : error = "XA_RBTIMEOUT "; break;
+ case XAException.XA_RBTRANSIENT : error = "XA_RBTRANSIENT "; break;
+ case XAException.XA_RDONLY : error = "XA_RDONLY "; break;
+ case XAException.XA_RETRY : error = "XA_RETRY "; break;
+ case XAException.XAER_ASYNC : error = "XAER_ASYNC "; break;
+ case XAException.XAER_DUPID : error = "XAER_DUPID "; break;
+ case XAException.XAER_INVAL : error = "XAER_INVAL "; break;
+ case XAException.XAER_NOTA : error = "XAER_NOTA "; break;
+ case XAException.XAER_OUTSIDE : error = "XAER_OUTSIDE "; break;
+ case XAException.XAER_PROTO : error = "XAER_PROTO "; break;
+ case XAException.XAER_RMERR : error = "XAER_RMERR "; break;
+ case XAException.XAER_RMFAIL : error = "XAER_RMFAIL "; break;
+ }
+ throw new ijException(error);
+
+ }
+ else // StandardException or run time exception, log it first
+ {
+ String info = LocalizedResource.getMessage("IJ_01SeeClouLog", t.toString(), t.getMessage());
+ t.printStackTrace(System.out);
+ throw new ijException(info);
+ }
+ }
+
+
+ // non-xa stuff. DataSource and ConnectionPoolDataSource
+ public Connection DataSourceStatement(ij parser, Token dbname, Token protocol,
+ Token userT, Token passT, String id)
+ throws SQLException
+ {
+
+ try {
+ currentDataSource = (DataSource) (Class.forName("org.apache.derby.jdbc.EmbeddedDataSource").newInstance());
+ } catch (Exception e) {
+ throw new SQLException(e.toString());
+ }
+ databaseName = parser.stringValue(dbname.image);
+ xaHelper.setDataSourceProperty(currentDataSource, "databaseName", databaseName);
+
+ // make a connection
+ Connection c = null;
+ String username = null;
+ String password = "";
+
+ if (passT != null)
+ password = parser.stringValue(passT.image);
+
+ if (userT != null)
+ {
+ username = parser.stringValue(userT.image);
+ c = currentDataSource.getConnection(username, password);
+ }
+ else
+ {
+ c = currentDataSource.getConnection();
+ }
+
+ return c;
+
+ }
+
+ public void CPDataSourceStatement(ij parser, Token dbname, Token protocol)
+ throws SQLException
+ {
+ try {
+ currentCPDataSource = (ConnectionPoolDataSource) (Class.forName("org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource").newInstance());
+ } catch (Exception e) {
+ throw new SQLException(e.toString());
+ }
+ databaseName = parser.stringValue(dbname.image);
+ xaHelper.setDataSourceProperty(currentCPDataSource, "databaseName", databaseName);
+ }
+
+ public void CPConnectStatement(ij parser, Token userT, Token passT, String n)
+ throws SQLException
+ {
+ String username = null;
+ String password = "";
+
+ if (passT != null)
+ password = parser.stringValue(passT.image);
+
+ if (userT != null)
+ {
+ username = parser.stringValue(userT.image);
+ currentPooledConnection =
+ currentCPDataSource.getPooledConnection(username, password);
+ }
+ else
+ {
+ currentPooledConnection =
+ currentCPDataSource.getPooledConnection();
+ }
+ }
+
+ public Connection CPGetConnectionStatement(ij parser, String n)
+ throws SQLException
+ {
+ return currentPooledConnection.getConnection();
+ }
+
+ public void CPDisconnectStatement(ij parser, String n) throws SQLException
+ {
+ if (currentPooledConnection == null)
+ throw ijException.noSuchConnection(LocalizedResource.getMessage("IJ_Pool"));
+ currentPooledConnection.close();
+ currentPooledConnection = null;
+ }
+
+ /**
+ * Get a DataSource that supports distributed transactions.
+ *
+ * @return XADataSource object
+ *
+ * @exception Exception if XaDataSource is not in class path.
+ */
+ private XADataSource getXADataSource() throws Exception
+ {
+ // We need to construct this object in this round about fashion because
+ // if we new it directly, then it will the tools.jar file to bloat.
+ try
+ {
+ return (XADataSource)(Class.forName("org.apache.derby.jdbc.EmbeddedXADataSource").newInstance());
+ }
+ catch(ClassNotFoundException cnfe) {
+ throw new ijException(LocalizedResource.getMessage("IJ_XAClass"));
+ }
+ catch (InstantiationException e) { }
+ catch (IllegalAccessException e) { }
+
+ throw new ijException(LocalizedResource.getMessage("IJ_XANoI"));
+ }
+ private static final Class[] STRING_P = { copyrightNotice.getClass() };
+ private static final Class[] INT_P = { Integer.TYPE };
+
+ private static void setDataSourceProperty(Object ds, String property, String value) throws SQLException {
+
+ String methodName =
+ "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1);
+
+ try {
+ java.lang.reflect.Method m = ds.getClass().getMethod(methodName, STRING_P);
+ m.invoke(ds, new Object[] {value});
+ return;
+ } catch (/*NoSuchMethod*/Exception nsme) {
+ throw new SQLException(property + " ???");
+ //java.lang.reflect.Method m = ds.getClass().getMethod("set" + property, INT_P);
+ //m.invoke(ds, new Object[] {Integer.valueOf(value)});
+ }
+ }
+}
+
+class ijXid implements Xid, java.io.Serializable
+{
+ private static final long serialVersionUID = 64467452100036L;
+
+ private final int format_id;
+ private final byte[] global_id;
+ private final byte[] branch_id;
+
+
+ ijXid(int xid, byte[] id)
+ {
+ format_id = xid;
+ global_id = id;
+ branch_id = id;
+
+ }
+ /**
+ * Obtain the format id part of the Xid.
+ * <p>
+ *
+ * @return Format identifier. O means the OSI CCR format.
+ **/
+ public int getFormatId()
+ {
+ return(format_id);
+ }
+
+ /**
+ * Obtain the global transaction identifier part of XID as an array of
+ * bytes.
+ * <p>
+ *
+ * @return A byte array containing the global transaction identifier.
+ **/
+ public byte[] getGlobalTransactionId()
+ {
+ return(global_id);
+ }
+
+ /**
+ * Obtain the transaction branch qualifier part of the Xid in a byte array.
+ * <p>
+ *
+ * @return A byte array containing the branch qualifier of the transaction.
+ **/
+ public byte[] getBranchQualifier()
+ {
+ return(branch_id);
+ }
+}
+
+
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/Main.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/Main.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/Main.java Fri Sep 24 10:33:20 2004
@@ -1,951 +1,951 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.sysinfo
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.impl.tools.sysinfo;
-
-import java.util.Locale;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.io.InputStream;
-import java.util.Properties;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.StringTokenizer;
-import java.io.File;
-import java.util.zip.ZipFile;
-import java.io.IOException;
-import java.util.zip.ZipEntry;
-import java.io.FileInputStream;
-import java.util.Vector;
-import java.io.InputStream;
-import java.lang.reflect.Method;
-
-import org.apache.derby.iapi.services.info.PropertyNames;
-import org.apache.derby.iapi.services.info.ProductVersionHolder;
-import org.apache.derby.iapi.services.info.ProductGenusNames;
-import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.tools.i18n.*;
-
-
-/**
- <i>Copyright © 1998, Cloudscape, Inc. All rights reserved.</i>
-
- <P>
- SysInfo reports values relevant to the Cloudscape product found on
- the CLASSPATH. It looks for a file called sysinfo.properties in
- the CLASSPATH using getResourceAsStream. If the file
- is not found, or some other exception occurs, the
- value returned will be that set for the key
- SysInfo.failureTag, or be the value "<info unavailable>".
-
- <P>
- This class can be used to print out system information at the
- command line by issuing the command:
- <PRE>
- java com.ibm.db2j.tools.SysInfo.main
- </PRE>
- Alternatively, you can use SysInfo within your program to display
- Cloudscape information; a Cloudscape version string is returned by this Java code:
- <PRE>
- new Main().toString();
- </PRE>
-
- */
-
-
-public final class Main {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- /**
- Application entry point for SysInfo. This will print out
- the Cloudscape product information as well as a snapshot of
- the System properties.
- */
- public static void main(String args[]) {
- // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
- LocalizedResource.getInstance();
-
- LocalizedOutput out;
-
- //using AppStreamReader(extends InputStreamReader) for conversion into specific codeset
-
- out = LocalizedResource.OutputWriter();
-
- // because we're in a static method, we need to
- // get our own instance variable
- parseArgs (args);
-
- if (cptester == true)
- getClasspathInfo (args, out);
- else
- getMainInfo (out, setPause);
-
- } // end of main (String args[])
-
-public static void getMainInfo (java.io.PrintWriter aw, boolean pause) {
-
- aw.println (javaSep);
- reportJavaInfo (aw);
- aw.println (jbmsSep);
- reportCloudscape (aw);
-
- aw.println (sep);
-
- // Locales info
- try {
- reportLocales (aw);
- }
- catch (Exception e) {
-
- aw.println (Main.getTextMessage ("SIF01.Q"));
- aw.println (Main.getTextMessage ("SIF01.B"));
- }
-
-
- if (pause) {
- pause();
- }
-
- } // end of getMainInfo (AppStreamWriter aw, boolean printLicense, boolean pause)
-
-
- private static boolean setPause = false;
-
- private static boolean setLicense = false;
-
- private static boolean cptester = false;
-
- private static void parseArgs (String args[]) {
-
- if (args == null) {
-
- return;
- }
-
-
- for (int i = 0; i < args.length; i++) {
-
- if (args[i].equals ("-pause")) {
-
- setPause = true;
- }
-
- if (args[i].equals ("-cp")) {
-
- cptester=true;
- }
-
- } // end for
-
- } // end of parseArgs (String args[])
-
-
- /**
- For the benefit of DOS box users, this method waits for input
- before returning
- */
- private static void pause () {
-
- try {
-
- System.out.print (Main.getTextMessage ("SIF01.C"));
- BufferedReader br = new BufferedReader (new InputStreamReader (System.in));
- br.readLine ();
- }
- catch (IOException ioe) {
-
- //just return
- }
-
- } // end of pause ()
-
- /**
- prints out the jbms info to the specified AppStreamWriter.
- @param aw the AppStreamWriter to use. If null, System.out is
- used
- */
-
- private static void reportCloudscape (java.io.PrintWriter localAW) {
-
- String classpath;
-
- try {
- classpath = System.getProperty("java.class.path");
- }
- catch (SecurityException se) {
- classpath = null;
- }
-
- ZipInfoProperties zip[]= Main.getAllInfo (classpath);
-
- if (zip != null) {
-
- for (int i = 0; i < zip.length; i++) {
-
- String thisInfo = "[" + zip[i].getLocation () + "] " +
- zip[i].getVersionBuildInfo ();
-
- localAW.println (thisInfo);
- }
- }
-
- else {
-
- localAW.println (Main.getTextMessage ("SIF01.D"));
- }
-
-
- } // end of reportCloudscape
-
-
- /**
- Writes out the relevant info about the Java environment to
- the specified AppStreamWriter.
-
- @param aw The AppStreamWriter to write info out to. If this is
- null, the info is written to System.out
- */
-
- private static void reportJavaInfo (java.io.PrintWriter localAW) {
-
-
-
- localAW.println (Main.getTextMessage ("SIF02.A",
- getJavaProperty ("java.version")));
-
- localAW.println (Main.getTextMessage ("SIF02.B",
- getJavaProperty ("java.vendor")));
-
- localAW.println (Main.getTextMessage ("SIF02.C",
- getJavaProperty ("java.home")));
-
- localAW.println (Main.getTextMessage ("SIF02.D",
- getJavaProperty ("java.class.path")));
-
- localAW.println (Main.getTextMessage ("SIF02.E",
- getJavaProperty ("os.name")));
-
- localAW.println (Main.getTextMessage ("SIF02.F",
- getJavaProperty ("os.arch")));
-
- localAW.println (Main.getTextMessage ("SIF02.G",
- getJavaProperty ("os.version")));
-
- localAW.println (Main.getTextMessage ("SIF02.H",
- getJavaProperty ("user.name")));
-
- localAW.println (Main.getTextMessage ("SIF02.I",
- getJavaProperty ("user.home")));
-
- localAW.println (Main.getTextMessage ("SIF02.J",
- getJavaProperty ("user.dir")));
-
- } // end of reportJavaInfo
-
-
-
- /**
- Return Java properties from java.lang.System. Will catch
- SecurityExceptions and note them for displaying information.
-
- @return the Java property value or a string capturing a
- security exception.
- */
-
- private static String getJavaProperty (String whichProperty) {
-
- String property;
- String unavailable = Main.getTextMessage ("SIF01.H");
-
- try {
-
- property = System.getProperty (whichProperty, unavailable);
- return property;
- }
- catch (SecurityException se) {
-
- return Main.getTextMessage ("SIF01.I", se);
- }
-
- } // end of getJavaProperty (String whichProperty)
-
-
-
- /**
- for use by the main () method
- */
-
- private final static String sep = "------------------------------------------------------";
- private final static String javaSep = Main.getTextMessage ("SIF01.L");
-
- private final static String jbmsSep = Main.getTextMessage ("SIF01.M");
-
- private final static String licSep = Main.getTextMessage ("SIF01.N");
-
- private final static String locSep = Main.getTextMessage ("SIF01.P");
-
- private final static String curLoc = Main.getTextMessage ("SIF01.T");
-
- /**
- The name of the failure tag in the information file.
- The failure tag's value provides a default value if
- any other properties are missing.
- */
- private final static String failureTag = Main.getTextMessage ("SIF01.J");
-
- private static void getClasspathInfo (String args[], java.io.PrintWriter aw) {
-
- Main.useMe (args, aw);
- }
-
-
-
-
- /**
- Writes out information about the locales with the
- product.
-
- @param aw the AppStreamWriter to which the info is written. If this
- value is null, the info is written to System.out
-
- */
- private static void reportLocales (java.io.PrintWriter localAW) { // throws StandardException {
-
- boolean cur_loc = true;
-
- localAW.println (locSep);
-
- // Read all the possible locales, and test for each one, if it loads.
- // If so, then read the properties, and print them out.
-
- Locale[] supportedLocales = Locale.getAvailableLocales();
- String[] stringLocales = new String[supportedLocales.length];
- for (int i = 0; i < supportedLocales.length; i++)
- {
- stringLocales[i] = supportedLocales[i].toString();
- }
- java.util.Arrays.sort(stringLocales);
-
- Properties p = new Properties ();
- for (int i = 0; i < stringLocales.length; i++) {
-
- String localeResource =
- "/org/apache/derby/info/locale_" + stringLocales[i] + ".properties";
-
- try {
-
- InputStream is = p.getClass().getResourceAsStream (localeResource);
-
- if (is == null) {
-// localAW.println("resource is null: " + localeResource);
- }
- else {
-
- try {
- p.clear();
- p.load (is);
- //Displaying Current Locale
- if (cur_loc)
- {
- Locale loc = null;
- loc = Locale.getDefault();
- localAW.println(Main.getTextMessage ("SIF01.T") + " [" + loc.getDisplayLanguage() + "/" + loc.getDisplayCountry() + " [" + loc + "]]");
- cur_loc = false;
- }
-
- //Beetle 5079: do not print unlocalized locale names to console, only print locale code.
- String localeName = p.getProperty("derby.locale.external.name");
- localeName = localeName.substring(localeName.indexOf("[")+1);
- localeName = localeName.substring(0,localeName.indexOf("]"));
-
- localAW.println (Main.getTextMessage ("SIF01.R",
- localeName));
-
-
- int major = Integer.valueOf(p.getProperty ("derby.locale.version.major")).intValue();
- int minor = Integer.valueOf(p.getProperty ("derby.locale.version.minor")).intValue();
- int maint = Integer.valueOf(p.getProperty ("derby.locale.version.maint")).intValue();
- int build = Integer.valueOf(p.getProperty ("derby.locale.build.number")).intValue();
-
- String lv = ProductVersionHolder.fullVersionString(major, minor, maint, false, build);
-
-
- localAW.println (Main.getTextMessage ("SIF01.S", lv));
-
-
- }
- catch (IOException ioe) {
-
- //This case is a bit ugly. If we get an IOException, we return
- //null. Though this correctly reflects that the product is not
- //available for use, it may be confusing to users that we swallow
- //the IO error here.
-
- localAW.println("Could not get locale properties from : " + is);
- }
- }
-
- }
- catch (Throwable t) {
- localAW.println ("Could not load resource: " + localeResource);
- localAW.println ("Exception: " + t);
- }
-
- }
-
-
- localAW.println (sep);
-
- } // end of reportLocales
-
- /* for arguments, choose from one of:*/
- private static final String EMBEDDED = "embedded";
-
- /* you can add this if you like*/
- private static final String TOOLS = "tools";
-
- private static final String NET = "server";
- private static final String CLIENT = "client";
-
- /* you can add this if you like */
-
- private static final String MAINUSAGESTRING = "java org.apache.derby.tools.sysinfo -cp";
-
- private static final String USAGESTRINGPARTA = MAINUSAGESTRING + " [ [ " + EMBEDDED + " ][ " + NET + " ][ " + CLIENT + "] [ " + TOOLS + " ] [ ";
- private static final String USAGESTRINGPARTB = ".class ] ]";
-
- static void useMe(String[] args, java.io.PrintWriter pw) {
- java.io.PrintWriter localPW = pw;
-
- if (localPW == null)
- {
- localPW = new java.io.PrintWriter(System.out);
- }
-
-
- int length = args.length;
- if (length==1) {
-
- try {
- tryAllClasspaths(localPW);
-
- }
-
- catch (Throwable t) {
-
- }
- }
- else {
- try {
- trySomeClasspaths(args, localPW);
- }
-
- catch (Throwable t) {
-
- }
- }
-
- }
-
-
-
-
-
- private static void tryAllClasspaths(java.io.PrintWriter localPW) throws Throwable {
- localPW.println(Main.getTextMessage("SIF08.B"));
- localPW.println(Main.getTextMessage("SIF08.C", MAINUSAGESTRING + " args"));
- StringBuffer successes = new StringBuffer(Main.getTextMessage("SIF08.D")+ crLf());
- StringBuffer failures = new StringBuffer(crLf() + Main.getTextMessage("SIF08.E") + crLf());
- tryCoreClasspath(successes, failures);
- tryNetClasspath(successes, failures);
- tryClientClasspath(successes, failures);
- tryUtilsClasspath(successes, failures);
- localPW.println(successes.toString());
- if (!failures.toString().equals(crLf() + Main.getTextMessage("SIF08.E") + crLf())) {
- localPW.println(failures.toString());
- }
- else {
-
- localPW.println(Main.getTextMessage("SIF08.F"));
- }
- localPW.flush();
- }
-
- private static void trySomeClasspaths(String[] args, java.io.PrintWriter localPW) throws Throwable {
-
- boolean seenArg = false;
- StringBuffer successes = new StringBuffer(Main.getTextMessage("SIF08.D")+ crLf());
- StringBuffer failures = new StringBuffer(crLf() + Main.getTextMessage("SIF08.E") + crLf());
-
- if (argumentsContain(args, EMBEDDED))
- {
-
- tryCoreClasspath(successes, failures);
- seenArg =true;
-
- }
- if (argumentsContain(args,NET)) {
- tryNetClasspath(successes, failures);
- seenArg =true;
-
- }
- if (argumentsContain(args,CLIENT)) {
- tryClientClasspath(successes, failures);
- seenArg =true;
-
- }
-
- if (argumentsContain(args,TOOLS) || argumentsContain(args,"utils")) {
- tryUtilsClasspath(successes, failures);
- seenArg =true;
-
- }
-
-
- String userclass = argumentMatches(args, ".class");
- if (!userclass.equals("")) {
- tryMyClasspath(argumentMatches(args, ".class"), Main.getTextMessage("SIF08.H", userclass), successes, failures);
- seenArg =true;
- }
-
- if (seenArg)
- {
-
- localPW.println(successes.toString());
- if (!failures.toString().equals(crLf() + Main.getTextMessage("SIF08.E") + crLf())) {
- localPW.println(failures.toString());
- }
- else {
-
- localPW.println(Main.getTextMessage("SIF08.F"));
- }
- }
- else
- {
- localPW.println(Main.getTextMessage("SIF08.A", USAGESTRINGPARTA, USAGESTRINGPARTB));
- }
- localPW.flush();
-
- }
-
- private static void tryCoreClasspath(StringBuffer successes, StringBuffer failures) {
- tryMyClasspath("org.apache.derby.database.Database", Main.getTextMessage("SIF08.J","derby.jar" ), successes, failures);
- }
- private static void tryNetClasspath(StringBuffer successes, StringBuffer failures) {
- tryMyClasspath("org.apache.derby.drda.NetworkServerControl", Main.getTextMessage("SIF08.I", "derbynet.jar"), successes, failures);
- }
- private static void tryClientClasspath(StringBuffer successes, StringBuffer failures) {
- tryMyClasspath("com.ibm.db2.jcc.DB2Driver", Main.getTextMessage("SIF08.L", "db2jcc.jar"), successes, failures);
- }
-
- private static void tryUtilsClasspath(StringBuffer successes, StringBuffer failures) {
- tryMyClasspath("org.apache.derby.tools.ij", Main.getTextMessage("SIF08.Q", "derbytools.jar"), successes, failures);
- }
-
- private static void tryMyClasspath(String cn, String library, StringBuffer successes, StringBuffer failures) {
-
- try {
- Class.forName(cn);
- successes.append(found(cn, library));
- }
-
- catch (Throwable t) {
-
- failures.append(notFound(cn, library));
-
- }
-
-
- }
-
- private static void tryAsResource(String cn, String library, StringBuffer successes, StringBuffer failures) {
-
- try {
- java.io.InputStream in = cn.getClass().getResourceAsStream(cn);
- in.close();
- successes.append(found(cn, library));
- }
-
- catch (Throwable t) {
- failures.append(notFound(cn, library));
-
- }
-
- }
-
- private static String found(String cn, String library) {
- StringBuffer temp = new StringBuffer(crLf());
- temp.append(" " + library);
- temp.append(crLf());
- temp.append(crLf());
- return temp.toString();
- }
- private static String notFound(String cn, String library) {
-
- StringBuffer temp = new StringBuffer(crLf());
- temp.append(" " + library);
- temp.append(crLf());
- temp.append(" " + Main.getTextMessage("SIF08.U", cn));
- temp.append(crLf());
- temp.append(crLf());
- return temp.toString();
- }
-
- private static String crLf() {
- return System.getProperty("line.separator");
- }
-
- private static String lookForMainArg(String[] args, java.io.PrintWriter localPW)
- {
- int length=args.length;
- String[] legalargs = new String[1];
- legalargs[0] = EMBEDDED;
-
- int argsfound = 0;
- String whichargument="";
-
- for (int i = 0; i < length; i++) {
-
- for (int j=0; j < legalargs.length; j++) {
- if (args[i].toUpperCase(java.util.Locale.ENGLISH).equals(legalargs[j].toUpperCase(java.util.Locale.ENGLISH))) {
- argsfound++;
- whichargument=legalargs[j];
- }
- }
- }
- if (argsfound > 1 || argsfound < 1) {
- localPW.println(Main.getTextMessage("SIF08.A", USAGESTRINGPARTA, USAGESTRINGPARTB));
- return "";
- }
- return whichargument;
- }
-
- private static boolean argumentsContain(String[] args, String s) {
- for (int i = 0; i < args.length; i++) {
- if (args[i].equalsIgnoreCase(s))
- return true;
- }
- return false;
-
- }
-
- private static String argumentMatches(String[] args, String ss) {
- String userclass = "";
- int length = args.length;
- for (int i = 0; i < length; i++) {
- if (args[i].endsWith(ss)) {
- userclass = args[i].substring(0,args[i].length()-6) ;
-
- }
-
- }
- return userclass;
- }
-
- /*
- ** Code related to loading info fromjar files.
- */
-
- private static final String infoNames[] = {
-
- "org/apache/derby/info/" +
- org.apache.derby.iapi.services.info.ProductGenusNames.DBMS +
- ".properties",
-
-
- "org/apache/derby/info/" +
- org.apache.derby.iapi.services.info.ProductGenusNames.TOOLS +
- ".properties",
-
- "org/apache/derby/info/" +
- org.apache.derby.iapi.services.info.ProductGenusNames.NET +
- ".properties"
- };
-
- public static ZipInfoProperties[] getAllInfo(String classpath)
- {
- try
- {
- if (classpath != null) {
- String cp [] = parseClasspath(classpath);
- Vector v = new Vector();
- for (int i = 0; i < cp.length; i++)
- {
- ZipInfoProperties zip = checkForInfo(cp[i]);
- if (zip != null)
- {
- v.addElement(zip);
- }
- }
- if (v.size() > 0)
- {
- ZipInfoProperties zips[] = new ZipInfoProperties[v.size()];
- v.copyInto(zips);
- return zips;
- }
- }
- return loadZipFromResource();
-
- }
- catch (SecurityException se)
- {
- ZipInfoProperties zip[] = new ZipInfoProperties[1];
- zip[0] = new ZipInfoProperties(null);
- zip[0].setLocation (Main.getTextMessage ("SIF03.C"));
- return zip;
- }
- }
-
- /**
- This method returns exactly one ZipInfoProperty in the array.
- If it is able to load the sysinfo file as a resource, it returns
- the ZipInfoProperty associated with that. Otherwise, the ZipInfoProperty
- will be empty.
- */
- private static ZipInfoProperties [] loadZipFromResource()
- {
- java.util.ArrayList al = new java.util.ArrayList();
-
- for (int i = 0; i < infoNames.length; i++)
- {
- String resource = "/".concat(infoNames[i]);
-
- InputStream is = new Main().getClass().getResourceAsStream(resource);
- if (is == null)
- continue;
-
- ZipInfoProperties ze = new ZipInfoProperties(ProductVersionHolder.getProductVersionHolderFromMyEnv(is));
- ze.setLocation(resource);
-
- al.add(ze);
- }
-
- if (al.size() == 0)
- {
- return null;
- }
-
- ZipInfoProperties[] zip = new ZipInfoProperties[al.size()];
-
- al.toArray(zip);
-
- return zip;
- }
-
- private static String [] parseClasspath(String cp)
- {
- StringTokenizer st = new StringTokenizer(cp, File.pathSeparator);
- int count = st.countTokens();
- if (count == 0)
- {
- return null;
- }
-
- String vals[] = new String[count];
- for (int i =0; i < count; i++)
- {
- vals[i] = st.nextToken();
- }
- return vals;
- }
-
- private static ZipInfoProperties checkForInfo(String cpEntry)
- {
- File f = new File(cpEntry);
- if ( ! f.exists())
- {
- return null;
- }
-
- if (f.isDirectory())
- {
- ZipInfoProperties zip = checkDirectory(cpEntry);
- return zip;
- }
-
- if (f.isFile())
- {
- ZipInfoProperties zip = checkFile(cpEntry);
- return zip;
- }
- return null;
-
-
- }
-
- private static ZipInfoProperties checkDirectory(String dirname)
- {
- boolean foundOne = false;
- File f = null;
- for (int i = 0; i < infoNames.length; i++)
- {
- String localSysinfo = infoNames[i].replace('/', File.separatorChar);
- f = new File(dirname, localSysinfo);
- if (f.exists())
- {
- foundOne = true;
- break;
- }
- }
-
- if (!foundOne || (f == null))
- {
- return null;
- }
-
- try
- {
- InputStream bis = new FileInputStream(f);
-
- ZipInfoProperties zip = new ZipInfoProperties(ProductVersionHolder.getProductVersionHolderFromMyEnv(bis));
- zip.setLocation(new File(dirname).getCanonicalPath().replace('/', File.separatorChar));
- return zip;
- }
- catch (IOException ioe)
- {
- return null;
- }
-
- }
-
- private static ZipInfoProperties checkFile(String filename)
- {
- // try to create a ZipFile from it
-
- // Check to see if it's a version of db2jcc.jar and if so, report the version number.
- if (filename.indexOf("db2jcc") >= 0)
- {
- Class c = null;
- Method m = null;
- Object o = null;
- Integer build = null;
- Integer major = null;
- Integer minor = null;
- try
- {
- try
- {
- c = Class.forName("com.ibm.db2.jcc.DB2Driver");
- m = c.getMethod("getJCCBuildNumber", null);
- o = c.newInstance();
- build = (Integer)m.invoke(o,null);
- } catch (ClassNotFoundException cnfe) {
- c = Class.forName("com.ibm.db2.jcc.DB2Version");
- m = c.getMethod("getBuildNumber", null);
- o = c.newInstance();
- build = (Integer)m.invoke(o,null);
- }
- m = c.getMethod("getMajorVersion", null);
- major = (Integer)m.invoke(o,null);
- m = c.getMethod("getMinorVersion", null);
- minor = (Integer)m.invoke(o,null);
-
- ProductVersionHolder jccVersion = ProductVersionHolder.getProductVersionHolder(
- "IBM Corp.",
- "DB2 Java Common Client",
- "DRDA:jcc",
- major.intValue(),
- minor.intValue(),
- 0,
- 0,
- build.intValue(),
- Boolean.FALSE);
-
- ZipInfoProperties zip = new ZipInfoProperties(jccVersion);
-
- zip.setLocation(new File(filename).getCanonicalPath().replace('/', File.separatorChar));
- return zip;
- } catch (Exception e) { return null; }
- }
-
- try
- {
- ZipFile zf = new ZipFile(filename);
- // try to get a ZipEntry from the ZipFile
-
- ZipEntry thisEntry = null;
-
- for (int i =0; i < infoNames.length; i++)
- {
- thisEntry = zf.getEntry(infoNames[i]);
- if (thisEntry != null)
- {
- break;
- }
- }
-
- if (thisEntry == null)
- {
- return null;
- }
-
- InputStream bis = zf.getInputStream(thisEntry);
- if (bis == null)
- {
- return null;
- }
-
- ZipInfoProperties zip = new ZipInfoProperties(ProductVersionHolder.getProductVersionHolderFromMyEnv(bis));
- zip.setLocation(new File(filename).getCanonicalPath().replace('/', File.separatorChar));
- return zip;
-
- }
- catch (IOException ioe)
- {
- //guess not
- return null;
- }
-
- }
-
- /*
- ** Message handling
- */
- private static ResourceBundle getBundle() {
- try {
- return ResourceBundle.getBundle("org.apache.derby.loc.sysinfoMessages");
- } catch (MissingResourceException mre) {
- }
- return null;
- }
-
- public static String getTextMessage(String msgId) {
- return getCompleteMessage(msgId, (Object[]) null);
- }
- public static String getTextMessage(String msgId, Object a1) {
-
- return getCompleteMessage(msgId, new Object[] {a1});
- }
- public static String getTextMessage(String msgId, Object a1, Object a2) {
- return getCompleteMessage(msgId, new Object[] {a1, a2});
- }
- public static String getTextMessage(String msgId, Object a1, Object a2, Object a3) {
- return getCompleteMessage(msgId, new Object[] {a1, a2, a3});
- }
- public static String getTextMessage(String msgId, Object a1, Object a2, Object a3, Object a4) {
- return getCompleteMessage(msgId, new Object[] {a1, a2, a3, a4});
- }
-
- /**
- */
- public static String getCompleteMessage(String msgId, Object[] arguments) {
-
- // we have a base file (sysinfoMessages.properties) so don't give us a last chance.
- return org.apache.derby.iapi.services.i18n.MessageService.formatMessage(getBundle(), msgId, arguments, false);
- }
-} // end of class Main
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.sysinfo
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.impl.tools.sysinfo;
+
+import java.util.Locale;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+import java.io.File;
+import java.util.zip.ZipFile;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.io.FileInputStream;
+import java.util.Vector;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+
+import org.apache.derby.iapi.services.info.PropertyNames;
+import org.apache.derby.iapi.services.info.ProductVersionHolder;
+import org.apache.derby.iapi.services.info.ProductGenusNames;
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.tools.i18n.*;
+
+
+/**
+ <i>Copyright © 1998, Cloudscape, Inc. All rights reserved.</i>
+
+ <P>
+ SysInfo reports values relevant to the Cloudscape product found on
+ the CLASSPATH. It looks for a file called sysinfo.properties in
+ the CLASSPATH using getResourceAsStream. If the file
+ is not found, or some other exception occurs, the
+ value returned will be that set for the key
+ SysInfo.failureTag, or be the value "<info unavailable>".
+
+ <P>
+ This class can be used to print out system information at the
+ command line by issuing the command:
+ <PRE>
+ java com.ibm.db2j.tools.SysInfo.main
+ </PRE>
+ Alternatively, you can use SysInfo within your program to display
+ Cloudscape information; a Cloudscape version string is returned by this Java code:
+ <PRE>
+ new Main().toString();
+ </PRE>
+
+ */
+
+
+public final class Main {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ /**
+ Application entry point for SysInfo. This will print out
+ the Cloudscape product information as well as a snapshot of
+ the System properties.
+ */
+ public static void main(String args[]) {
+ // adjust the application in accordance with derby.ui.locale and derby.ui.codeset
+ LocalizedResource.getInstance();
+
+ LocalizedOutput out;
+
+ //using AppStreamReader(extends InputStreamReader) for conversion into specific codeset
+
+ out = LocalizedResource.OutputWriter();
+
+ // because we're in a static method, we need to
+ // get our own instance variable
+ parseArgs (args);
+
+ if (cptester == true)
+ getClasspathInfo (args, out);
+ else
+ getMainInfo (out, setPause);
+
+ } // end of main (String args[])
+
+public static void getMainInfo (java.io.PrintWriter aw, boolean pause) {
+
+ aw.println (javaSep);
+ reportJavaInfo (aw);
+ aw.println (jbmsSep);
+ reportCloudscape (aw);
+
+ aw.println (sep);
+
+ // Locales info
+ try {
+ reportLocales (aw);
+ }
+ catch (Exception e) {
+
+ aw.println (Main.getTextMessage ("SIF01.Q"));
+ aw.println (Main.getTextMessage ("SIF01.B"));
+ }
+
+
+ if (pause) {
+ pause();
+ }
+
+ } // end of getMainInfo (AppStreamWriter aw, boolean printLicense, boolean pause)
+
+
+ private static boolean setPause = false;
+
+ private static boolean setLicense = false;
+
+ private static boolean cptester = false;
+
+ private static void parseArgs (String args[]) {
+
+ if (args == null) {
+
+ return;
+ }
+
+
+ for (int i = 0; i < args.length; i++) {
+
+ if (args[i].equals ("-pause")) {
+
+ setPause = true;
+ }
+
+ if (args[i].equals ("-cp")) {
+
+ cptester=true;
+ }
+
+ } // end for
+
+ } // end of parseArgs (String args[])
+
+
+ /**
+ For the benefit of DOS box users, this method waits for input
+ before returning
+ */
+ private static void pause () {
+
+ try {
+
+ System.out.print (Main.getTextMessage ("SIF01.C"));
+ BufferedReader br = new BufferedReader (new InputStreamReader (System.in));
+ br.readLine ();
+ }
+ catch (IOException ioe) {
+
+ //just return
+ }
+
+ } // end of pause ()
+
+ /**
+ prints out the jbms info to the specified AppStreamWriter.
+ @param aw the AppStreamWriter to use. If null, System.out is
+ used
+ */
+
+ private static void reportCloudscape (java.io.PrintWriter localAW) {
+
+ String classpath;
+
+ try {
+ classpath = System.getProperty("java.class.path");
+ }
+ catch (SecurityException se) {
+ classpath = null;
+ }
+
+ ZipInfoProperties zip[]= Main.getAllInfo (classpath);
+
+ if (zip != null) {
+
+ for (int i = 0; i < zip.length; i++) {
+
+ String thisInfo = "[" + zip[i].getLocation () + "] " +
+ zip[i].getVersionBuildInfo ();
+
+ localAW.println (thisInfo);
+ }
+ }
+
+ else {
+
+ localAW.println (Main.getTextMessage ("SIF01.D"));
+ }
+
+
+ } // end of reportCloudscape
+
+
+ /**
+ Writes out the relevant info about the Java environment to
+ the specified AppStreamWriter.
+
+ @param aw The AppStreamWriter to write info out to. If this is
+ null, the info is written to System.out
+ */
+
+ private static void reportJavaInfo (java.io.PrintWriter localAW) {
+
+
+
+ localAW.println (Main.getTextMessage ("SIF02.A",
+ getJavaProperty ("java.version")));
+
+ localAW.println (Main.getTextMessage ("SIF02.B",
+ getJavaProperty ("java.vendor")));
+
+ localAW.println (Main.getTextMessage ("SIF02.C",
+ getJavaProperty ("java.home")));
+
+ localAW.println (Main.getTextMessage ("SIF02.D",
+ getJavaProperty ("java.class.path")));
+
+ localAW.println (Main.getTextMessage ("SIF02.E",
+ getJavaProperty ("os.name")));
+
+ localAW.println (Main.getTextMessage ("SIF02.F",
+ getJavaProperty ("os.arch")));
+
+ localAW.println (Main.getTextMessage ("SIF02.G",
+ getJavaProperty ("os.version")));
+
+ localAW.println (Main.getTextMessage ("SIF02.H",
+ getJavaProperty ("user.name")));
+
+ localAW.println (Main.getTextMessage ("SIF02.I",
+ getJavaProperty ("user.home")));
+
+ localAW.println (Main.getTextMessage ("SIF02.J",
+ getJavaProperty ("user.dir")));
+
+ } // end of reportJavaInfo
+
+
+
+ /**
+ Return Java properties from java.lang.System. Will catch
+ SecurityExceptions and note them for displaying information.
+
+ @return the Java property value or a string capturing a
+ security exception.
+ */
+
+ private static String getJavaProperty (String whichProperty) {
+
+ String property;
+ String unavailable = Main.getTextMessage ("SIF01.H");
+
+ try {
+
+ property = System.getProperty (whichProperty, unavailable);
+ return property;
+ }
+ catch (SecurityException se) {
+
+ return Main.getTextMessage ("SIF01.I", se);
+ }
+
+ } // end of getJavaProperty (String whichProperty)
+
+
+
+ /**
+ for use by the main () method
+ */
+
+ private final static String sep = "------------------------------------------------------";
+ private final static String javaSep = Main.getTextMessage ("SIF01.L");
+
+ private final static String jbmsSep = Main.getTextMessage ("SIF01.M");
+
+ private final static String licSep = Main.getTextMessage ("SIF01.N");
+
+ private final static String locSep = Main.getTextMessage ("SIF01.P");
+
+ private final static String curLoc = Main.getTextMessage ("SIF01.T");
+
+ /**
+ The name of the failure tag in the information file.
+ The failure tag's value provides a default value if
+ any other properties are missing.
+ */
+ private final static String failureTag = Main.getTextMessage ("SIF01.J");
+
+ private static void getClasspathInfo (String args[], java.io.PrintWriter aw) {
+
+ Main.useMe (args, aw);
+ }
+
+
+
+
+ /**
+ Writes out information about the locales with the
+ product.
+
+ @param aw the AppStreamWriter to which the info is written. If this
+ value is null, the info is written to System.out
+
+ */
+ private static void reportLocales (java.io.PrintWriter localAW) { // throws StandardException {
+
+ boolean cur_loc = true;
+
+ localAW.println (locSep);
+
+ // Read all the possible locales, and test for each one, if it loads.
+ // If so, then read the properties, and print them out.
+
+ Locale[] supportedLocales = Locale.getAvailableLocales();
+ String[] stringLocales = new String[supportedLocales.length];
+ for (int i = 0; i < supportedLocales.length; i++)
+ {
+ stringLocales[i] = supportedLocales[i].toString();
+ }
+ java.util.Arrays.sort(stringLocales);
+
+ Properties p = new Properties ();
+ for (int i = 0; i < stringLocales.length; i++) {
+
+ String localeResource =
+ "/org/apache/derby/info/locale_" + stringLocales[i] + ".properties";
+
+ try {
+
+ InputStream is = p.getClass().getResourceAsStream (localeResource);
+
+ if (is == null) {
+// localAW.println("resource is null: " + localeResource);
+ }
+ else {
+
+ try {
+ p.clear();
+ p.load (is);
+ //Displaying Current Locale
+ if (cur_loc)
+ {
+ Locale loc = null;
+ loc = Locale.getDefault();
+ localAW.println(Main.getTextMessage ("SIF01.T") + " [" + loc.getDisplayLanguage() + "/" + loc.getDisplayCountry() + " [" + loc + "]]");
+ cur_loc = false;
+ }
+
+ //Beetle 5079: do not print unlocalized locale names to console, only print locale code.
+ String localeName = p.getProperty("derby.locale.external.name");
+ localeName = localeName.substring(localeName.indexOf("[")+1);
+ localeName = localeName.substring(0,localeName.indexOf("]"));
+
+ localAW.println (Main.getTextMessage ("SIF01.R",
+ localeName));
+
+
+ int major = Integer.valueOf(p.getProperty ("derby.locale.version.major")).intValue();
+ int minor = Integer.valueOf(p.getProperty ("derby.locale.version.minor")).intValue();
+ int maint = Integer.valueOf(p.getProperty ("derby.locale.version.maint")).intValue();
+ int build = Integer.valueOf(p.getProperty ("derby.locale.build.number")).intValue();
+
+ String lv = ProductVersionHolder.fullVersionString(major, minor, maint, false, build);
+
+
+ localAW.println (Main.getTextMessage ("SIF01.S", lv));
+
+
+ }
+ catch (IOException ioe) {
+
+ //This case is a bit ugly. If we get an IOException, we return
+ //null. Though this correctly reflects that the product is not
+ //available for use, it may be confusing to users that we swallow
+ //the IO error here.
+
+ localAW.println("Could not get locale properties from : " + is);
+ }
+ }
+
+ }
+ catch (Throwable t) {
+ localAW.println ("Could not load resource: " + localeResource);
+ localAW.println ("Exception: " + t);
+ }
+
+ }
+
+
+ localAW.println (sep);
+
+ } // end of reportLocales
+
+ /* for arguments, choose from one of:*/
+ private static final String EMBEDDED = "embedded";
+
+ /* you can add this if you like*/
+ private static final String TOOLS = "tools";
+
+ private static final String NET = "server";
+ private static final String CLIENT = "client";
+
+ /* you can add this if you like */
+
+ private static final String MAINUSAGESTRING = "java org.apache.derby.tools.sysinfo -cp";
+
+ private static final String USAGESTRINGPARTA = MAINUSAGESTRING + " [ [ " + EMBEDDED + " ][ " + NET + " ][ " + CLIENT + "] [ " + TOOLS + " ] [ ";
+ private static final String USAGESTRINGPARTB = ".class ] ]";
+
+ static void useMe(String[] args, java.io.PrintWriter pw) {
+ java.io.PrintWriter localPW = pw;
+
+ if (localPW == null)
+ {
+ localPW = new java.io.PrintWriter(System.out);
+ }
+
+
+ int length = args.length;
+ if (length==1) {
+
+ try {
+ tryAllClasspaths(localPW);
+
+ }
+
+ catch (Throwable t) {
+
+ }
+ }
+ else {
+ try {
+ trySomeClasspaths(args, localPW);
+ }
+
+ catch (Throwable t) {
+
+ }
+ }
+
+ }
+
+
+
+
+
+ private static void tryAllClasspaths(java.io.PrintWriter localPW) throws Throwable {
+ localPW.println(Main.getTextMessage("SIF08.B"));
+ localPW.println(Main.getTextMessage("SIF08.C", MAINUSAGESTRING + " args"));
+ StringBuffer successes = new StringBuffer(Main.getTextMessage("SIF08.D")+ crLf());
+ StringBuffer failures = new StringBuffer(crLf() + Main.getTextMessage("SIF08.E") + crLf());
+ tryCoreClasspath(successes, failures);
+ tryNetClasspath(successes, failures);
+ tryClientClasspath(successes, failures);
+ tryUtilsClasspath(successes, failures);
+ localPW.println(successes.toString());
+ if (!failures.toString().equals(crLf() + Main.getTextMessage("SIF08.E") + crLf())) {
+ localPW.println(failures.toString());
+ }
+ else {
+
+ localPW.println(Main.getTextMessage("SIF08.F"));
+ }
+ localPW.flush();
+ }
+
+ private static void trySomeClasspaths(String[] args, java.io.PrintWriter localPW) throws Throwable {
+
+ boolean seenArg = false;
+ StringBuffer successes = new StringBuffer(Main.getTextMessage("SIF08.D")+ crLf());
+ StringBuffer failures = new StringBuffer(crLf() + Main.getTextMessage("SIF08.E") + crLf());
+
+ if (argumentsContain(args, EMBEDDED))
+ {
+
+ tryCoreClasspath(successes, failures);
+ seenArg =true;
+
+ }
+ if (argumentsContain(args,NET)) {
+ tryNetClasspath(successes, failures);
+ seenArg =true;
+
+ }
+ if (argumentsContain(args,CLIENT)) {
+ tryClientClasspath(successes, failures);
+ seenArg =true;
+
+ }
+
+ if (argumentsContain(args,TOOLS) || argumentsContain(args,"utils")) {
+ tryUtilsClasspath(successes, failures);
+ seenArg =true;
+
+ }
+
+
+ String userclass = argumentMatches(args, ".class");
+ if (!userclass.equals("")) {
+ tryMyClasspath(argumentMatches(args, ".class"), Main.getTextMessage("SIF08.H", userclass), successes, failures);
+ seenArg =true;
+ }
+
+ if (seenArg)
+ {
+
+ localPW.println(successes.toString());
+ if (!failures.toString().equals(crLf() + Main.getTextMessage("SIF08.E") + crLf())) {
+ localPW.println(failures.toString());
+ }
+ else {
+
+ localPW.println(Main.getTextMessage("SIF08.F"));
+ }
+ }
+ else
+ {
+ localPW.println(Main.getTextMessage("SIF08.A", USAGESTRINGPARTA, USAGESTRINGPARTB));
+ }
+ localPW.flush();
+
+ }
+
+ private static void tryCoreClasspath(StringBuffer successes, StringBuffer failures) {
+ tryMyClasspath("org.apache.derby.database.Database", Main.getTextMessage("SIF08.J","derby.jar" ), successes, failures);
+ }
+ private static void tryNetClasspath(StringBuffer successes, StringBuffer failures) {
+ tryMyClasspath("org.apache.derby.drda.NetworkServerControl", Main.getTextMessage("SIF08.I", "derbynet.jar"), successes, failures);
+ }
+ private static void tryClientClasspath(StringBuffer successes, StringBuffer failures) {
+ tryMyClasspath("com.ibm.db2.jcc.DB2Driver", Main.getTextMessage("SIF08.L", "db2jcc.jar"), successes, failures);
+ }
+
+ private static void tryUtilsClasspath(StringBuffer successes, StringBuffer failures) {
+ tryMyClasspath("org.apache.derby.tools.ij", Main.getTextMessage("SIF08.Q", "derbytools.jar"), successes, failures);
+ }
+
+ private static void tryMyClasspath(String cn, String library, StringBuffer successes, StringBuffer failures) {
+
+ try {
+ Class.forName(cn);
+ successes.append(found(cn, library));
+ }
+
+ catch (Throwable t) {
+
+ failures.append(notFound(cn, library));
+
+ }
+
+
+ }
+
+ private static void tryAsResource(String cn, String library, StringBuffer successes, StringBuffer failures) {
+
+ try {
+ java.io.InputStream in = cn.getClass().getResourceAsStream(cn);
+ in.close();
+ successes.append(found(cn, library));
+ }
+
+ catch (Throwable t) {
+ failures.append(notFound(cn, library));
+
+ }
+
+ }
+
+ private static String found(String cn, String library) {
+ StringBuffer temp = new StringBuffer(crLf());
+ temp.append(" " + library);
+ temp.append(crLf());
+ temp.append(crLf());
+ return temp.toString();
+ }
+ private static String notFound(String cn, String library) {
+
+ StringBuffer temp = new StringBuffer(crLf());
+ temp.append(" " + library);
+ temp.append(crLf());
+ temp.append(" " + Main.getTextMessage("SIF08.U", cn));
+ temp.append(crLf());
+ temp.append(crLf());
+ return temp.toString();
+ }
+
+ private static String crLf() {
+ return System.getProperty("line.separator");
+ }
+
+ private static String lookForMainArg(String[] args, java.io.PrintWriter localPW)
+ {
+ int length=args.length;
+ String[] legalargs = new String[1];
+ legalargs[0] = EMBEDDED;
+
+ int argsfound = 0;
+ String whichargument="";
+
+ for (int i = 0; i < length; i++) {
+
+ for (int j=0; j < legalargs.length; j++) {
+ if (args[i].toUpperCase(java.util.Locale.ENGLISH).equals(legalargs[j].toUpperCase(java.util.Locale.ENGLISH))) {
+ argsfound++;
+ whichargument=legalargs[j];
+ }
+ }
+ }
+ if (argsfound > 1 || argsfound < 1) {
+ localPW.println(Main.getTextMessage("SIF08.A", USAGESTRINGPARTA, USAGESTRINGPARTB));
+ return "";
+ }
+ return whichargument;
+ }
+
+ private static boolean argumentsContain(String[] args, String s) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equalsIgnoreCase(s))
+ return true;
+ }
+ return false;
+
+ }
+
+ private static String argumentMatches(String[] args, String ss) {
+ String userclass = "";
+ int length = args.length;
+ for (int i = 0; i < length; i++) {
+ if (args[i].endsWith(ss)) {
+ userclass = args[i].substring(0,args[i].length()-6) ;
+
+ }
+
+ }
+ return userclass;
+ }
+
+ /*
+ ** Code related to loading info fromjar files.
+ */
+
+ private static final String infoNames[] = {
+
+ "org/apache/derby/info/" +
+ org.apache.derby.iapi.services.info.ProductGenusNames.DBMS +
+ ".properties",
+
+
+ "org/apache/derby/info/" +
+ org.apache.derby.iapi.services.info.ProductGenusNames.TOOLS +
+ ".properties",
+
+ "org/apache/derby/info/" +
+ org.apache.derby.iapi.services.info.ProductGenusNames.NET +
+ ".properties"
+ };
+
+ public static ZipInfoProperties[] getAllInfo(String classpath)
+ {
+ try
+ {
+ if (classpath != null) {
+ String cp [] = parseClasspath(classpath);
+ Vector v = new Vector();
+ for (int i = 0; i < cp.length; i++)
+ {
+ ZipInfoProperties zip = checkForInfo(cp[i]);
+ if (zip != null)
+ {
+ v.addElement(zip);
+ }
+ }
+ if (v.size() > 0)
+ {
+ ZipInfoProperties zips[] = new ZipInfoProperties[v.size()];
+ v.copyInto(zips);
+ return zips;
+ }
+ }
+ return loadZipFromResource();
+
+ }
+ catch (SecurityException se)
+ {
+ ZipInfoProperties zip[] = new ZipInfoProperties[1];
+ zip[0] = new ZipInfoProperties(null);
+ zip[0].setLocation (Main.getTextMessage ("SIF03.C"));
+ return zip;
+ }
+ }
+
+ /**
+ This method returns exactly one ZipInfoProperty in the array.
+ If it is able to load the sysinfo file as a resource, it returns
+ the ZipInfoProperty associated with that. Otherwise, the ZipInfoProperty
+ will be empty.
+ */
+ private static ZipInfoProperties [] loadZipFromResource()
+ {
+ java.util.ArrayList al = new java.util.ArrayList();
+
+ for (int i = 0; i < infoNames.length; i++)
+ {
+ String resource = "/".concat(infoNames[i]);
+
+ InputStream is = new Main().getClass().getResourceAsStream(resource);
+ if (is == null)
+ continue;
+
+ ZipInfoProperties ze = new ZipInfoProperties(ProductVersionHolder.getProductVersionHolderFromMyEnv(is));
+ ze.setLocation(resource);
+
+ al.add(ze);
+ }
+
+ if (al.size() == 0)
+ {
+ return null;
+ }
+
+ ZipInfoProperties[] zip = new ZipInfoProperties[al.size()];
+
+ al.toArray(zip);
+
+ return zip;
+ }
+
+ private static String [] parseClasspath(String cp)
+ {
+ StringTokenizer st = new StringTokenizer(cp, File.pathSeparator);
+ int count = st.countTokens();
+ if (count == 0)
+ {
+ return null;
+ }
+
+ String vals[] = new String[count];
+ for (int i =0; i < count; i++)
+ {
+ vals[i] = st.nextToken();
+ }
+ return vals;
+ }
+
+ private static ZipInfoProperties checkForInfo(String cpEntry)
+ {
+ File f = new File(cpEntry);
+ if ( ! f.exists())
+ {
+ return null;
+ }
+
+ if (f.isDirectory())
+ {
+ ZipInfoProperties zip = checkDirectory(cpEntry);
+ return zip;
+ }
+
+ if (f.isFile())
+ {
+ ZipInfoProperties zip = checkFile(cpEntry);
+ return zip;
+ }
+ return null;
+
+
+ }
+
+ private static ZipInfoProperties checkDirectory(String dirname)
+ {
+ boolean foundOne = false;
+ File f = null;
+ for (int i = 0; i < infoNames.length; i++)
+ {
+ String localSysinfo = infoNames[i].replace('/', File.separatorChar);
+ f = new File(dirname, localSysinfo);
+ if (f.exists())
+ {
+ foundOne = true;
+ break;
+ }
+ }
+
+ if (!foundOne || (f == null))
+ {
+ return null;
+ }
+
+ try
+ {
+ InputStream bis = new FileInputStream(f);
+
+ ZipInfoProperties zip = new ZipInfoProperties(ProductVersionHolder.getProductVersionHolderFromMyEnv(bis));
+ zip.setLocation(new File(dirname).getCanonicalPath().replace('/', File.separatorChar));
+ return zip;
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
+
+ }
+
+ private static ZipInfoProperties checkFile(String filename)
+ {
+ // try to create a ZipFile from it
+
+ // Check to see if it's a version of db2jcc.jar and if so, report the version number.
+ if (filename.indexOf("db2jcc") >= 0)
+ {
+ Class c = null;
+ Method m = null;
+ Object o = null;
+ Integer build = null;
+ Integer major = null;
+ Integer minor = null;
+ try
+ {
+ try
+ {
+ c = Class.forName("com.ibm.db2.jcc.DB2Driver");
+ m = c.getMethod("getJCCBuildNumber", null);
+ o = c.newInstance();
+ build = (Integer)m.invoke(o,null);
+ } catch (ClassNotFoundException cnfe) {
+ c = Class.forName("com.ibm.db2.jcc.DB2Version");
+ m = c.getMethod("getBuildNumber", null);
+ o = c.newInstance();
+ build = (Integer)m.invoke(o,null);
+ }
+ m = c.getMethod("getMajorVersion", null);
+ major = (Integer)m.invoke(o,null);
+ m = c.getMethod("getMinorVersion", null);
+ minor = (Integer)m.invoke(o,null);
+
+ ProductVersionHolder jccVersion = ProductVersionHolder.getProductVersionHolder(
+ "IBM Corp.",
+ "DB2 Java Common Client",
+ "DRDA:jcc",
+ major.intValue(),
+ minor.intValue(),
+ 0,
+ 0,
+ build.intValue(),
+ Boolean.FALSE);
+
+ ZipInfoProperties zip = new ZipInfoProperties(jccVersion);
+
+ zip.setLocation(new File(filename).getCanonicalPath().replace('/', File.separatorChar));
+ return zip;
+ } catch (Exception e) { return null; }
+ }
+
+ try
+ {
+ ZipFile zf = new ZipFile(filename);
+ // try to get a ZipEntry from the ZipFile
+
+ ZipEntry thisEntry = null;
+
+ for (int i =0; i < infoNames.length; i++)
+ {
+ thisEntry = zf.getEntry(infoNames[i]);
+ if (thisEntry != null)
+ {
+ break;
+ }
+ }
+
+ if (thisEntry == null)
+ {
+ return null;
+ }
+
+ InputStream bis = zf.getInputStream(thisEntry);
+ if (bis == null)
+ {
+ return null;
+ }
+
+ ZipInfoProperties zip = new ZipInfoProperties(ProductVersionHolder.getProductVersionHolderFromMyEnv(bis));
+ zip.setLocation(new File(filename).getCanonicalPath().replace('/', File.separatorChar));
+ return zip;
+
+ }
+ catch (IOException ioe)
+ {
+ //guess not
+ return null;
+ }
+
+ }
+
+ /*
+ ** Message handling
+ */
+ private static ResourceBundle getBundle() {
+ try {
+ return ResourceBundle.getBundle("org.apache.derby.loc.sysinfoMessages");
+ } catch (MissingResourceException mre) {
+ }
+ return null;
+ }
+
+ public static String getTextMessage(String msgId) {
+ return getCompleteMessage(msgId, (Object[]) null);
+ }
+ public static String getTextMessage(String msgId, Object a1) {
+
+ return getCompleteMessage(msgId, new Object[] {a1});
+ }
+ public static String getTextMessage(String msgId, Object a1, Object a2) {
+ return getCompleteMessage(msgId, new Object[] {a1, a2});
+ }
+ public static String getTextMessage(String msgId, Object a1, Object a2, Object a3) {
+ return getCompleteMessage(msgId, new Object[] {a1, a2, a3});
+ }
+ public static String getTextMessage(String msgId, Object a1, Object a2, Object a3, Object a4) {
+ return getCompleteMessage(msgId, new Object[] {a1, a2, a3, a4});
+ }
+
+ /**
+ */
+ public static String getCompleteMessage(String msgId, Object[] arguments) {
+
+ // we have a base file (sysinfoMessages.properties) so don't give us a last chance.
+ return org.apache.derby.iapi.services.i18n.MessageService.formatMessage(getBundle(), msgId, arguments, false);
+ }
+} // end of class Main
+
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/ZipInfoProperties.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/ZipInfoProperties.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/impl/tools/sysinfo/ZipInfoProperties.java Fri Sep 24 10:33:20 2004
@@ -1,77 +1,77 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.impl.tools.sysinfo
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-//ZipInfoProperties
-
-package org.apache.derby.impl.tools.sysinfo;
-
-import java.util.Properties;
-import java.io.OutputStream;
-import org.apache.derby.iapi.services.info.PropertyNames;
-import org.apache.derby.iapi.services.info.ProductVersionHolder;
-
-public class ZipInfoProperties // extends Properties
- /**
- IBM Copyright © notice.
- */
-
-{ private static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- private final ProductVersionHolder version;
- /**
- full path to zip (or expanded zip)
- C:/cloudscape/lib/tools.zip
- -or-
- D:\myWorkDir\cloudscape\lib\ *expanded*
-
- The base name (at the end) should be the same as the zipNameString
- */
- private String location;
-
- ZipInfoProperties(ProductVersionHolder version) {
- this.version = version;
- }
-
- /**
- Method to get only the "interesting" pieces of information
- for the customer, namely the version number (2.0.1) and
- the beta status and the build number
- @return a value for displaying to the user via Sysinfo
- */
- public String getVersionBuildInfo()
- {
- if (version == null)
- {
- return Main.getTextMessage ("SIF04.C");
- }
-
- if ("DRDA:jcc".equals(version.getProductTechnologyName()))
- return version.getSimpleVersionString() + " - (" + version.getBuildNumber() + ")";
-
- return version.getVersionBuildString(true);
-
- }
-
- public String getLocation()
- {
- if (location == null)
- return Main.getTextMessage ("SIF01.H");
- return location;
- }
-
- void setLocation(String location) {
- this.location = location;
- }
-
-
-
-}
-
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.impl.tools.sysinfo
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+//ZipInfoProperties
+
+package org.apache.derby.impl.tools.sysinfo;
+
+import java.util.Properties;
+import java.io.OutputStream;
+import org.apache.derby.iapi.services.info.PropertyNames;
+import org.apache.derby.iapi.services.info.ProductVersionHolder;
+
+public class ZipInfoProperties // extends Properties
+ /**
+ IBM Copyright © notice.
+ */
+
+{ private static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ private final ProductVersionHolder version;
+ /**
+ full path to zip (or expanded zip)
+ C:/cloudscape/lib/tools.zip
+ -or-
+ D:\myWorkDir\cloudscape\lib\ *expanded*
+
+ The base name (at the end) should be the same as the zipNameString
+ */
+ private String location;
+
+ ZipInfoProperties(ProductVersionHolder version) {
+ this.version = version;
+ }
+
+ /**
+ Method to get only the "interesting" pieces of information
+ for the customer, namely the version number (2.0.1) and
+ the beta status and the build number
+ @return a value for displaying to the user via Sysinfo
+ */
+ public String getVersionBuildInfo()
+ {
+ if (version == null)
+ {
+ return Main.getTextMessage ("SIF04.C");
+ }
+
+ if ("DRDA:jcc".equals(version.getProductTechnologyName()))
+ return version.getSimpleVersionString() + " - (" + version.getBuildNumber() + ")";
+
+ return version.getVersionBuildString(true);
+
+ }
+
+ public String getLocation()
+ {
+ if (location == null)
+ return Main.getTextMessage ("SIF01.H");
+ return location;
+ }
+
+ void setLocation(String location) {
+ this.location = location;
+ }
+
+
+
+}
+
+
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/tools/JDBCDisplayUtil.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/tools/JDBCDisplayUtil.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/tools/JDBCDisplayUtil.java Fri Sep 24 10:33:20 2004
@@ -1,1193 +1,1193 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.tools
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.tools;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Statement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Types;
-
-import java.util.Properties;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-
-import org.apache.derby.impl.tools.ij.ijException;
-
-/**
-
- This class contains utility methods for displaying JDBC objects and results.
-
- <p>
- All of the methods are static. The output stream
- to write to is always passed in, along with the
- JDBC objects to display.
-
- @author ames
- */
-public class JDBCDisplayUtil {
-
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- // used to control display
- static final private int MINWIDTH = 4;
- static private int maxWidth = 128;
- static public boolean showSelectCount = false;
-
- static {
- // initialize the locale support functions to default value of JVM
- LocalizedResource.getInstance();
- }
-
-
- //-----------------------------------------------------------------
- // Methods for initialization resource bundle and codeset's output
-
- /**
- * init method - will init the class to support a locale and
- * codeset based on the derby.ui.locale and derby.ui.codeset
- * properties if exists or using the default values from the JVM.
- */
- static public boolean init() {
- return (LocalizedResource.getInstance() != null);
- }
-
- /**
- * init method - will init the class to support a locale and
- * codeset based on the derby.ui.locale properties and on the
- * given codeset if exists or using the default values from the JVM.
- */
- public static boolean init(String codeset) {
- return init(codeset, null);
- }
-
- /**
- * init method - will init the class to support a locale and
- * codeset based on the given codeset and locale.
- * If the parameters are null it will try to init use derby.ui.locale
- * and derby.ui.codeset properties if exists or using the default
- * values from the JVM.
- */
- public static boolean init(String pCodeset, String pLocale) {
- LocalizedResource.getInstance().init(pCodeset, pLocale,null);
- return true;
- }
-
- //-----------------------------------------------------------------
- // Methods for displaying and checking errors
-
- /**
- Print information about the exception to the given PrintWriter.
- For non-SQLExceptions, does a stack trace. For SQLExceptions,
- print a standard error message and walk the list, if any.
-
- @param out the place to write to
- @param e the exception to display
- */
- static public void ShowException(PrintWriter out, Throwable e) {
- if (e == null) return;
-
- if (e instanceof SQLException)
- ShowSQLException(out, (SQLException)e);
- else
- e.printStackTrace(out);
- }
-
- /**
- Print information about the SQL exception to the given PrintWriter.
- Walk the list of exceptions, if any.
-
- @param out the place to write to
- @param e the exception to display
- */
- static public void ShowSQLException(PrintWriter out, SQLException e) {
- String errorCode;
-
- if (Boolean.getBoolean("ij.showErrorCode")) {
- errorCode = LocalizedResource.getMessage("UT_Error0", LocalizedResource.getNumber(e.getErrorCode()));
- }
- else {
- errorCode = "";
- }
-
- while (e!=null) {
- String p1 = mapNull(e.getSQLState(),LocalizedResource.getMessage("UT_NoSqlst"));
- String p2 = mapNull(e.getMessage(),LocalizedResource.getMessage("UT_NoMessa"));
- out.println(LocalizedResource.getMessage("UT_Error012", p1, p2,errorCode));
- doTrace(out, e);
- e=e.getNextException();
- }
- }
-
- /**
- Print information about the SQL warnings for the connection
- to the given PrintWriter.
- Walks the list of exceptions, if any.
-
- @param out the place to write to
- @param theConnection the connection that may have warnings.
- */
- static public void ShowWarnings(PrintWriter out, Connection theConnection) {
- try {
- // GET CONNECTION WARNINGS
- SQLWarning warning = null;
-
- if (theConnection != null) {
- ShowWarnings(out, theConnection.getWarnings());
- }
-
- if (theConnection != null) {
- theConnection.clearWarnings();
- }
- } catch (SQLException e) {
- ShowSQLException(out, e);
- }
- } // ShowWarnings
-
- /**
- @param out the place to write to
- @param warning the SQLWarning
- */
- static public void ShowWarnings(PrintWriter out, SQLWarning warning) {
- while (warning != null) {
- String p1 = mapNull(warning.getSQLState(),LocalizedResource.getMessage("UT_NoSqlst_7"));
- String p2 = mapNull(warning.getMessage(),LocalizedResource.getMessage("UT_NoMessa_8"));
- out.println(LocalizedResource.getMessage("UT_Warni01", p1, p2));
- warning = warning.getNextWarning();
- }
- }
-
- /**
- Print information about the SQL warnings for the ResultSet
- to the given PrintWriter.
- Walk the list of exceptions, if any.
-
- @param out the place to write to
- @param rs the ResultSet that may have warnings on it
- */
- static public void ShowWarnings(PrintWriter out, ResultSet rs) {
- try {
- // GET RESULTSET WARNINGS
- SQLWarning warning = null;
-
- if (rs != null) {
- ShowWarnings(out, rs.getWarnings());
- }
-
- if (rs != null) {
- rs.clearWarnings();
- }
- } catch (SQLException e) {
- ShowSQLException(out, e);
- }
- } // ShowResultSetWarnings
-
- /**
- Print information about the SQL warnings for the Statement
- to the given PrintWriter.
- Walks the list of exceptions, if any.
-
- @param out the place to write to
- @param s the Statement that may have warnings on it
- */
- static public void ShowWarnings(PrintWriter out, Statement s)
- {
- try {
- // GET STATEMENT WARNINGS
- SQLWarning warning = null;
-
- if (s != null) {
- ShowWarnings(out, s.getWarnings());
- }
-
- if (s != null) {
- s.clearWarnings();
- }
- } catch (SQLException e) {
- ShowSQLException(out, e);
- }
- } // ShowStatementWarnings
-
- //-----------------------------------------------------------------
- // Methods for displaying and checking results
-
- // REMIND: make this configurable...
- static final private int MAX_RETRIES = 0;
-
- /**
- Pretty-print the results of a statement that has been executed.
- If it is a select, gathers and prints the results. Display
- partial results up to the first error.
- If it is not a SELECT, determine if rows were involved or not,
- and print the appropriate message.
-
- @param out the place to write to
- @param stmt the Statement to display
- @param conn the Connection against which the statement was executed
-
- @exception SQLException on JDBC access failure
- */
- static public void DisplayResults(PrintWriter out, Statement stmt, Connection conn )
- throws SQLException
- {
- indent_DisplayResults( out, stmt, conn, 0);
- }
-
- static private void indent_DisplayResults
- (PrintWriter out, Statement stmt, Connection conn, int indentLevel)
- throws SQLException {
-
- checkNotNull(stmt, "Statement");
-
- ResultSet rs = stmt.getResultSet();
- if (rs != null) {
- indent_DisplayResults(out, rs, conn, indentLevel);
- rs.close(); // let the result set go away
- }
- else {
- DisplayUpdateCount(out,stmt.getUpdateCount(), indentLevel);
- }
-
- ShowWarnings(out,stmt);
- } // DisplayResults
-
- /**
- @param out the place to write to
- @param count the update count to display
- @param indentLevel number of tab stops to indent line
- */
- static void DisplayUpdateCount(PrintWriter out, int count, int indentLevel ) {
- if (count == 1) {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_1RowInserUpdatDelet"));
- }
- else if (count >= 0) {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_0RowsInserUpdatDelet", LocalizedResource.getNumber(count)));
- }
- else {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_StateExecu"));
- }
- }
-
- /**
- @param out the place to write to
- @param rs the ResultSet to display
- @param conn the Connection against which the ResultSet was retrieved
-
- @exception SQLException on JDBC access failure
- */
- static public void DisplayResults(PrintWriter out, ResultSet rs, Connection conn)
- throws SQLException
- {
- indent_DisplayResults( out, rs, conn, 0);
- }
-
- static private void indent_DisplayResults
- (PrintWriter out, ResultSet rs, Connection conn, int indentLevel)
- throws SQLException {
- ResultSetMetaData rsmd = rs.getMetaData();
- checkNotNull(rsmd, "ResultSetMetaData");
- Vector nestedResults;
- int numberOfRowsSelected = 0;
-
- // autocommit must be off or the nested cursors
- // are closed when the outer statement completes.
- if (!conn.getAutoCommit())
- nestedResults = new Vector();
- else
- nestedResults = null;
-
- int len = indent_DisplayBanner(out,rsmd, indentLevel);
-
- // When displaying rows, keep going past errors
- // unless/until the maximum # of errors is reached.
- boolean doNext = true;
- int retry = 0;
- while (doNext) {
- try {
- doNext = rs.next();
- if (doNext) {
-
- DisplayRow(out, rs, rsmd, len, nestedResults, conn, indentLevel);
- ShowWarnings(out, rs);
- numberOfRowsSelected++;
- }
- } catch (SQLException e) {
- // REVISIT: might want to check the exception
- // and for some, not bother with the retry.
- if (++retry > MAX_RETRIES)
- throw e;
- else
- ShowSQLException(out, e);
- }
- }
- if (showSelectCount == true) {
- if (numberOfRowsSelected == 1) {
- out.println();
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_1RowSelec"));
- } else if (numberOfRowsSelected >= 0) {
- out.println();
- indentedPrintLine( out, indentLevel,
- LocalizedResource.getMessage("UT_0RowsSelec", LocalizedResource.getNumber(numberOfRowsSelected)));
- }
- }
-
- DisplayNestedResults(out, nestedResults, conn, indentLevel );
- nestedResults = null;
- }
-
- /**
- @param out the place to write to
- @param nr the vector of results
- @param conn the Connection against which the ResultSet was retrieved
- @param indentLevel number of tab stops to indent line
-
- @exception SQLException thrown on access error
- */
- static private void DisplayNestedResults(PrintWriter out, Vector nr, Connection conn, int indentLevel )
- throws SQLException {
-
- if (nr == null) return;
-
- String b=LocalizedResource.getMessage("UT_JDBCDisplayUtil_16");
- String oldString="0";
-
- for (int i=0; i < nr.size(); i++) {
- LocalizedResource.OutputWriter().println();
-
- //just too clever to get the extra +s
- String t = Integer.toString(i);
- if (t.length() > oldString.length()) {
- oldString = t;
- b=b+LocalizedResource.getMessage("UT_JDBCDisplayUtil_17");
- }
-
- LocalizedResource.OutputWriter().println(b);
- LocalizedResource.OutputWriter().println(LocalizedResource.getMessage("UT_Resul0", LocalizedResource.getNumber(i)));
- LocalizedResource.OutputWriter().println(b);
- indent_DisplayResults(out, (ResultSet) nr.elementAt(i), conn, indentLevel);
- }
- }
-
- /**
- Fetch the next row of the result set, and if it
- exists format and display a banner and the row.
-
- @param out the place to write to
- @param rs the ResultSet in use
- @param conn the Connection against which the ResultSet was retrieved
-
- @exception SQLException on JDBC access failure
- */
- static public void DisplayNextRow(PrintWriter out, ResultSet rs, Connection conn )
- throws SQLException
- {
- indent_DisplayNextRow( out, rs, conn, 0 );
- }
-
- static private void indent_DisplayNextRow(PrintWriter out, ResultSet rs, Connection conn, int indentLevel )
- throws SQLException {
-
- Vector nestedResults;
-
- // autocommit must be off or the nested cursors
- // are closed when the outer statement completes.
- if (!conn.getAutoCommit())
- nestedResults = new Vector();
- else
- nestedResults = null;
-
- checkNotNull(rs, "ResultSet");
-
- ResultSetMetaData rsmd = rs.getMetaData();
- checkNotNull(rsmd, "ResultSetMetaData");
-
- // Only print stuff out if there is a row to be had.
- if (rs.next()) {
- int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
- DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
- }
- else {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow"));
- }
-
- ShowWarnings(out, rs);
-
- DisplayNestedResults(out, nestedResults, conn, indentLevel );
- nestedResults = null;
-
- } // DisplayNextRow
-
- /**
- Display the current row of the result set along with
- a banner. Assume the result set is on a row.
-
- @param out the place to write to
- @param rs the ResultSet in use
- @param conn the Connection against which the ResultSet was retrieved
-
- @exception SQLException on JDBC access failure
- */
- static public void DisplayCurrentRow(PrintWriter out, ResultSet rs, Connection conn )
- throws SQLException
- {
- indent_DisplayCurrentRow( out, rs, conn, 0 );
- }
-
- static private void indent_DisplayCurrentRow(PrintWriter out, ResultSet rs, Connection conn, int indentLevel )
- throws SQLException {
-
- Vector nestedResults;
-
- if (rs == null) {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow_19"));
- return;
- }
-
- // autocommit must be off or the nested cursors
- // are closed when the outer statement completes.
- if (!conn.getAutoCommit())
- nestedResults = new Vector();
- else
- nestedResults = null;
-
- ResultSetMetaData rsmd = rs.getMetaData();
- checkNotNull(rsmd, "ResultSetMetaData");
-
- int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
- DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
-
- ShowWarnings(out, rs);
-
- DisplayNestedResults(out, nestedResults, conn, indentLevel );
- nestedResults = null;
-
- } // DisplayNextRow
-
- /**
- Print a banner containing the column labels separated with '|'s
- and a line of '-'s. Each field is as wide as the display
- width reported by the metadata.
-
- @param out the place to write to
- @param rsmd the ResultSetMetaData to use
-
- @exception SQLException on JDBC access failure
- */
- static public int DisplayBanner(PrintWriter out, ResultSetMetaData rsmd )
- throws SQLException
- {
- return indent_DisplayBanner( out, rsmd, 0 );
- }
-
- static private int indent_DisplayBanner(PrintWriter out, ResultSetMetaData rsmd, int indentLevel )
- throws SQLException {
-
- StringBuffer buf = new StringBuffer();
-
- int numCols = rsmd.getColumnCount();
- int rowLen;
-
- // do some precalculation so the buffer is allocated only once
- // buffer is twice as long as the display length plus one for a newline
- rowLen = (numCols - 1); // for the column separators
- for (int i=1; i <= numCols; i++) {
- rowLen += Math.min(maxWidth,
- Math.max((rsmd.isNullable(i) ==
- ResultSetMetaData.columnNoNulls)?
- 0 : MINWIDTH, LocalizedResource.getInstance().getColumnDisplaySize(rsmd, i)));
- }
- buf.ensureCapacity(rowLen);
-
- // get column header info
- // truncate it to the column display width
- // add a bar between each item.
- for (int i=1; i <= numCols; i++) {
-
- if (i>1)
- buf.append('|');
-
- String s = rsmd.getColumnLabel(i);
-
- int w = Math.min(maxWidth,
- Math.max(((rsmd.isNullable(i) ==
- ResultSetMetaData.columnNoNulls)?
- 0 : MINWIDTH), LocalizedResource.getInstance().getColumnDisplaySize(rsmd, i)));
-
- if (s.length() < w) {
- // build a string buffer to hold the whitespace
- StringBuffer blanks = new StringBuffer(s);
- blanks.ensureCapacity(w);
-
- // try to paste on big chunks of space at a time.
- for (int k=blanks.length()+64; k<=w; k+=64)
- blanks.append(
- " ");
- for (int k=blanks.length()+16; k<=w; k+=16)
- blanks.append(" ");
- for (int k=blanks.length()+4; k<=w; k+=4)
- blanks.append(" ");
- for (int k=blanks.length(); k<w; k++)
- blanks.append(' ');
-
- buf.append(blanks);
- // REMIND: could do more cleverness, like keep around
- // past buffers to reuse...
- }
- else if (s.length() > w) {
- if (w > 1)
- buf.append(s.substring(0,w-1));
- if (w > 0)
- buf.append('&');
- }
- else {
- buf.append(s);
- }
- }
-
- buf.setLength(Math.min(rowLen, 1024));
- indentedPrintLine( out, indentLevel, buf);
-
- // now print a row of '-'s
- for (int i=0; i<Math.min(rowLen, 1024); i++)
- buf.setCharAt(i, '-');
- indentedPrintLine( out, indentLevel, buf);
-
- buf = null;
-
- return rowLen;
- } // DisplayBanner
-
- /**
- Print one row of a result set, padding each field to the
- display width and separating them with '|'s
-
- @param out the place to write to
- @param rs the ResultSet to use
- @param rsmd the ResultSetMetaData to use
- @param rowLen
- @param nestedResults
- @param conn
- @param indentLevel number of tab stops to indent line
-
- @exception SQLException thrown on JDBC access failure
- */
- static private void DisplayRow(PrintWriter out, ResultSet rs, ResultSetMetaData rsmd, int rowLen, Vector nestedResults, Connection conn, int indentLevel )
- throws SQLException
- {
- StringBuffer buf = new StringBuffer();
- buf.ensureCapacity(rowLen);
-
- int numCols = rsmd.getColumnCount();
- int i;
-
- // get column header info
- // truncate it to the column display width
- // add a bar between each item.
- for (i=1; i <= numCols; i++){
- if (i>1)
- buf.append('|');
-
- String s;
- switch (rsmd.getColumnType(i)) {
- default:
- s = LocalizedResource.getInstance().getLocalizedString(rs, rsmd, i );
- break;
- case org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT:
- case Types.OTHER:
- {
- Object o = rs.getObject(i);
- if (o == null) { s = "NULL"; }
- else if (o instanceof ResultSet && nestedResults != null)
- {
- s = LocalizedResource.getMessage("UT_Resul0_20", LocalizedResource.getNumber(nestedResults.size()));
- nestedResults.addElement(o);
- }
- else
- {
- try {
- s = rs.getString(i);
- } catch (SQLException se) {
- // oops, they don't support refetching the column
- s = o.toString();
- }
- }
- }
- break;
- }
- if (s==null) s = "NULL";
-
- int w = Math.min(maxWidth,
- Math.max((rsmd.isNullable(i) ==
- ResultSetMetaData.columnNoNulls)?
- 0 : MINWIDTH, LocalizedResource.getInstance().getColumnDisplaySize(rsmd, i)));
- if (s.length() < w) {
- StringBuffer fullS = new StringBuffer(s);
- fullS.ensureCapacity(w);
- for (int k=s.length(); k<w; k++)
- fullS.append(' ');
- s = fullS.toString();
- }
- else if (s.length() > w)
- // add the & marker to know it got cut off
- s = s.substring(0,w-1)+"&";
-
- buf.append(s);
- }
- indentedPrintLine( out, indentLevel, buf);
-
- } // DisplayRow
-
- /**
- Check if an object is null, and if it is, throw an exception
- with an informative parameter about what was null.
- The exception is a run-time exception that is internal to ij.
-
- @param o the object to test
- @param what the information to include in the error if it is null
- */
- public static void checkNotNull(Object o, String what) {
- if (o == null) {
- throw ijException.objectWasNull(what);
- }
- } // checkNotNull
-
- /**
- Map the string to the value if it is null.
-
- @param s the string to test for null
- @param nullValue the value to use if s is null
-
- @return if s is non-null, s; else nullValue.
- */
- static public String mapNull(String s, String nullValue) {
- if (s==null) return nullValue;
- return s;
- }
-
- /**
- If the property ij.exceptionTrace is true, display the stack
- trace to the print stream. Otherwise, do nothing.
-
- @param out the output stream to write to
- @param e the exception to display
- */
- static public void doTrace(PrintWriter out, Exception e) {
- if (Boolean.getBoolean("ij.exceptionTrace")) {
- e.printStackTrace(out);
- out.flush();
- }
- }
-
- static public void setMaxDisplayWidth(int maxDisplayWidth) {
- maxWidth = maxDisplayWidth;
- }
-
- static private void indentedPrintLine( PrintWriter out, int indentLevel, String text )
- {
- indent( out, indentLevel );
- out.println( text );
- }
-
- static private void indentedPrintLine( PrintWriter out, int indentLevel, StringBuffer text )
- {
- indent( out, indentLevel );
- out.println( text );
- }
-
- static private void indent( PrintWriter out, int indentLevel )
- {
- for ( int ictr = 0; ictr < indentLevel; ictr++ ) { out.print( " " ); }
- }
-
- // ================
-
- static public void ShowException(PrintStream out, Throwable e) {
- if (e == null) return;
-
- if (e instanceof SQLException)
- ShowSQLException(out, (SQLException)e);
- else
- e.printStackTrace(out);
- }
-
- static public void ShowSQLException(PrintStream out, SQLException e) {
- String errorCode;
-
- if (Boolean.getBoolean("ij.showErrorCode")) {
- errorCode = " (errorCode = " + e.getErrorCode() + ")";
- }
- else {
- errorCode = "";
- }
-
- while (e!=null) {
- out.println("ERROR "+mapNull(e.getSQLState(),"(no SQLState)")+": "+
- mapNull(e.getMessage(),"(no message)")+errorCode);
- doTrace(out, e);
- e=e.getNextException();
- }
- }
-
- static public void ShowWarnings(PrintStream out, Connection theConnection) {
- try {
- // GET CONNECTION WARNINGS
- SQLWarning warning = null;
-
- if (theConnection != null) {
- ShowWarnings(out, theConnection.getWarnings());
- }
-
- if (theConnection != null) {
- theConnection.clearWarnings();
- }
- } catch (SQLException e) {
- ShowSQLException(out, e);
- }
- } // ShowWarnings
-
- static public void ShowWarnings(PrintStream out, SQLWarning warning) {
- while (warning != null) {
- out.println("WARNING "+
- mapNull(warning.getSQLState(),"(no SQLState)")+": "+
- mapNull(warning.getMessage(),"(no message)"));
- warning = warning.getNextWarning();
- }
- }
-
- static public void ShowWarnings(PrintStream out, ResultSet rs) {
- try {
- // GET RESULTSET WARNINGS
- SQLWarning warning = null;
-
- if (rs != null) {
- ShowWarnings(out, rs.getWarnings());
- }
-
- if (rs != null) {
- rs.clearWarnings();
- }
- } catch (SQLException e) {
- ShowSQLException(out, e);
- }
- } // ShowResultSetWarnings
-
- static public void ShowWarnings(PrintStream out, Statement s)
- {
- try {
- // GET STATEMENT WARNINGS
- SQLWarning warning = null;
-
- if (s != null) {
- ShowWarnings(out, s.getWarnings());
- }
-
- if (s != null) {
- s.clearWarnings();
- }
- } catch (SQLException e) {
- ShowSQLException(out, e);
- }
- } // ShowStatementWarnings
-
- static public void DisplayResults(PrintStream out, Statement stmt, Connection conn )
- throws SQLException
- {
- indent_DisplayResults( out, stmt, conn, 0);
- }
-
- static private void indent_DisplayResults
- (PrintStream out, Statement stmt, Connection conn, int indentLevel)
- throws SQLException {
-
- checkNotNull(stmt, "Statement");
-
- ResultSet rs = stmt.getResultSet();
- if (rs != null) {
- indent_DisplayResults(out, rs, conn, indentLevel);
- rs.close(); // let the result set go away
- }
- else {
- DisplayUpdateCount(out,stmt.getUpdateCount(), indentLevel);
- }
-
- ShowWarnings(out,stmt);
- } // DisplayResults
-
- static void DisplayUpdateCount(PrintStream out, int count, int indentLevel ) {
- if (count == 1) {
- indentedPrintLine( out, indentLevel, "1 row inserted/updated/deleted");
- }
- else if (count >= 0) {
- indentedPrintLine( out, indentLevel, count+" rows inserted/updated/deleted");
- }
- else {
- indentedPrintLine( out, indentLevel, "Statement executed.");
- }
- }
-
- static public void DisplayResults(PrintStream out, ResultSet rs, Connection conn)
- throws SQLException
- {
- indent_DisplayResults( out, rs, conn, 0);
- }
-
- static private void indent_DisplayResults
- (PrintStream out, ResultSet rs, Connection conn, int indentLevel)
- throws SQLException {
- ResultSetMetaData rsmd = rs.getMetaData();
- checkNotNull(rsmd, "ResultSetMetaData");
- Vector nestedResults;
- int numberOfRowsSelected = 0;
-
- // autocommit must be off or the nested cursors
- // are closed when the outer statement completes.
- if (!conn.getAutoCommit())
- nestedResults = new Vector();
- else
- nestedResults = null;
-
- int len = indent_DisplayBanner(out,rsmd, indentLevel);
-
- // When displaying rows, keep going past errors
- // unless/until the maximum # of errors is reached.
- boolean doNext = true;
- int retry = 0;
- while (doNext) {
- try {
- doNext = rs.next();
- if (doNext) {
-
- DisplayRow(out, rs, rsmd, len, nestedResults, conn, indentLevel);
- ShowWarnings(out, rs);
- numberOfRowsSelected++;
- }
- } catch (SQLException e) {
- // REVISIT: might want to check the exception
- // and for some, not bother with the retry.
- if (++retry > MAX_RETRIES)
- throw e;
- else
- ShowSQLException(out, e);
- }
- }
- if (showSelectCount == true) {
- if (numberOfRowsSelected == 1) {
- out.println();
- indentedPrintLine( out, indentLevel, "1 row selected");
- } else if (numberOfRowsSelected >= 0) {
- out.println();
- indentedPrintLine( out, indentLevel, numberOfRowsSelected + " rows selected");
- }
- }
-
- DisplayNestedResults(out, nestedResults, conn, indentLevel );
- nestedResults = null;
- }
-
- static private void DisplayNestedResults(PrintStream out, Vector nr, Connection conn, int indentLevel )
- throws SQLException {
-
- if (nr == null) return;
-
- String s="+ ResultSet #";
- String b="++++++++++++++++";
- String oldString="0";
-
- for (int i=0; i < nr.size(); i++) {
- System.out.println();
-
- //just too clever to get the extra +s
- String t = Integer.toString(i);
- if (t.length() > oldString.length()) {
- oldString = t;
- b=b+"+";
- }
-
- System.out.println(b);
- System.out.println(s+i+" +");
- System.out.println(b);
- indent_DisplayResults(out, (ResultSet) nr.elementAt(i), conn, indentLevel);
- }
- }
-
- static public void DisplayNextRow(PrintStream out, ResultSet rs, Connection conn )
- throws SQLException
- {
- indent_DisplayNextRow( out, rs, conn, 0 );
- }
-
- static private void indent_DisplayNextRow(PrintStream out, ResultSet rs, Connection conn, int indentLevel )
- throws SQLException {
-
- Vector nestedResults;
-
- // autocommit must be off or the nested cursors
- // are closed when the outer statement completes.
- if (!conn.getAutoCommit())
- nestedResults = new Vector();
- else
- nestedResults = null;
-
- checkNotNull(rs, "ResultSet");
-
- ResultSetMetaData rsmd = rs.getMetaData();
- checkNotNull(rsmd, "ResultSetMetaData");
-
- // Only print stuff out if there is a row to be had.
- if (rs.next()) {
- int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
- DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
- }
- else {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow"));
- }
-
- ShowWarnings(out, rs);
-
- DisplayNestedResults(out, nestedResults, conn, indentLevel );
- nestedResults = null;
-
- } // DisplayNextRow
-
- static public void DisplayCurrentRow(PrintStream out, ResultSet rs, Connection conn )
- throws SQLException
- {
- indent_DisplayCurrentRow( out, rs, conn, 0 );
- }
-
- static private void indent_DisplayCurrentRow(PrintStream out, ResultSet rs, Connection conn, int indentLevel )
- throws SQLException {
-
- Vector nestedResults;
-
- if (rs == null) {
- indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow_19"));
- return;
- }
-
- // autocommit must be off or the nested cursors
- // are closed when the outer statement completes.
- if (!conn.getAutoCommit())
- nestedResults = new Vector();
- else
- nestedResults = null;
-
- ResultSetMetaData rsmd = rs.getMetaData();
- checkNotNull(rsmd, "ResultSetMetaData");
-
- int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
- DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
-
- ShowWarnings(out, rs);
-
- DisplayNestedResults(out, nestedResults, conn, indentLevel );
- nestedResults = null;
-
- } // DisplayNextRow
-
- static public int DisplayBanner(PrintStream out, ResultSetMetaData rsmd )
- throws SQLException
- {
- return indent_DisplayBanner( out, rsmd, 0 );
- }
-
- static private int indent_DisplayBanner(PrintStream out, ResultSetMetaData rsmd, int indentLevel )
- throws SQLException {
-
- StringBuffer buf = new StringBuffer();
-
- int numCols = rsmd.getColumnCount();
- int rowLen;
-
- // do some precalculation so the buffer is allocated only once
- // buffer is twice as long as the display length plus one for a newline
- rowLen = (numCols - 1); // for the column separators
- for (int i=1; i <= numCols; i++) {
- rowLen += Math.min(maxWidth,
- Math.max((rsmd.isNullable(i) ==
- ResultSetMetaData.columnNoNulls)?
- 0 : MINWIDTH,
- rsmd.getColumnDisplaySize(i)));
- }
- buf.ensureCapacity(rowLen);
-
- // get column header info
- // truncate it to the column display width
- // add a bar between each item.
- for (int i=1; i <= numCols; i++) {
-
- if (i>1)
- buf.append('|');
-
- String s = rsmd.getColumnLabel(i);
-
- int w = Math.min(maxWidth,
- Math.max(((rsmd.isNullable(i) ==
- ResultSetMetaData.columnNoNulls)?
- 0 : MINWIDTH),
- rsmd.getColumnDisplaySize(i)));
-
- if (s.length() < w) {
- // build a string buffer to hold the whitespace
- StringBuffer blanks = new StringBuffer(s);
- blanks.ensureCapacity(w);
-
- // try to paste on big chunks of space at a time.
- for (int k=blanks.length()+64; k<=w; k+=64)
- blanks.append(
- " ");
- for (int k=blanks.length()+16; k<=w; k+=16)
- blanks.append(" ");
- for (int k=blanks.length()+4; k<=w; k+=4)
- blanks.append(" ");
- for (int k=blanks.length(); k<w; k++)
- blanks.append(' ');
-
- buf.append(blanks);
- // REMIND: could do more cleverness, like keep around
- // past buffers to reuse...
- }
- else if (s.length() > w) {
- if (w > 1)
- buf.append(s.substring(0,w-1));
- if (w > 0)
- buf.append('&');
- }
- else {
- buf.append(s);
- }
- }
-
- buf.setLength(Math.min(rowLen, 1024));
- indentedPrintLine( out, indentLevel, buf);
-
- // now print a row of '-'s
- for (int i=0; i<Math.min(rowLen, 1024); i++)
- buf.setCharAt(i, '-');
- indentedPrintLine( out, indentLevel, buf);
-
- buf = null;
-
- return rowLen;
- } // DisplayBanner
-
- static private void DisplayRow(PrintStream out, ResultSet rs, ResultSetMetaData rsmd, int rowLen, Vector nestedResults, Connection conn, int indentLevel )
- throws SQLException
- {
- StringBuffer buf = new StringBuffer();
- buf.ensureCapacity(rowLen);
-
- int numCols = rsmd.getColumnCount();
- int i;
-
- // get column header info
- // truncate it to the column display width
- // add a bar between each item.
- for (i=1; i <= numCols; i++){
- if (i>1)
- buf.append('|');
-
- String s;
- switch (rsmd.getColumnType(i)) {
- default:
- s = rs.getString(i);
- break;
- case org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT:
- case Types.OTHER:
- {
- Object o = rs.getObject(i);
- if (o == null) { s = "NULL"; }
- else if (o instanceof ResultSet && nestedResults != null)
- {
- s = "ResultSet #"+nestedResults.size();
- nestedResults.addElement(o);
- }
- else
- {
- try {
- s = rs.getString(i);
- } catch (SQLException se) {
- // oops, they don't support refetching the column
- s = o.toString();
- }
- }
- }
- break;
- }
-
- if (s==null) s = "NULL";
-
- int w = Math.min(maxWidth,
- Math.max((rsmd.isNullable(i) ==
- ResultSetMetaData.columnNoNulls)?
- 0 : MINWIDTH,
- rsmd.getColumnDisplaySize(i)));
- if (s.length() < w) {
- StringBuffer fullS = new StringBuffer(s);
- fullS.ensureCapacity(w);
- for (int k=s.length(); k<w; k++)
- fullS.append(' ');
- s = fullS.toString();
- }
- else if (s.length() > w)
- // add the & marker to know it got cut off
- s = s.substring(0,w-1)+"&";
-
- buf.append(s);
- }
- indentedPrintLine( out, indentLevel, buf);
-
- } // DisplayRow
-
- static public void doTrace(PrintStream out, Exception e) {
- if (Boolean.getBoolean("ij.exceptionTrace")) {
- e.printStackTrace(out);
- out.flush();
- }
- }
-
- static private void indentedPrintLine( PrintStream out, int indentLevel, String text )
- {
- indent( out, indentLevel );
- out.println( text );
- }
-
- static private void indentedPrintLine( PrintStream out, int indentLevel, StringBuffer text )
- {
- indent( out, indentLevel );
- out.println( text );
- }
-
- static private void indent( PrintStream out, int indentLevel )
- {
- for ( int ictr = 0; ictr < indentLevel; ictr++ ) { out.print( " " ); }
- }
-
- // ==========================
-}
-
-
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.tools
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.tools;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Types;
+
+import java.util.Properties;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+
+import org.apache.derby.impl.tools.ij.ijException;
+
+/**
+
+ This class contains utility methods for displaying JDBC objects and results.
+
+ <p>
+ All of the methods are static. The output stream
+ to write to is always passed in, along with the
+ JDBC objects to display.
+
+ @author ames
+ */
+public class JDBCDisplayUtil {
+
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ // used to control display
+ static final private int MINWIDTH = 4;
+ static private int maxWidth = 128;
+ static public boolean showSelectCount = false;
+
+ static {
+ // initialize the locale support functions to default value of JVM
+ LocalizedResource.getInstance();
+ }
+
+
+ //-----------------------------------------------------------------
+ // Methods for initialization resource bundle and codeset's output
+
+ /**
+ * init method - will init the class to support a locale and
+ * codeset based on the derby.ui.locale and derby.ui.codeset
+ * properties if exists or using the default values from the JVM.
+ */
+ static public boolean init() {
+ return (LocalizedResource.getInstance() != null);
+ }
+
+ /**
+ * init method - will init the class to support a locale and
+ * codeset based on the derby.ui.locale properties and on the
+ * given codeset if exists or using the default values from the JVM.
+ */
+ public static boolean init(String codeset) {
+ return init(codeset, null);
+ }
+
+ /**
+ * init method - will init the class to support a locale and
+ * codeset based on the given codeset and locale.
+ * If the parameters are null it will try to init use derby.ui.locale
+ * and derby.ui.codeset properties if exists or using the default
+ * values from the JVM.
+ */
+ public static boolean init(String pCodeset, String pLocale) {
+ LocalizedResource.getInstance().init(pCodeset, pLocale,null);
+ return true;
+ }
+
+ //-----------------------------------------------------------------
+ // Methods for displaying and checking errors
+
+ /**
+ Print information about the exception to the given PrintWriter.
+ For non-SQLExceptions, does a stack trace. For SQLExceptions,
+ print a standard error message and walk the list, if any.
+
+ @param out the place to write to
+ @param e the exception to display
+ */
+ static public void ShowException(PrintWriter out, Throwable e) {
+ if (e == null) return;
+
+ if (e instanceof SQLException)
+ ShowSQLException(out, (SQLException)e);
+ else
+ e.printStackTrace(out);
+ }
+
+ /**
+ Print information about the SQL exception to the given PrintWriter.
+ Walk the list of exceptions, if any.
+
+ @param out the place to write to
+ @param e the exception to display
+ */
+ static public void ShowSQLException(PrintWriter out, SQLException e) {
+ String errorCode;
+
+ if (Boolean.getBoolean("ij.showErrorCode")) {
+ errorCode = LocalizedResource.getMessage("UT_Error0", LocalizedResource.getNumber(e.getErrorCode()));
+ }
+ else {
+ errorCode = "";
+ }
+
+ while (e!=null) {
+ String p1 = mapNull(e.getSQLState(),LocalizedResource.getMessage("UT_NoSqlst"));
+ String p2 = mapNull(e.getMessage(),LocalizedResource.getMessage("UT_NoMessa"));
+ out.println(LocalizedResource.getMessage("UT_Error012", p1, p2,errorCode));
+ doTrace(out, e);
+ e=e.getNextException();
+ }
+ }
+
+ /**
+ Print information about the SQL warnings for the connection
+ to the given PrintWriter.
+ Walks the list of exceptions, if any.
+
+ @param out the place to write to
+ @param theConnection the connection that may have warnings.
+ */
+ static public void ShowWarnings(PrintWriter out, Connection theConnection) {
+ try {
+ // GET CONNECTION WARNINGS
+ SQLWarning warning = null;
+
+ if (theConnection != null) {
+ ShowWarnings(out, theConnection.getWarnings());
+ }
+
+ if (theConnection != null) {
+ theConnection.clearWarnings();
+ }
+ } catch (SQLException e) {
+ ShowSQLException(out, e);
+ }
+ } // ShowWarnings
+
+ /**
+ @param out the place to write to
+ @param warning the SQLWarning
+ */
+ static public void ShowWarnings(PrintWriter out, SQLWarning warning) {
+ while (warning != null) {
+ String p1 = mapNull(warning.getSQLState(),LocalizedResource.getMessage("UT_NoSqlst_7"));
+ String p2 = mapNull(warning.getMessage(),LocalizedResource.getMessage("UT_NoMessa_8"));
+ out.println(LocalizedResource.getMessage("UT_Warni01", p1, p2));
+ warning = warning.getNextWarning();
+ }
+ }
+
+ /**
+ Print information about the SQL warnings for the ResultSet
+ to the given PrintWriter.
+ Walk the list of exceptions, if any.
+
+ @param out the place to write to
+ @param rs the ResultSet that may have warnings on it
+ */
+ static public void ShowWarnings(PrintWriter out, ResultSet rs) {
+ try {
+ // GET RESULTSET WARNINGS
+ SQLWarning warning = null;
+
+ if (rs != null) {
+ ShowWarnings(out, rs.getWarnings());
+ }
+
+ if (rs != null) {
+ rs.clearWarnings();
+ }
+ } catch (SQLException e) {
+ ShowSQLException(out, e);
+ }
+ } // ShowResultSetWarnings
+
+ /**
+ Print information about the SQL warnings for the Statement
+ to the given PrintWriter.
+ Walks the list of exceptions, if any.
+
+ @param out the place to write to
+ @param s the Statement that may have warnings on it
+ */
+ static public void ShowWarnings(PrintWriter out, Statement s)
+ {
+ try {
+ // GET STATEMENT WARNINGS
+ SQLWarning warning = null;
+
+ if (s != null) {
+ ShowWarnings(out, s.getWarnings());
+ }
+
+ if (s != null) {
+ s.clearWarnings();
+ }
+ } catch (SQLException e) {
+ ShowSQLException(out, e);
+ }
+ } // ShowStatementWarnings
+
+ //-----------------------------------------------------------------
+ // Methods for displaying and checking results
+
+ // REMIND: make this configurable...
+ static final private int MAX_RETRIES = 0;
+
+ /**
+ Pretty-print the results of a statement that has been executed.
+ If it is a select, gathers and prints the results. Display
+ partial results up to the first error.
+ If it is not a SELECT, determine if rows were involved or not,
+ and print the appropriate message.
+
+ @param out the place to write to
+ @param stmt the Statement to display
+ @param conn the Connection against which the statement was executed
+
+ @exception SQLException on JDBC access failure
+ */
+ static public void DisplayResults(PrintWriter out, Statement stmt, Connection conn )
+ throws SQLException
+ {
+ indent_DisplayResults( out, stmt, conn, 0);
+ }
+
+ static private void indent_DisplayResults
+ (PrintWriter out, Statement stmt, Connection conn, int indentLevel)
+ throws SQLException {
+
+ checkNotNull(stmt, "Statement");
+
+ ResultSet rs = stmt.getResultSet();
+ if (rs != null) {
+ indent_DisplayResults(out, rs, conn, indentLevel);
+ rs.close(); // let the result set go away
+ }
+ else {
+ DisplayUpdateCount(out,stmt.getUpdateCount(), indentLevel);
+ }
+
+ ShowWarnings(out,stmt);
+ } // DisplayResults
+
+ /**
+ @param out the place to write to
+ @param count the update count to display
+ @param indentLevel number of tab stops to indent line
+ */
+ static void DisplayUpdateCount(PrintWriter out, int count, int indentLevel ) {
+ if (count == 1) {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_1RowInserUpdatDelet"));
+ }
+ else if (count >= 0) {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_0RowsInserUpdatDelet", LocalizedResource.getNumber(count)));
+ }
+ else {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_StateExecu"));
+ }
+ }
+
+ /**
+ @param out the place to write to
+ @param rs the ResultSet to display
+ @param conn the Connection against which the ResultSet was retrieved
+
+ @exception SQLException on JDBC access failure
+ */
+ static public void DisplayResults(PrintWriter out, ResultSet rs, Connection conn)
+ throws SQLException
+ {
+ indent_DisplayResults( out, rs, conn, 0);
+ }
+
+ static private void indent_DisplayResults
+ (PrintWriter out, ResultSet rs, Connection conn, int indentLevel)
+ throws SQLException {
+ ResultSetMetaData rsmd = rs.getMetaData();
+ checkNotNull(rsmd, "ResultSetMetaData");
+ Vector nestedResults;
+ int numberOfRowsSelected = 0;
+
+ // autocommit must be off or the nested cursors
+ // are closed when the outer statement completes.
+ if (!conn.getAutoCommit())
+ nestedResults = new Vector();
+ else
+ nestedResults = null;
+
+ int len = indent_DisplayBanner(out,rsmd, indentLevel);
+
+ // When displaying rows, keep going past errors
+ // unless/until the maximum # of errors is reached.
+ boolean doNext = true;
+ int retry = 0;
+ while (doNext) {
+ try {
+ doNext = rs.next();
+ if (doNext) {
+
+ DisplayRow(out, rs, rsmd, len, nestedResults, conn, indentLevel);
+ ShowWarnings(out, rs);
+ numberOfRowsSelected++;
+ }
+ } catch (SQLException e) {
+ // REVISIT: might want to check the exception
+ // and for some, not bother with the retry.
+ if (++retry > MAX_RETRIES)
+ throw e;
+ else
+ ShowSQLException(out, e);
+ }
+ }
+ if (showSelectCount == true) {
+ if (numberOfRowsSelected == 1) {
+ out.println();
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_1RowSelec"));
+ } else if (numberOfRowsSelected >= 0) {
+ out.println();
+ indentedPrintLine( out, indentLevel,
+ LocalizedResource.getMessage("UT_0RowsSelec", LocalizedResource.getNumber(numberOfRowsSelected)));
+ }
+ }
+
+ DisplayNestedResults(out, nestedResults, conn, indentLevel );
+ nestedResults = null;
+ }
+
+ /**
+ @param out the place to write to
+ @param nr the vector of results
+ @param conn the Connection against which the ResultSet was retrieved
+ @param indentLevel number of tab stops to indent line
+
+ @exception SQLException thrown on access error
+ */
+ static private void DisplayNestedResults(PrintWriter out, Vector nr, Connection conn, int indentLevel )
+ throws SQLException {
+
+ if (nr == null) return;
+
+ String b=LocalizedResource.getMessage("UT_JDBCDisplayUtil_16");
+ String oldString="0";
+
+ for (int i=0; i < nr.size(); i++) {
+ LocalizedResource.OutputWriter().println();
+
+ //just too clever to get the extra +s
+ String t = Integer.toString(i);
+ if (t.length() > oldString.length()) {
+ oldString = t;
+ b=b+LocalizedResource.getMessage("UT_JDBCDisplayUtil_17");
+ }
+
+ LocalizedResource.OutputWriter().println(b);
+ LocalizedResource.OutputWriter().println(LocalizedResource.getMessage("UT_Resul0", LocalizedResource.getNumber(i)));
+ LocalizedResource.OutputWriter().println(b);
+ indent_DisplayResults(out, (ResultSet) nr.elementAt(i), conn, indentLevel);
+ }
+ }
+
+ /**
+ Fetch the next row of the result set, and if it
+ exists format and display a banner and the row.
+
+ @param out the place to write to
+ @param rs the ResultSet in use
+ @param conn the Connection against which the ResultSet was retrieved
+
+ @exception SQLException on JDBC access failure
+ */
+ static public void DisplayNextRow(PrintWriter out, ResultSet rs, Connection conn )
+ throws SQLException
+ {
+ indent_DisplayNextRow( out, rs, conn, 0 );
+ }
+
+ static private void indent_DisplayNextRow(PrintWriter out, ResultSet rs, Connection conn, int indentLevel )
+ throws SQLException {
+
+ Vector nestedResults;
+
+ // autocommit must be off or the nested cursors
+ // are closed when the outer statement completes.
+ if (!conn.getAutoCommit())
+ nestedResults = new Vector();
+ else
+ nestedResults = null;
+
+ checkNotNull(rs, "ResultSet");
+
+ ResultSetMetaData rsmd = rs.getMetaData();
+ checkNotNull(rsmd, "ResultSetMetaData");
+
+ // Only print stuff out if there is a row to be had.
+ if (rs.next()) {
+ int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
+ DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
+ }
+ else {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow"));
+ }
+
+ ShowWarnings(out, rs);
+
+ DisplayNestedResults(out, nestedResults, conn, indentLevel );
+ nestedResults = null;
+
+ } // DisplayNextRow
+
+ /**
+ Display the current row of the result set along with
+ a banner. Assume the result set is on a row.
+
+ @param out the place to write to
+ @param rs the ResultSet in use
+ @param conn the Connection against which the ResultSet was retrieved
+
+ @exception SQLException on JDBC access failure
+ */
+ static public void DisplayCurrentRow(PrintWriter out, ResultSet rs, Connection conn )
+ throws SQLException
+ {
+ indent_DisplayCurrentRow( out, rs, conn, 0 );
+ }
+
+ static private void indent_DisplayCurrentRow(PrintWriter out, ResultSet rs, Connection conn, int indentLevel )
+ throws SQLException {
+
+ Vector nestedResults;
+
+ if (rs == null) {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow_19"));
+ return;
+ }
+
+ // autocommit must be off or the nested cursors
+ // are closed when the outer statement completes.
+ if (!conn.getAutoCommit())
+ nestedResults = new Vector();
+ else
+ nestedResults = null;
+
+ ResultSetMetaData rsmd = rs.getMetaData();
+ checkNotNull(rsmd, "ResultSetMetaData");
+
+ int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
+ DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
+
+ ShowWarnings(out, rs);
+
+ DisplayNestedResults(out, nestedResults, conn, indentLevel );
+ nestedResults = null;
+
+ } // DisplayNextRow
+
+ /**
+ Print a banner containing the column labels separated with '|'s
+ and a line of '-'s. Each field is as wide as the display
+ width reported by the metadata.
+
+ @param out the place to write to
+ @param rsmd the ResultSetMetaData to use
+
+ @exception SQLException on JDBC access failure
+ */
+ static public int DisplayBanner(PrintWriter out, ResultSetMetaData rsmd )
+ throws SQLException
+ {
+ return indent_DisplayBanner( out, rsmd, 0 );
+ }
+
+ static private int indent_DisplayBanner(PrintWriter out, ResultSetMetaData rsmd, int indentLevel )
+ throws SQLException {
+
+ StringBuffer buf = new StringBuffer();
+
+ int numCols = rsmd.getColumnCount();
+ int rowLen;
+
+ // do some precalculation so the buffer is allocated only once
+ // buffer is twice as long as the display length plus one for a newline
+ rowLen = (numCols - 1); // for the column separators
+ for (int i=1; i <= numCols; i++) {
+ rowLen += Math.min(maxWidth,
+ Math.max((rsmd.isNullable(i) ==
+ ResultSetMetaData.columnNoNulls)?
+ 0 : MINWIDTH, LocalizedResource.getInstance().getColumnDisplaySize(rsmd, i)));
+ }
+ buf.ensureCapacity(rowLen);
+
+ // get column header info
+ // truncate it to the column display width
+ // add a bar between each item.
+ for (int i=1; i <= numCols; i++) {
+
+ if (i>1)
+ buf.append('|');
+
+ String s = rsmd.getColumnLabel(i);
+
+ int w = Math.min(maxWidth,
+ Math.max(((rsmd.isNullable(i) ==
+ ResultSetMetaData.columnNoNulls)?
+ 0 : MINWIDTH), LocalizedResource.getInstance().getColumnDisplaySize(rsmd, i)));
+
+ if (s.length() < w) {
+ // build a string buffer to hold the whitespace
+ StringBuffer blanks = new StringBuffer(s);
+ blanks.ensureCapacity(w);
+
+ // try to paste on big chunks of space at a time.
+ for (int k=blanks.length()+64; k<=w; k+=64)
+ blanks.append(
+ " ");
+ for (int k=blanks.length()+16; k<=w; k+=16)
+ blanks.append(" ");
+ for (int k=blanks.length()+4; k<=w; k+=4)
+ blanks.append(" ");
+ for (int k=blanks.length(); k<w; k++)
+ blanks.append(' ');
+
+ buf.append(blanks);
+ // REMIND: could do more cleverness, like keep around
+ // past buffers to reuse...
+ }
+ else if (s.length() > w) {
+ if (w > 1)
+ buf.append(s.substring(0,w-1));
+ if (w > 0)
+ buf.append('&');
+ }
+ else {
+ buf.append(s);
+ }
+ }
+
+ buf.setLength(Math.min(rowLen, 1024));
+ indentedPrintLine( out, indentLevel, buf);
+
+ // now print a row of '-'s
+ for (int i=0; i<Math.min(rowLen, 1024); i++)
+ buf.setCharAt(i, '-');
+ indentedPrintLine( out, indentLevel, buf);
+
+ buf = null;
+
+ return rowLen;
+ } // DisplayBanner
+
+ /**
+ Print one row of a result set, padding each field to the
+ display width and separating them with '|'s
+
+ @param out the place to write to
+ @param rs the ResultSet to use
+ @param rsmd the ResultSetMetaData to use
+ @param rowLen
+ @param nestedResults
+ @param conn
+ @param indentLevel number of tab stops to indent line
+
+ @exception SQLException thrown on JDBC access failure
+ */
+ static private void DisplayRow(PrintWriter out, ResultSet rs, ResultSetMetaData rsmd, int rowLen, Vector nestedResults, Connection conn, int indentLevel )
+ throws SQLException
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.ensureCapacity(rowLen);
+
+ int numCols = rsmd.getColumnCount();
+ int i;
+
+ // get column header info
+ // truncate it to the column display width
+ // add a bar between each item.
+ for (i=1; i <= numCols; i++){
+ if (i>1)
+ buf.append('|');
+
+ String s;
+ switch (rsmd.getColumnType(i)) {
+ default:
+ s = LocalizedResource.getInstance().getLocalizedString(rs, rsmd, i );
+ break;
+ case org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT:
+ case Types.OTHER:
+ {
+ Object o = rs.getObject(i);
+ if (o == null) { s = "NULL"; }
+ else if (o instanceof ResultSet && nestedResults != null)
+ {
+ s = LocalizedResource.getMessage("UT_Resul0_20", LocalizedResource.getNumber(nestedResults.size()));
+ nestedResults.addElement(o);
+ }
+ else
+ {
+ try {
+ s = rs.getString(i);
+ } catch (SQLException se) {
+ // oops, they don't support refetching the column
+ s = o.toString();
+ }
+ }
+ }
+ break;
+ }
+ if (s==null) s = "NULL";
+
+ int w = Math.min(maxWidth,
+ Math.max((rsmd.isNullable(i) ==
+ ResultSetMetaData.columnNoNulls)?
+ 0 : MINWIDTH, LocalizedResource.getInstance().getColumnDisplaySize(rsmd, i)));
+ if (s.length() < w) {
+ StringBuffer fullS = new StringBuffer(s);
+ fullS.ensureCapacity(w);
+ for (int k=s.length(); k<w; k++)
+ fullS.append(' ');
+ s = fullS.toString();
+ }
+ else if (s.length() > w)
+ // add the & marker to know it got cut off
+ s = s.substring(0,w-1)+"&";
+
+ buf.append(s);
+ }
+ indentedPrintLine( out, indentLevel, buf);
+
+ } // DisplayRow
+
+ /**
+ Check if an object is null, and if it is, throw an exception
+ with an informative parameter about what was null.
+ The exception is a run-time exception that is internal to ij.
+
+ @param o the object to test
+ @param what the information to include in the error if it is null
+ */
+ public static void checkNotNull(Object o, String what) {
+ if (o == null) {
+ throw ijException.objectWasNull(what);
+ }
+ } // checkNotNull
+
+ /**
+ Map the string to the value if it is null.
+
+ @param s the string to test for null
+ @param nullValue the value to use if s is null
+
+ @return if s is non-null, s; else nullValue.
+ */
+ static public String mapNull(String s, String nullValue) {
+ if (s==null) return nullValue;
+ return s;
+ }
+
+ /**
+ If the property ij.exceptionTrace is true, display the stack
+ trace to the print stream. Otherwise, do nothing.
+
+ @param out the output stream to write to
+ @param e the exception to display
+ */
+ static public void doTrace(PrintWriter out, Exception e) {
+ if (Boolean.getBoolean("ij.exceptionTrace")) {
+ e.printStackTrace(out);
+ out.flush();
+ }
+ }
+
+ static public void setMaxDisplayWidth(int maxDisplayWidth) {
+ maxWidth = maxDisplayWidth;
+ }
+
+ static private void indentedPrintLine( PrintWriter out, int indentLevel, String text )
+ {
+ indent( out, indentLevel );
+ out.println( text );
+ }
+
+ static private void indentedPrintLine( PrintWriter out, int indentLevel, StringBuffer text )
+ {
+ indent( out, indentLevel );
+ out.println( text );
+ }
+
+ static private void indent( PrintWriter out, int indentLevel )
+ {
+ for ( int ictr = 0; ictr < indentLevel; ictr++ ) { out.print( " " ); }
+ }
+
+ // ================
+
+ static public void ShowException(PrintStream out, Throwable e) {
+ if (e == null) return;
+
+ if (e instanceof SQLException)
+ ShowSQLException(out, (SQLException)e);
+ else
+ e.printStackTrace(out);
+ }
+
+ static public void ShowSQLException(PrintStream out, SQLException e) {
+ String errorCode;
+
+ if (Boolean.getBoolean("ij.showErrorCode")) {
+ errorCode = " (errorCode = " + e.getErrorCode() + ")";
+ }
+ else {
+ errorCode = "";
+ }
+
+ while (e!=null) {
+ out.println("ERROR "+mapNull(e.getSQLState(),"(no SQLState)")+": "+
+ mapNull(e.getMessage(),"(no message)")+errorCode);
+ doTrace(out, e);
+ e=e.getNextException();
+ }
+ }
+
+ static public void ShowWarnings(PrintStream out, Connection theConnection) {
+ try {
+ // GET CONNECTION WARNINGS
+ SQLWarning warning = null;
+
+ if (theConnection != null) {
+ ShowWarnings(out, theConnection.getWarnings());
+ }
+
+ if (theConnection != null) {
+ theConnection.clearWarnings();
+ }
+ } catch (SQLException e) {
+ ShowSQLException(out, e);
+ }
+ } // ShowWarnings
+
+ static public void ShowWarnings(PrintStream out, SQLWarning warning) {
+ while (warning != null) {
+ out.println("WARNING "+
+ mapNull(warning.getSQLState(),"(no SQLState)")+": "+
+ mapNull(warning.getMessage(),"(no message)"));
+ warning = warning.getNextWarning();
+ }
+ }
+
+ static public void ShowWarnings(PrintStream out, ResultSet rs) {
+ try {
+ // GET RESULTSET WARNINGS
+ SQLWarning warning = null;
+
+ if (rs != null) {
+ ShowWarnings(out, rs.getWarnings());
+ }
+
+ if (rs != null) {
+ rs.clearWarnings();
+ }
+ } catch (SQLException e) {
+ ShowSQLException(out, e);
+ }
+ } // ShowResultSetWarnings
+
+ static public void ShowWarnings(PrintStream out, Statement s)
+ {
+ try {
+ // GET STATEMENT WARNINGS
+ SQLWarning warning = null;
+
+ if (s != null) {
+ ShowWarnings(out, s.getWarnings());
+ }
+
+ if (s != null) {
+ s.clearWarnings();
+ }
+ } catch (SQLException e) {
+ ShowSQLException(out, e);
+ }
+ } // ShowStatementWarnings
+
+ static public void DisplayResults(PrintStream out, Statement stmt, Connection conn )
+ throws SQLException
+ {
+ indent_DisplayResults( out, stmt, conn, 0);
+ }
+
+ static private void indent_DisplayResults
+ (PrintStream out, Statement stmt, Connection conn, int indentLevel)
+ throws SQLException {
+
+ checkNotNull(stmt, "Statement");
+
+ ResultSet rs = stmt.getResultSet();
+ if (rs != null) {
+ indent_DisplayResults(out, rs, conn, indentLevel);
+ rs.close(); // let the result set go away
+ }
+ else {
+ DisplayUpdateCount(out,stmt.getUpdateCount(), indentLevel);
+ }
+
+ ShowWarnings(out,stmt);
+ } // DisplayResults
+
+ static void DisplayUpdateCount(PrintStream out, int count, int indentLevel ) {
+ if (count == 1) {
+ indentedPrintLine( out, indentLevel, "1 row inserted/updated/deleted");
+ }
+ else if (count >= 0) {
+ indentedPrintLine( out, indentLevel, count+" rows inserted/updated/deleted");
+ }
+ else {
+ indentedPrintLine( out, indentLevel, "Statement executed.");
+ }
+ }
+
+ static public void DisplayResults(PrintStream out, ResultSet rs, Connection conn)
+ throws SQLException
+ {
+ indent_DisplayResults( out, rs, conn, 0);
+ }
+
+ static private void indent_DisplayResults
+ (PrintStream out, ResultSet rs, Connection conn, int indentLevel)
+ throws SQLException {
+ ResultSetMetaData rsmd = rs.getMetaData();
+ checkNotNull(rsmd, "ResultSetMetaData");
+ Vector nestedResults;
+ int numberOfRowsSelected = 0;
+
+ // autocommit must be off or the nested cursors
+ // are closed when the outer statement completes.
+ if (!conn.getAutoCommit())
+ nestedResults = new Vector();
+ else
+ nestedResults = null;
+
+ int len = indent_DisplayBanner(out,rsmd, indentLevel);
+
+ // When displaying rows, keep going past errors
+ // unless/until the maximum # of errors is reached.
+ boolean doNext = true;
+ int retry = 0;
+ while (doNext) {
+ try {
+ doNext = rs.next();
+ if (doNext) {
+
+ DisplayRow(out, rs, rsmd, len, nestedResults, conn, indentLevel);
+ ShowWarnings(out, rs);
+ numberOfRowsSelected++;
+ }
+ } catch (SQLException e) {
+ // REVISIT: might want to check the exception
+ // and for some, not bother with the retry.
+ if (++retry > MAX_RETRIES)
+ throw e;
+ else
+ ShowSQLException(out, e);
+ }
+ }
+ if (showSelectCount == true) {
+ if (numberOfRowsSelected == 1) {
+ out.println();
+ indentedPrintLine( out, indentLevel, "1 row selected");
+ } else if (numberOfRowsSelected >= 0) {
+ out.println();
+ indentedPrintLine( out, indentLevel, numberOfRowsSelected + " rows selected");
+ }
+ }
+
+ DisplayNestedResults(out, nestedResults, conn, indentLevel );
+ nestedResults = null;
+ }
+
+ static private void DisplayNestedResults(PrintStream out, Vector nr, Connection conn, int indentLevel )
+ throws SQLException {
+
+ if (nr == null) return;
+
+ String s="+ ResultSet #";
+ String b="++++++++++++++++";
+ String oldString="0";
+
+ for (int i=0; i < nr.size(); i++) {
+ System.out.println();
+
+ //just too clever to get the extra +s
+ String t = Integer.toString(i);
+ if (t.length() > oldString.length()) {
+ oldString = t;
+ b=b+"+";
+ }
+
+ System.out.println(b);
+ System.out.println(s+i+" +");
+ System.out.println(b);
+ indent_DisplayResults(out, (ResultSet) nr.elementAt(i), conn, indentLevel);
+ }
+ }
+
+ static public void DisplayNextRow(PrintStream out, ResultSet rs, Connection conn )
+ throws SQLException
+ {
+ indent_DisplayNextRow( out, rs, conn, 0 );
+ }
+
+ static private void indent_DisplayNextRow(PrintStream out, ResultSet rs, Connection conn, int indentLevel )
+ throws SQLException {
+
+ Vector nestedResults;
+
+ // autocommit must be off or the nested cursors
+ // are closed when the outer statement completes.
+ if (!conn.getAutoCommit())
+ nestedResults = new Vector();
+ else
+ nestedResults = null;
+
+ checkNotNull(rs, "ResultSet");
+
+ ResultSetMetaData rsmd = rs.getMetaData();
+ checkNotNull(rsmd, "ResultSetMetaData");
+
+ // Only print stuff out if there is a row to be had.
+ if (rs.next()) {
+ int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
+ DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
+ }
+ else {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow"));
+ }
+
+ ShowWarnings(out, rs);
+
+ DisplayNestedResults(out, nestedResults, conn, indentLevel );
+ nestedResults = null;
+
+ } // DisplayNextRow
+
+ static public void DisplayCurrentRow(PrintStream out, ResultSet rs, Connection conn )
+ throws SQLException
+ {
+ indent_DisplayCurrentRow( out, rs, conn, 0 );
+ }
+
+ static private void indent_DisplayCurrentRow(PrintStream out, ResultSet rs, Connection conn, int indentLevel )
+ throws SQLException {
+
+ Vector nestedResults;
+
+ if (rs == null) {
+ indentedPrintLine( out, indentLevel, LocalizedResource.getMessage("UT_NoCurreRow_19"));
+ return;
+ }
+
+ // autocommit must be off or the nested cursors
+ // are closed when the outer statement completes.
+ if (!conn.getAutoCommit())
+ nestedResults = new Vector();
+ else
+ nestedResults = null;
+
+ ResultSetMetaData rsmd = rs.getMetaData();
+ checkNotNull(rsmd, "ResultSetMetaData");
+
+ int rowLen = indent_DisplayBanner(out, rsmd, indentLevel);
+ DisplayRow(out, rs, rsmd, rowLen, nestedResults, conn, indentLevel );
+
+ ShowWarnings(out, rs);
+
+ DisplayNestedResults(out, nestedResults, conn, indentLevel );
+ nestedResults = null;
+
+ } // DisplayNextRow
+
+ static public int DisplayBanner(PrintStream out, ResultSetMetaData rsmd )
+ throws SQLException
+ {
+ return indent_DisplayBanner( out, rsmd, 0 );
+ }
+
+ static private int indent_DisplayBanner(PrintStream out, ResultSetMetaData rsmd, int indentLevel )
+ throws SQLException {
+
+ StringBuffer buf = new StringBuffer();
+
+ int numCols = rsmd.getColumnCount();
+ int rowLen;
+
+ // do some precalculation so the buffer is allocated only once
+ // buffer is twice as long as the display length plus one for a newline
+ rowLen = (numCols - 1); // for the column separators
+ for (int i=1; i <= numCols; i++) {
+ rowLen += Math.min(maxWidth,
+ Math.max((rsmd.isNullable(i) ==
+ ResultSetMetaData.columnNoNulls)?
+ 0 : MINWIDTH,
+ rsmd.getColumnDisplaySize(i)));
+ }
+ buf.ensureCapacity(rowLen);
+
+ // get column header info
+ // truncate it to the column display width
+ // add a bar between each item.
+ for (int i=1; i <= numCols; i++) {
+
+ if (i>1)
+ buf.append('|');
+
+ String s = rsmd.getColumnLabel(i);
+
+ int w = Math.min(maxWidth,
+ Math.max(((rsmd.isNullable(i) ==
+ ResultSetMetaData.columnNoNulls)?
+ 0 : MINWIDTH),
+ rsmd.getColumnDisplaySize(i)));
+
+ if (s.length() < w) {
+ // build a string buffer to hold the whitespace
+ StringBuffer blanks = new StringBuffer(s);
+ blanks.ensureCapacity(w);
+
+ // try to paste on big chunks of space at a time.
+ for (int k=blanks.length()+64; k<=w; k+=64)
+ blanks.append(
+ " ");
+ for (int k=blanks.length()+16; k<=w; k+=16)
+ blanks.append(" ");
+ for (int k=blanks.length()+4; k<=w; k+=4)
+ blanks.append(" ");
+ for (int k=blanks.length(); k<w; k++)
+ blanks.append(' ');
+
+ buf.append(blanks);
+ // REMIND: could do more cleverness, like keep around
+ // past buffers to reuse...
+ }
+ else if (s.length() > w) {
+ if (w > 1)
+ buf.append(s.substring(0,w-1));
+ if (w > 0)
+ buf.append('&');
+ }
+ else {
+ buf.append(s);
+ }
+ }
+
+ buf.setLength(Math.min(rowLen, 1024));
+ indentedPrintLine( out, indentLevel, buf);
+
+ // now print a row of '-'s
+ for (int i=0; i<Math.min(rowLen, 1024); i++)
+ buf.setCharAt(i, '-');
+ indentedPrintLine( out, indentLevel, buf);
+
+ buf = null;
+
+ return rowLen;
+ } // DisplayBanner
+
+ static private void DisplayRow(PrintStream out, ResultSet rs, ResultSetMetaData rsmd, int rowLen, Vector nestedResults, Connection conn, int indentLevel )
+ throws SQLException
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.ensureCapacity(rowLen);
+
+ int numCols = rsmd.getColumnCount();
+ int i;
+
+ // get column header info
+ // truncate it to the column display width
+ // add a bar between each item.
+ for (i=1; i <= numCols; i++){
+ if (i>1)
+ buf.append('|');
+
+ String s;
+ switch (rsmd.getColumnType(i)) {
+ default:
+ s = rs.getString(i);
+ break;
+ case org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT:
+ case Types.OTHER:
+ {
+ Object o = rs.getObject(i);
+ if (o == null) { s = "NULL"; }
+ else if (o instanceof ResultSet && nestedResults != null)
+ {
+ s = "ResultSet #"+nestedResults.size();
+ nestedResults.addElement(o);
+ }
+ else
+ {
+ try {
+ s = rs.getString(i);
+ } catch (SQLException se) {
+ // oops, they don't support refetching the column
+ s = o.toString();
+ }
+ }
+ }
+ break;
+ }
+
+ if (s==null) s = "NULL";
+
+ int w = Math.min(maxWidth,
+ Math.max((rsmd.isNullable(i) ==
+ ResultSetMetaData.columnNoNulls)?
+ 0 : MINWIDTH,
+ rsmd.getColumnDisplaySize(i)));
+ if (s.length() < w) {
+ StringBuffer fullS = new StringBuffer(s);
+ fullS.ensureCapacity(w);
+ for (int k=s.length(); k<w; k++)
+ fullS.append(' ');
+ s = fullS.toString();
+ }
+ else if (s.length() > w)
+ // add the & marker to know it got cut off
+ s = s.substring(0,w-1)+"&";
+
+ buf.append(s);
+ }
+ indentedPrintLine( out, indentLevel, buf);
+
+ } // DisplayRow
+
+ static public void doTrace(PrintStream out, Exception e) {
+ if (Boolean.getBoolean("ij.exceptionTrace")) {
+ e.printStackTrace(out);
+ out.flush();
+ }
+ }
+
+ static private void indentedPrintLine( PrintStream out, int indentLevel, String text )
+ {
+ indent( out, indentLevel );
+ out.println( text );
+ }
+
+ static private void indentedPrintLine( PrintStream out, int indentLevel, StringBuffer text )
+ {
+ indent( out, indentLevel );
+ out.println( text );
+ }
+
+ static private void indent( PrintStream out, int indentLevel )
+ {
+ for ( int ictr = 0; ictr < indentLevel; ictr++ ) { out.print( " " ); }
+ }
+
+ // ==========================
+}
+
+
+
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/tools/URLCheck.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/tools/URLCheck.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/tools/URLCheck.java Fri Sep 24 10:33:20 2004
@@ -1,174 +1,174 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.tools
- (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.tools;
-
-import org.apache.derby.iapi.reference.Attribute;
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-import org.apache.derby.impl.tools.ij.AttributeHolder;
-import java.util.Vector;
-import java.util.Properties;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-import java.lang.reflect.Field;
-import java.sql.SQLException;
-
-/**
- * This class takes a string used for a connection URL and checks for
- * correctness.
- * To turn off output in ij, use the command line
- * property of -DURLCheck=false.
- *
- * param anURL The URL used to connect to a database.
- *
- */
-
-public class URLCheck {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
-
- public Vector attributes;
- public static Vector booleanAttributes;
- //Need so that AppUI class does not get garbage collected
- LocalizedResource langUtil = LocalizedResource.getInstance();
- Vector validProps;
-
- public URLCheck(String anURL) {
-
- try {
- //Initialize the AppUI class
-
- //Parse the URL string into properties.
- Properties props = getAttributes(anURL, new Properties());
- check();
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
-
- public static void main(String[] args) {
- if (args.length > 0) {
- //Get the first argument passed in.
- URLCheck aCheck = new URLCheck(args[0]);
- }
- }
- public void check(){
- Enumeration enum = attributes.elements();
- while (enum.hasMoreElements()) {
- AttributeHolder anAttribute = (AttributeHolder)enum.nextElement();
- //The check for duplicate must be done at the URLCheck level
- //and not by each specific attribute. Only URLCheck knowns about
- //all of the attributes and names.
- checkForDuplicate(anAttribute);
- //Have each attribute check as much about themself as possible.
- anAttribute.check( validProps);
- }
- }
- public void checkForDuplicate(AttributeHolder anAttribute){
- Enumeration enum = attributes.elements();
- while (enum.hasMoreElements()) {
- AttributeHolder aHolder = (AttributeHolder)enum.nextElement();
- //If a duplicate is found, make sure that the message is only shown
- //once for each attribute.
- if (anAttribute != aHolder && anAttribute.getName().equals(aHolder.getName())) {
- anAttribute.addError(langUtil.getTextMessage("TL_dupAtt"));
- }
- }
-
- }
- public Properties getAttributes(String url, Properties props) throws Exception {
-
- String protocol = "";
-
- if( url.startsWith( "jdbc:derby:net:"))
- {
- validProps = null;
- }
- else if( url.startsWith( "jdbc:derby:"))
- {
- protocol = "jdbc:derby:";
- validProps = getValidCloudscapeProps();
- }
- else
- validProps = null;
-
-
- //Parse the url into attributes and put them in a Properties object.
- StringTokenizer st = new StringTokenizer(url.substring(protocol.length()), ";:\"");
- attributes = new Vector();
- while (st.hasMoreTokens()) {
- AttributeHolder anAttribute = new AttributeHolder();
- String anAtt = "";
- String aValue = "";
- String aToken = st.nextToken();
- //The "=" is the seperator between key and value.
- int eqPos = aToken.indexOf('=');
- if (eqPos == -1) {
- //If there is no "=" this is not an attribute
- continue;
- }
- else {
- anAtt = (aToken.substring(0, eqPos)).trim();
- aValue = (aToken.substring(eqPos + 1)).trim();
-
- }
- anAttribute.setName(anAtt);
- anAttribute.setValue(aValue);
- anAttribute.setToken(aToken);
- attributes.addElement(anAttribute);
- props.put(anAtt, aToken);
- }
- return props;
- }
-
- public static Vector getBooleanAttributes(){
- if (booleanAttributes == null) {
- booleanAttributes = new Vector();
- booleanAttributes.addElement(Attribute.DATA_ENCRYPTION);
- booleanAttributes.addElement(Attribute.CREATE_ATTR);
- booleanAttributes.addElement(Attribute.SHUTDOWN_ATTR);
- booleanAttributes.addElement(Attribute.UPGRADE_ATTR);
- }
- return booleanAttributes;
- }
-
- private static Vector validCloudscapeProps;
- private Vector getValidCloudscapeProps()
- {
- if( validCloudscapeProps == null)
- {
- try
- {
- Vector props = new Vector();
- Class att = Attribute.class;
- //Use reflection to get the list of valid keys from the Attribute class.
- //The Attribute class is an interface and therefore all the field
- //for it are public.
- Field[] fields = att.getFields();
- for (int i = 0; i < fields.length; i++)
- {
- Field aField = (Field)fields[i];
- props.addElement(aField.get(att));
- }
- validCloudscapeProps = props;
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- }
- return validCloudscapeProps;
- } // end of getValidCloudscapeProps
-
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.tools
+ (C) Copyright IBM Corp. 2000, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.tools;
+
+import org.apache.derby.iapi.reference.Attribute;
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+import org.apache.derby.impl.tools.ij.AttributeHolder;
+import java.util.Vector;
+import java.util.Properties;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.lang.reflect.Field;
+import java.sql.SQLException;
+
+/**
+ * This class takes a string used for a connection URL and checks for
+ * correctness.
+ * To turn off output in ij, use the command line
+ * property of -DURLCheck=false.
+ *
+ * param anURL The URL used to connect to a database.
+ *
+ */
+
+public class URLCheck {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2000_2004;
+
+ public Vector attributes;
+ public static Vector booleanAttributes;
+ //Need so that AppUI class does not get garbage collected
+ LocalizedResource langUtil = LocalizedResource.getInstance();
+ Vector validProps;
+
+ public URLCheck(String anURL) {
+
+ try {
+ //Initialize the AppUI class
+
+ //Parse the URL string into properties.
+ Properties props = getAttributes(anURL, new Properties());
+ check();
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+
+ public static void main(String[] args) {
+ if (args.length > 0) {
+ //Get the first argument passed in.
+ URLCheck aCheck = new URLCheck(args[0]);
+ }
+ }
+ public void check(){
+ Enumeration enum = attributes.elements();
+ while (enum.hasMoreElements()) {
+ AttributeHolder anAttribute = (AttributeHolder)enum.nextElement();
+ //The check for duplicate must be done at the URLCheck level
+ //and not by each specific attribute. Only URLCheck knowns about
+ //all of the attributes and names.
+ checkForDuplicate(anAttribute);
+ //Have each attribute check as much about themself as possible.
+ anAttribute.check( validProps);
+ }
+ }
+ public void checkForDuplicate(AttributeHolder anAttribute){
+ Enumeration enum = attributes.elements();
+ while (enum.hasMoreElements()) {
+ AttributeHolder aHolder = (AttributeHolder)enum.nextElement();
+ //If a duplicate is found, make sure that the message is only shown
+ //once for each attribute.
+ if (anAttribute != aHolder && anAttribute.getName().equals(aHolder.getName())) {
+ anAttribute.addError(langUtil.getTextMessage("TL_dupAtt"));
+ }
+ }
+
+ }
+ public Properties getAttributes(String url, Properties props) throws Exception {
+
+ String protocol = "";
+
+ if( url.startsWith( "jdbc:derby:net:"))
+ {
+ validProps = null;
+ }
+ else if( url.startsWith( "jdbc:derby:"))
+ {
+ protocol = "jdbc:derby:";
+ validProps = getValidCloudscapeProps();
+ }
+ else
+ validProps = null;
+
+
+ //Parse the url into attributes and put them in a Properties object.
+ StringTokenizer st = new StringTokenizer(url.substring(protocol.length()), ";:\"");
+ attributes = new Vector();
+ while (st.hasMoreTokens()) {
+ AttributeHolder anAttribute = new AttributeHolder();
+ String anAtt = "";
+ String aValue = "";
+ String aToken = st.nextToken();
+ //The "=" is the seperator between key and value.
+ int eqPos = aToken.indexOf('=');
+ if (eqPos == -1) {
+ //If there is no "=" this is not an attribute
+ continue;
+ }
+ else {
+ anAtt = (aToken.substring(0, eqPos)).trim();
+ aValue = (aToken.substring(eqPos + 1)).trim();
+
+ }
+ anAttribute.setName(anAtt);
+ anAttribute.setValue(aValue);
+ anAttribute.setToken(aToken);
+ attributes.addElement(anAttribute);
+ props.put(anAtt, aToken);
+ }
+ return props;
+ }
+
+ public static Vector getBooleanAttributes(){
+ if (booleanAttributes == null) {
+ booleanAttributes = new Vector();
+ booleanAttributes.addElement(Attribute.DATA_ENCRYPTION);
+ booleanAttributes.addElement(Attribute.CREATE_ATTR);
+ booleanAttributes.addElement(Attribute.SHUTDOWN_ATTR);
+ booleanAttributes.addElement(Attribute.UPGRADE_ATTR);
+ }
+ return booleanAttributes;
+ }
+
+ private static Vector validCloudscapeProps;
+ private Vector getValidCloudscapeProps()
+ {
+ if( validCloudscapeProps == null)
+ {
+ try
+ {
+ Vector props = new Vector();
+ Class att = Attribute.class;
+ //Use reflection to get the list of valid keys from the Attribute class.
+ //The Attribute class is an interface and therefore all the field
+ //for it are public.
+ Field[] fields = att.getFields();
+ for (int i = 0; i < fields.length; i++)
+ {
+ Field aField = (Field)fields[i];
+ props.addElement(aField.get(att));
+ }
+ validCloudscapeProps = props;
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ return validCloudscapeProps;
+ } // end of getValidCloudscapeProps
+
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/tools/dblook.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/tools/dblook.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/tools/dblook.java Fri Sep 24 10:33:20 2004
@@ -1,1128 +1,1128 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.tools
- (C) Copyright IBM Corp. 2003, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.tools;
-
-import java.io.BufferedReader;
-import java.io.StringReader;
-
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Timestamp;
-
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import java.util.ArrayList;
-
-import org.apache.derby.iapi.tools.i18n.LocalizedResource;
-
-import org.apache.derby.impl.tools.cslook.DB_Check;
-import org.apache.derby.impl.tools.cslook.DB_Index;
-import org.apache.derby.impl.tools.cslook.DB_Jar;
-import org.apache.derby.impl.tools.cslook.DB_Key;
-import org.apache.derby.impl.tools.cslook.DB_Table;
-import org.apache.derby.impl.tools.cslook.DB_Schema;
-import org.apache.derby.impl.tools.cslook.DB_StoredProcedure;
-import org.apache.derby.impl.tools.cslook.DB_Trigger;
-import org.apache.derby.impl.tools.cslook.DB_View;
-import org.apache.derby.impl.tools.cslook.Logs;
-
-public class dblook {
-
- /*
- IBM Copyright © notice.
- */
- /**
- IBM Copyright © notice.
- */
-
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2003_2004;
-
- // DB2 enforces a maximum of 30 tables to be specified as part of
- // the table list.
- public static final int DB2_MAX_NUMBER_OF_TABLES = 30;
-
- private Connection conn;
- private static PreparedStatement getColNameFromNumberQuery;
-
- // Mappings from id to name for schemas and tables (for ease
- // of reference).
- protected static HashMap schemaMap;
- protected static HashMap tableIdToNameMap;
-
- // Command-line Parameters.
- protected static String sourceDBUrl;
- protected static String ddlFileName;
- protected static String stmtDelimiter;
- protected static boolean appendLogs;
- protected static ArrayList tableList;
- protected static String schemaParam;
- protected static String targetSchema;
- protected static boolean skipViews;
- protected static boolean verbose;
- private static String sourceDBName;
-
- private static String lookLogName = "dblook.log";
-
- private final static String DEFAULT_LOCALE= "en";
- private final static String DEFAULT_LOCALE_COUNTRY="US";
- private static LocalizedResource langUtil;
-
- /* ************************************************
- * main:
- * Initialize program state by creating a dblook object,
- * and then start the DDL generation by calling "go".
- * ****/
-
- public static void main(String[] args) {
-
- dblook looker = new dblook(args);
- try {
- looker.go(sourceDBUrl, sourceDBName);
- } catch (Exception e) {
- // Errors are logged and printed to console according
- // to command line arguments, so just ignore here.
- }
-
- }
-
- /* ************************************************
- * Constructor:
- * Parse the command line, initialize logs, echo program variables,
- * and load the Cloudscape driver.
- * @param args args[0] is the database URL. All other command-line
- * parameters are read as system properties.
- * ****/
-
- public dblook(String[] args) {
-
- // Adjust the application in accordance with derby.ui.locale
- // and derby.ui.codeset
- langUtil = LocalizedResource.getInstance();
-
- // Initialize class variables.
- initState();
-
- // Parse the command line.
- if (!parseArgs(args)) {
- System.out.println(lookupMessage("CSLOOK_Usage"));
- System.exit(1);
- }
-
- showVariables();
-
- if (!loadDriver()) {
- // Failed when loading the driver. We already printed
- // the exception, so just return.
- return;
- }
-
- schemaMap = new HashMap();
- tableIdToNameMap = new HashMap();
-
- }
-
- /* ************************************************
- * initState:
- * Initialize class variables.
- ****/
-
- private void initState() {
-
- sourceDBUrl = null;
- ddlFileName = null;
- stmtDelimiter = null;
- appendLogs = false;
- tableList = null;
- targetSchema = null;
- schemaParam = null;
- skipViews = false;
- verbose= false;
- sourceDBName = null;
- return;
-
- }
-
- /* ************************************************
- * parseArgs:
- * Parse the command-line arguments. There is only one
- * actual argument (database url); the rest of the parameters
- * are read in as System properties.
- * @param args args[0] is the url for the source database.
- * @return true if all parameters were loaded and the output
- * files were successfully created; false otherwise.
- ****/
-
- private boolean parseArgs(String[] args) {
-
- if (args.length < 2)
- // must have minimum of 2 args: "-d" and "<dbUrl>".
- return false;
-
- int st = 0;
- for (int i = 0; i < args.length; i++) {
- st = loadParam(args, i);
- if (st == -1)
- return false;
- i = st;
- }
-
- if (sourceDBUrl == null) {
- // must have at least a database url.
- return false;
- }
-
- // At this point, all parameters should have been read into
- // their respective class variables. Use those
- // variables for some further processing.
-
- // Setup logs.
- boolean okay = Logs.initLogs(lookLogName, ddlFileName, appendLogs,
- verbose, (stmtDelimiter == null ? ";" : stmtDelimiter));
-
- // Get database name.
- sourceDBName = extractDBNameFromUrl(sourceDBUrl);
-
- // Set up schema restriction.
- if ((schemaParam != null) && (schemaParam.length() > 0) &&
- (schemaParam.charAt(0) != '"'))
- // not quoted, so upper case, then add quotes.
- {
- targetSchema = addQuotes(expandDoubleQuotes(
- schemaParam.toUpperCase(java.util.Locale.ENGLISH)));
- }
- else
- targetSchema = addQuotes(expandDoubleQuotes(stripQuotes(schemaParam)));
- return okay;
-
- }
-
- /* ************************************************
- * loadParam:
- * Read in a flag and its corresponding values from
- * list of command line arguments, starting at
- * the start'th argument.
- * @return The position of the argument that was
- * most recently processed.
- ****/
-
- private int loadParam(String [] args, int start) {
-
- if ((args[start].length() == 0) || args[start].charAt(0) != '-')
- // starting argument should be a flag; if it's
- // not, ignore it.
- return start;
-
- boolean haveVal = (args.length > start + 1);
- switch (args[start].charAt(1)) {
-
- case 'd':
- if (!haveVal)
- return -1;
- if (args[start].length() == 2)
- sourceDBUrl = args[++start];
- return start;
-
- case 'z':
- if (!haveVal)
- return -1;
- if (args[start].length() == 2)
- schemaParam = args[++start];
- return start;
-
- case 't':
- if (!haveVal)
- return -1;
- if (args[start].equals("-td")) {
- stmtDelimiter = args[++start];
- return start;
- }
- else if (args[start].equals("-t"))
- // list of tables.
- return extractTableNamesFromList(args, start+1);
- return -1;
- case 'o':
- if (!haveVal)
- return -1;
- if ((args[start].length() == 2) && (args[start+1].length() > 0))
- ddlFileName = args[++start];
- return start;
-
- case 'a':
- if (args[start].equals("-append")) {
- appendLogs = true;
- return start;
- }
- return -1;
-
- case 'n':
- if (args[start].equals("-noview")) {
- skipViews = true;
- return start;
- }
- return -1;
-
- case 'v':
- if (args[start].equals("-verbose")) {
- verbose = true;
- return start;
- }
- return -1;
-
- default:
- return -1;
-
- }
-
- }
-
- /* ************************************************
- * loadDriver:
- * Load db2j driver.
- * @param precondition sourceDBUrl has been loaded.
- * @return false if anything goes wrong; true otherwise.
- ****/
-
- private boolean loadDriver() {
-
- String db2jDriver;
- if (sourceDBUrl.indexOf(":net://") != -1)
- db2jDriver = "com.ibm.db2.jcc.DB2Driver";
- else
- db2jDriver = "org.apache.derby.jdbc.EmbeddedDriver";
- try {
- Class.forName(db2jDriver).newInstance();
- } catch (Exception e)
- {
- Logs.debug(e);
- return false;
- }
-
- return true;
-
- }
-
- /* ************************************************
- * extractDBNameFromUrl:
- * Given a database url, parse out the actual name
- * of the database. This is required for creation
- * the DB2JJARS directory (the database name is part
- * of the path to the jar).
- * @param dbUrl The database url from which to extract the
- * the database name.
- * @return the name of the database (including its
- * path, if provided) that is referenced by the url.
- ****/
-
- protected String extractDBNameFromUrl(String dbUrl) {
-
- if (dbUrl == null)
- // shouldn't happen; ignore it here, as an error
- // will be thrown we try to connect.
- return "";
-
- int start = dbUrl.indexOf("jdbc:derby:");
- if (start == -1)
- // not a valid url; just ignore it (an error
- // will be thrown when we try to connect).
- return "";
-
- start = dbUrl.indexOf("net://");
- if (start == -1)
- // standard url (jdbc:derby:<dbname>). Database
- // name starts right after "cloudscape:". The "11" in
- // the following line is the length of "cloudscape:".
- start = dbUrl.indexOf("cloudscape:") + 11;
- else
- // Network Server url. Database name starts right
- // after next slash (":net://hostname:port/<dbname>).
- // The "6" in the following line is the length of
- // "net://".
- start = dbUrl.indexOf("/", start+6) + 1;
-
- int stop = -1;
- if (dbUrl.charAt(start) == '"') {
- // database name is quoted; end of the name is the
- // closing quote.
- start++;
- stop = dbUrl.indexOf("\"", start);
- }
- else {
- // Database name ends with the start of a list of connection
- // attributes. This list can begin with either a colon
- // or a semi-colon.
- stop = dbUrl.indexOf(":", start);
- if (stop != -1) {
- if ((dbUrl.charAt(stop+1) == '/') ||
- (dbUrl.charAt(stop+1) == '\\'))
- // then this colon is part of the path (ex. "C:"),
- // so ignore it.
- stop = dbUrl.indexOf(":", stop+2);
- }
- int stop2 = dbUrl.length();
- if (stop == -1)
- // no colons; see if we can find a semi-colon.
- stop = dbUrl.indexOf(";", start);
- else
- stop2 = dbUrl.indexOf(";", start);
- stop = (stop <= stop2 ? stop : stop2);
- }
-
- if (stop == -1)
- // we have a url that ends with database name (no
- // other attributes appended).
- stop = dbUrl.length();
-
- return dbUrl.substring(start, stop);
-
- }
-
- /* ************************************************
- * extractTableNamesFromList:
- * Given an array of command line arguments containing
- * a list of table names beginning at start'th position,
- * read the list of table names and store them as
- * our target table list. Names without quotes are
- * turned into ALL CAPS and then double quotes are
- * added; names whcih already have double quotes are
- * stored exactly as they are. NOTE: DB2 enforces
- * maximum of 30 tables, and ignores the rest; so
- * do we.
- * @param args Array of command line arguments.
- * @start Position of the start of the list of tables
- * with the args array.
- * @return The position of the last table name in
- * the list of table names.
- ****/
-
- private int extractTableNamesFromList(String [] args,
- int start)
- {
-
- int argIndex = start;
- int count = 0;
- tableList = new ArrayList();
- while (argIndex < args.length) {
-
- if (((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '-')) ||
- (++count > DB2_MAX_NUMBER_OF_TABLES))
- // we're done with the table list.
- break;
-
- if ((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '"'))
- // it's quoted.
- tableList.add(addQuotes(expandDoubleQuotes(
- stripQuotes(args[argIndex++]))));
- else
- // not quoted, so make it all caps, then add
- // quotes.
- tableList.add(addQuotes(
- expandDoubleQuotes(args[argIndex++].toUpperCase(
- java.util.Locale.ENGLISH))));
-
- }
-
- if (tableList.size() == 0)
- tableList = null;
-
- return argIndex - 1;
-
- }
-
- /* ************************************************
- * showVariables:
- * Echo primary variables to output, so user can see
- * what s/he specified.
- ****/
-
- private void showVariables() {
-
- if (ddlFileName != null) {
- Logs.reportString("============================\n");
- Logs.reportMessage("CSLOOK_FileCreation");
- if (verbose)
- writeVerboseOutput("CSLOOK_OutputLocation",
- ddlFileName);
- }
-
- Logs.reportMessage("CSLOOK_Timestamp",
- new Timestamp(System.currentTimeMillis()).toString());
- Logs.reportMessage("CSLOOK_DBName", sourceDBName);
- Logs.reportMessage("CSLOOK_DBUrl", sourceDBUrl);
- if (tableList != null)
- Logs.reportMessage("CSLOOK_TargetTables");
- if (schemaParam != null)
- Logs.reportMessage("CSLOOK_TargetSchema", stripQuotes(schemaParam));
- Logs.reportString("appendLogs: " + appendLogs + "\n");
- return;
-
- }
-
- /* ************************************************
- * go:
- * Connect to the source database, prepare statements,
- * and load a list of table id-to-name mappings. Then,
- * generate the DDL for the various objects in the
- * database by making calls to static methods of helper
- * classes (one helper class for each type of database
- * object). If a particular object type should not be
- * generated (because of the user-specified command-
- * line), then we enforce that here.
- * @precondition all user-specified parameters have
- * been loaded.
- * @param srcUrl The full url of the database, as obtained
- * from parseArgs().
- * @param srcName The name of the database (as opposed to
- * the URL), as obtained from parseArgs(). This is
- * needed for locating any jar files that might'
- * exist in the source database.
- * @return DDL for the source database has been
- * generated and printed to output, subject to
- * user-specified restrictions.
- * ****/
-
- public void go(String srcUrl, String srcName)
- throws Exception
- {
-
- try
- {
-
- // Connect to the database, prepare statements,
- // and load id-to-name mappings.
- this.conn = DriverManager.getConnection(srcUrl);
- try {
- prepForDump();
- } catch (SQLException sqlE) {
- Logs.debug(sqlE);
- Logs.debug(Logs.unRollExceptions(sqlE), (String)null);
- Logs.cleanup();
- return;
- }
- catch (Exception e) {
- Logs.debug(e);
- Logs.cleanup();
- return;
- }
-
- // Generate DDL.
-
- // Start with schemas, since we might need them to
- // exist for jars to load properly.
- DB_Schema.doSchemas(this.conn,
- (tableList != null) && (targetSchema == null));
-
- if (tableList == null) {
- // Don't do these if user just wants table-related objects.
- DB_Jar.doJars(srcName, this.conn);
- DB_StoredProcedure.doStoredProcedures(this.conn);
- }
-
- DB_Table.doTables(this.conn, tableIdToNameMap);
- DB_Index.doIndexes(this.conn);
- DB_Key.doKeys(this.conn);
- DB_Check.doChecks(this.conn);
-
- if (!skipViews)
- DB_View.doViews(this.conn);
-
- DB_Trigger.doTriggers(this.conn);
-
- // That's it; we're done.
- if (getColNameFromNumberQuery != null)
- getColNameFromNumberQuery.close();
- Logs.cleanup();
-
- }
- catch (SQLException sqlE)
- {
- Logs.debug(sqlE);
- Logs.debug(Logs.unRollExceptions(sqlE), (String)null);
- Logs.cleanup();
- throw sqlE;
- }
- catch (Exception e)
- {
- Logs.debug(e);
- Logs.cleanup();
- throw e;
- }
- finally {
- // Close our connection.
- conn.commit();
- conn.close();
- }
-
- }
-
- /* ************************************************
- * prepForDump:
- * Prepare any useful statements (i.e. statements that
- * are required by more than one helper class) and load
- * the id-to-name mappings for the source database.
- ****/
-
- private void prepForDump() throws Exception {
-
- // We're only SELECTing throughout all of this, so no need
- // to commit (plus, disabling commit makes it easier to
- // have multiple ResultSets open on the same connection).
- this.conn.setAutoCommit(false);
-
- // Prepare statements.
- getColNameFromNumberQuery = conn.prepareStatement(
- "SELECT COLUMNNAME FROM SYS.SYSCOLUMNS WHERE " +
- "REFERENCEID = ? AND COLUMNNUMBER = ?");
-
- // Load list of user tables and table ids, for general use.
- Statement stmt = conn.createStatement();
- ResultSet rs = stmt.executeQuery("SELECT T.TABLEID, T.TABLENAME, " +
- "S.SCHEMANAME FROM SYS.SYSTABLES T, SYS.SYSSCHEMAS S " +
- "WHERE T.TABLETYPE = 'T' AND T.SCHEMAID = S.SCHEMAID");
-
- while (rs.next()) {
- String tableName = addQuotes(expandDoubleQuotes(rs.getString(2)));
- String schemaName = addQuotes(expandDoubleQuotes(rs.getString(3)));
- tableIdToNameMap.put(rs.getString(1),
- schemaName + "." + tableName);
- }
-
- // Load schema id's and names.
- rs = stmt.executeQuery("SELECT SCHEMAID, SCHEMANAME FROM " +
- "SYS.SYSSCHEMAS");
- while (rs.next()) {
- schemaMap.put(rs.getString(1),
- addQuotes(expandDoubleQuotes(rs.getString(2))));
- }
-
- stmt.close();
-
- // Load default property values.
- return;
-
- }
-
- /* ************************************************
- * getColumnListFromDescription:
- * Takes string description of column numbers in the
- * form of "(2, 1, 3...)" and the id of the table
- * having those columns, and then returns a string
- * with the column numbers replaced by their actual
- * names ('2' is replaced with the 2nd column in the
- * table, '1' with the first column, etc.).
- * @param tableId the id of the table to which the column
- * numbers should be applied.
- * @param description a string holding a list of column
- * numbers, enclosed in parentheses and separated
- * by commas.
- * @return a new string with the column numbers in
- * 'description' replaced by their column names;
- * also, the parentheses have been stripped off.
- ****/
-
- public static String getColumnListFromDescription(String tableId,
- String description) throws SQLException
- {
-
- StringBuffer sb = new StringBuffer();
- StringTokenizer tokenizer = new StringTokenizer(
- description.substring(description.indexOf("(") + 1,
- description.lastIndexOf(")")), " ,", true);
-
- boolean firstCol = true;
- while (tokenizer.hasMoreTokens()) {
-
- String tok = tokenizer.nextToken().trim();
- if (tok.equals(""))
- continue;
- else if (tok.equals(",")) {
- firstCol = false;
- continue;
- }
- try {
- String colName = getColNameFromNumber(tableId,
- (Integer.valueOf(tok)).intValue());
- if (!firstCol)
- sb.append(", ");
- sb.append(colName);
- } catch (NumberFormatException e) {
- // not a number; could be "ASC" or "DESC" tag,
- // which is okay; otherwise, something's wrong.
- tok = tok.toUpperCase();
- if (tok.equals("DESC") || tok.equals("ASC"))
- // then this is okay; just add the token to result.
- sb.append(" " + tok);
- else
- // shouldn't happen.
- Logs.debug("INTERNAL ERROR: read a non-number (" +
- tok + ") when a column number was expected:\n" +
- description, (String)null);
- }
-
- }
-
- return sb.toString();
-
- }
-
- /* ************************************************
- * getColNameFromNumber:
- * Takes a tableid and a column number colNum, and
- * returns the name of the colNum'th column in the
- * table with tableid.
- * @param tableid id of the table.
- * @param colNum number of the column for which we want
- * the name.
- * @return The name of the colNum'th column in the
- * table with tableid.
- ****/
-
- public static String getColNameFromNumber(String tableId,
- int colNum) throws SQLException
- {
-
- getColNameFromNumberQuery.setString(1, tableId);
- getColNameFromNumberQuery.setInt(2, colNum);
- ResultSet rs = getColNameFromNumberQuery.executeQuery();
-
- if (!rs.next()) {
- // shouldn't happen.
- Logs.debug("INTERNAL ERROR: Failed column number " +
- "lookup for table " + lookupTableId(tableId) +
- ", column " + colNum, (String)null);
- rs.close();
- return "";
- }
- else {
- String colName = addQuotes(expandDoubleQuotes(rs.getString(1)));
- rs.close();
- return colName;
- }
-
- }
-
- /* ************************************************
- * addQuotes:
- * Add quotes to the received object name, and return
- * the result.
- * @param name the name to which to add quotes.
- * @return the name with double quotes around it.
- ****/
-
- public static String addQuotes(String name) {
-
- if (name == null)
- return null;
-
- return "\"" + name + "\"";
-
- }
-
- /* ************************************************
- * stripQuotes:
- * Takes a name and, if the name is enclosed in
- * quotes, strips the quotes off. This method
- * assumes that the received String either has no quotes,
- * or has a quote (double or single) as the very first
- * AND very last character.
- * @param quotedName a name with quotes as the first
- * and last character, or else with no quotes at all.
- * @return quotedName, without the quotes.
- ****/
-
- public static String stripQuotes(String quotedName) {
-
- if (quotedName == null)
- return null;
-
- if ((quotedName.indexOf("\"") == -1) &&
- (quotedName.indexOf("'") == -1))
- // nothing to do.
- return quotedName;
-
- return quotedName.substring(1, quotedName.length() - 1);
-
- }
-
- /* ************************************************
- * isExcludedTable:
- * Takes a table name and determines whether or not
- * the DDL for objects related to that table should be
- * generated.
- * @param tableName name of the table to check.
- * @return true if 1) the user specified a table list
- * and that list does NOT include the received name; or
- * 2) if the user specified a schema restriction and
- * the received name does NOT have that schema; false
- * otherwise.
- ****/
-
- public static boolean isExcludedTable(String tableName) {
-
- if (tableName == null)
- return true;
-
- int dot = tableName.indexOf(".");
- if (dot != -1) {
- // strip off the schema part of the name, and see if we're
- // okay to use it.
- if (isIgnorableSchema(tableName.substring(0, dot)))
- // then we exclude this table.
- return true;
- tableName = tableName.substring(dot + 1,
- tableName.length());
- }
-
- return ((tableList != null) && !tableList.contains(tableName));
-
- }
-
- /* ************************************************
- * Takes a schema name and determines whether or
- * not the DDL for objects with that schema should
- * be generated.
- * @param schemaName schema name to be checked.
- * @return true if 1) the user specified a target
- * schema and that target is NOT the same as the
- * received schema name, or 2) the schema is a
- * system schema (SYS, SYSVISUAL, or SYSIBM);
- * false otherwise;
- ****/
-
- public static final String[] ignorableSchemaNames = {
- "SYSIBM",
- "SYS",
- "SYSVISUAL",
- "SYSCAT",
- "SYSFUN",
- "SYSPROC",
- "SYSSTAT",
- "NULLID",
- "SYSCS_ADMIN",
- "SYSCS_DIAG",
- "SYSCS_UTIL",
- "SQLJ"};
-
- public static boolean isIgnorableSchema(String schemaName) {
-
- if ((targetSchema != null) && (!schemaName.equals(targetSchema)))
- return true;
-
- schemaName = stripQuotes(schemaName);
-
- boolean ret = false;
-
- for (int i = ignorableSchemaNames.length - 1; i >= 0;)
- {
- if ((ret = ignorableSchemaNames[i--].equalsIgnoreCase(schemaName)))
- break;
- }
-
- return(ret);
- }
-
- /* ************************************************
- * Takes a string and determines whether or not that
- * string makes reference to any of the table names
- * in the user-specified table list.
- * @param str The string in which to search for table names.
- * @return true if 1) the user didn't specify a
- * target table list, or 2) the received string
- * contains at least one of the table names in the
- * user-specified target list; false otherwise.
- ****/
-
- public static boolean stringContainsTargetTable(String str) {
-
- if (str == null)
- // if the string is null, it can't possibly contain
- // any table names.
- return false;
-
- if (tableList == null)
- // if we have no target tables, then default to true.
- return true;
-
- int strLen = str.length();
- for (int i = 0; i < tableList.size(); i++) {
-
- String tableName = (String)tableList.get(i);
- tableName = expandDoubleQuotes(stripQuotes(tableName));
- int nameLen = tableName.length();
- String strCopy;
- if (tableName.equals(tableName.toUpperCase(
- java.util.Locale.ENGLISH)))
- // case doesn't matter.
- strCopy = str.toUpperCase();
- else
- strCopy = str;
- int pos = strCopy.indexOf(tableName);
- while (pos != -1) {
-
- // If we found it, make sure it's really a match.
- // First, see if it's part of another word.
- if (!partOfWord(str, pos, nameLen, strLen)) {
-
- // See if the match is in quotes--if so, then
- // it should match the table name's case.
- if ((pos >= 1) && (strCopy.charAt(pos-1) == '"') &&
- (pos + nameLen < strCopy.length()) &&
- (strCopy.charAt(pos+nameLen) == '"'))
- { // match is quoted; check it's case.
- if (str.substring(pos,
- pos + nameLen).equals(tableName))
- // everything checks out.
- return true;
- }
- else
- // match isn't quoted, so we're okay as is.
- return true;
- }
-
- pos = str.indexOf(tableName, pos + nameLen);
-
- }
- }
-
- // If we get here, we didn't find it.
- return false;
-
- }
-
- /* ************************************************
- * partOfWord:
- * Returns true if the part of the string given by
- * str.substring(pos, pos + nameLen) is part of
- * another word.
- * @param str The string in which we're looking.
- * @param pos The position at which the substring in
- * question begins.
- * @param nameLen the length of the substring in
- * question.
- * @param strLen The length of the string in which
- * we're looking.
- * @return true if the substring from pos to
- * pos+nameLen is part of larger word (i.e.
- * if it has a letter/digit immediately before
- * or after); false otherwise.
- ****/
-
- private static boolean partOfWord (String str,
- int pos, int nameLen, int strLen)
- {
-
- boolean somethingBefore = false;
- if (pos > 0) {
- char c = str.charAt(pos-1);
- somethingBefore = ((c == '_') ||
- Character.isLetterOrDigit(c));
- }
-
- boolean somethingAfter = false;
- if (pos + nameLen < strLen) {
- char c = str.charAt(pos + nameLen);
- somethingAfter = ((c == '_') ||
- Character.isLetterOrDigit(c));
- }
-
- return (somethingBefore || somethingAfter);
-
- }
-
- /* ************************************************
- * expandDoubleQuotes:
- * If the received SQL id contains a quote, we have
- * to expand it into TWO quotes so that it can be
- * treated correctly at parse time.
- * @param name Id that we want to print.
- ****/
-
- public static String expandDoubleQuotes(String name) {
-
- if ((name == null) || (name.indexOf("\"") < 0))
- // nothing to do.
- return name;
-
- char [] cA = name.toCharArray();
-
- // Worst (and extremely unlikely) case is every
- // character is a double quote, which means the
- // escaped string would need to be 2 times as long.
- char [] result = new char[2*cA.length];
-
- int j = 0;
- for (int i = 0; i < cA.length; i++) {
-
- if (cA[i] == '"') {
- result[j++] = '"';
- result[j++] = '"';
- }
- else
- result[j++] = cA[i];
-
- }
-
- return new String(result, 0, j);
-
- }
-
- /* ************************************************
- * lookupSchemaId:
- * Return the schema name corresponding to the
- * received schema id.
- * @param schemaId The id to look up.
- * @return the schema name.
- ****/
-
- public static String lookupSchemaId(String schemaId) {
-
- return (String)(schemaMap.get(schemaId));
-
- }
-
- /* ************************************************
- * lookupTableId:
- * Return the table name corresponding to the
- * received table id.
- * @param tableId The id to look up.
- * @return the table name.
- ****/
-
- public static String lookupTableId(String tableId) {
-
- return (String)(tableIdToNameMap.get(tableId));
-
- }
-
- /* ************************************************
- * writeVerboseOutput:
- * Writes the received string as "verbose" output,
- * meaning that we write it to System.err. We
- * choose System.err so that the string doesn't
- * show up if the user pipes dblook output to
- * a file (unless s/he explicitly pipes System.err
- * output to that file, as well).
- * @param key Key for the message to be printed as
- * verbose output.
- * @param value Value to be substituted into the
- * message.
- * @return message for received key has been printed
- * to System.err.
- ****/
-
- public static void writeVerboseOutput(String key,
- String value) {
-
- if (value == null)
- System.err.println(lookupMessage(key));
- else
- System.err.println(lookupMessage(key,
- new String [] {value}));
- return;
-
- }
-
- /* ************************************************
- * lookupMessage:
- * Retrieve a localized message.
- * @param key The key for the localized message.
- * @return the message corresponding to the received
- * key.
- ****/
-
- public static String lookupMessage(String key) {
-
- return lookupMessage(key, null);
-
- }
-
- /* ************************************************
- * lookupMessage:
- * Retreive a localized message.
- * @param key The key for the localized message.
- * @param vals Array of values to be used in the
- * message.
- * @return the message corresponding to the received
- * key, with the received values substituted where
- * appropriate.
- ****/
-
- public static String lookupMessage(String key, String[] vals) {
-
- String msg = "";
- if (vals == null)
- msg = langUtil.getTextMessage(key);
- else {
- switch (vals.length) {
- case 1: msg = langUtil.getTextMessage(
- key, vals[0]);
- break;
- case 2: msg = langUtil.getTextMessage(
- key, vals[0], vals[1]);
- break;
- default: /* shouldn't happen */
- break;
- }
- }
-
- return msg;
-
- }
-
- /* ************************************************
- * removeNewlines:
- * Remove any newline characters from the received
- * string (replace them with spaces).
- * @param str The string from which we are removing
- * all newline characters.
- * @return The string, with all newline characters
- * replaced with spaces.
- ****/
-
- public static String removeNewlines(String str) {
-
- if (str == null)
- // don't do anything.
- return null;
-
- StringBuffer result = null;
- try {
-
- BufferedReader strVal = new BufferedReader (new StringReader(str));
- for (String txt = strVal.readLine(); txt != null;
- txt = strVal.readLine())
- {
- if (result == null)
- result = new StringBuffer(txt);
- else {
- result.append(" ");
- result.append(txt);
- }
- }
-
- return result.toString();
-
- } catch (Exception e) {
- // if something went wrong, just return the string as is--
- // worst case is that the generated DDL is correct, it just
- // can't be run in a DB2 CLP script (because of the newline
- // characters).
- return str;
- }
-
- }
-
-}
-
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.tools
+ (C) Copyright IBM Corp. 2003, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.tools;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Timestamp;
+
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.util.ArrayList;
+
+import org.apache.derby.iapi.tools.i18n.LocalizedResource;
+
+import org.apache.derby.impl.tools.cslook.DB_Check;
+import org.apache.derby.impl.tools.cslook.DB_Index;
+import org.apache.derby.impl.tools.cslook.DB_Jar;
+import org.apache.derby.impl.tools.cslook.DB_Key;
+import org.apache.derby.impl.tools.cslook.DB_Table;
+import org.apache.derby.impl.tools.cslook.DB_Schema;
+import org.apache.derby.impl.tools.cslook.DB_StoredProcedure;
+import org.apache.derby.impl.tools.cslook.DB_Trigger;
+import org.apache.derby.impl.tools.cslook.DB_View;
+import org.apache.derby.impl.tools.cslook.Logs;
+
+public class dblook {
+
+ /*
+ IBM Copyright © notice.
+ */
+ /**
+ IBM Copyright © notice.
+ */
+
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_2003_2004;
+
+ // DB2 enforces a maximum of 30 tables to be specified as part of
+ // the table list.
+ public static final int DB2_MAX_NUMBER_OF_TABLES = 30;
+
+ private Connection conn;
+ private static PreparedStatement getColNameFromNumberQuery;
+
+ // Mappings from id to name for schemas and tables (for ease
+ // of reference).
+ protected static HashMap schemaMap;
+ protected static HashMap tableIdToNameMap;
+
+ // Command-line Parameters.
+ protected static String sourceDBUrl;
+ protected static String ddlFileName;
+ protected static String stmtDelimiter;
+ protected static boolean appendLogs;
+ protected static ArrayList tableList;
+ protected static String schemaParam;
+ protected static String targetSchema;
+ protected static boolean skipViews;
+ protected static boolean verbose;
+ private static String sourceDBName;
+
+ private static String lookLogName = "dblook.log";
+
+ private final static String DEFAULT_LOCALE= "en";
+ private final static String DEFAULT_LOCALE_COUNTRY="US";
+ private static LocalizedResource langUtil;
+
+ /* ************************************************
+ * main:
+ * Initialize program state by creating a dblook object,
+ * and then start the DDL generation by calling "go".
+ * ****/
+
+ public static void main(String[] args) {
+
+ dblook looker = new dblook(args);
+ try {
+ looker.go(sourceDBUrl, sourceDBName);
+ } catch (Exception e) {
+ // Errors are logged and printed to console according
+ // to command line arguments, so just ignore here.
+ }
+
+ }
+
+ /* ************************************************
+ * Constructor:
+ * Parse the command line, initialize logs, echo program variables,
+ * and load the Cloudscape driver.
+ * @param args args[0] is the database URL. All other command-line
+ * parameters are read as system properties.
+ * ****/
+
+ public dblook(String[] args) {
+
+ // Adjust the application in accordance with derby.ui.locale
+ // and derby.ui.codeset
+ langUtil = LocalizedResource.getInstance();
+
+ // Initialize class variables.
+ initState();
+
+ // Parse the command line.
+ if (!parseArgs(args)) {
+ System.out.println(lookupMessage("CSLOOK_Usage"));
+ System.exit(1);
+ }
+
+ showVariables();
+
+ if (!loadDriver()) {
+ // Failed when loading the driver. We already printed
+ // the exception, so just return.
+ return;
+ }
+
+ schemaMap = new HashMap();
+ tableIdToNameMap = new HashMap();
+
+ }
+
+ /* ************************************************
+ * initState:
+ * Initialize class variables.
+ ****/
+
+ private void initState() {
+
+ sourceDBUrl = null;
+ ddlFileName = null;
+ stmtDelimiter = null;
+ appendLogs = false;
+ tableList = null;
+ targetSchema = null;
+ schemaParam = null;
+ skipViews = false;
+ verbose= false;
+ sourceDBName = null;
+ return;
+
+ }
+
+ /* ************************************************
+ * parseArgs:
+ * Parse the command-line arguments. There is only one
+ * actual argument (database url); the rest of the parameters
+ * are read in as System properties.
+ * @param args args[0] is the url for the source database.
+ * @return true if all parameters were loaded and the output
+ * files were successfully created; false otherwise.
+ ****/
+
+ private boolean parseArgs(String[] args) {
+
+ if (args.length < 2)
+ // must have minimum of 2 args: "-d" and "<dbUrl>".
+ return false;
+
+ int st = 0;
+ for (int i = 0; i < args.length; i++) {
+ st = loadParam(args, i);
+ if (st == -1)
+ return false;
+ i = st;
+ }
+
+ if (sourceDBUrl == null) {
+ // must have at least a database url.
+ return false;
+ }
+
+ // At this point, all parameters should have been read into
+ // their respective class variables. Use those
+ // variables for some further processing.
+
+ // Setup logs.
+ boolean okay = Logs.initLogs(lookLogName, ddlFileName, appendLogs,
+ verbose, (stmtDelimiter == null ? ";" : stmtDelimiter));
+
+ // Get database name.
+ sourceDBName = extractDBNameFromUrl(sourceDBUrl);
+
+ // Set up schema restriction.
+ if ((schemaParam != null) && (schemaParam.length() > 0) &&
+ (schemaParam.charAt(0) != '"'))
+ // not quoted, so upper case, then add quotes.
+ {
+ targetSchema = addQuotes(expandDoubleQuotes(
+ schemaParam.toUpperCase(java.util.Locale.ENGLISH)));
+ }
+ else
+ targetSchema = addQuotes(expandDoubleQuotes(stripQuotes(schemaParam)));
+ return okay;
+
+ }
+
+ /* ************************************************
+ * loadParam:
+ * Read in a flag and its corresponding values from
+ * list of command line arguments, starting at
+ * the start'th argument.
+ * @return The position of the argument that was
+ * most recently processed.
+ ****/
+
+ private int loadParam(String [] args, int start) {
+
+ if ((args[start].length() == 0) || args[start].charAt(0) != '-')
+ // starting argument should be a flag; if it's
+ // not, ignore it.
+ return start;
+
+ boolean haveVal = (args.length > start + 1);
+ switch (args[start].charAt(1)) {
+
+ case 'd':
+ if (!haveVal)
+ return -1;
+ if (args[start].length() == 2)
+ sourceDBUrl = args[++start];
+ return start;
+
+ case 'z':
+ if (!haveVal)
+ return -1;
+ if (args[start].length() == 2)
+ schemaParam = args[++start];
+ return start;
+
+ case 't':
+ if (!haveVal)
+ return -1;
+ if (args[start].equals("-td")) {
+ stmtDelimiter = args[++start];
+ return start;
+ }
+ else if (args[start].equals("-t"))
+ // list of tables.
+ return extractTableNamesFromList(args, start+1);
+ return -1;
+ case 'o':
+ if (!haveVal)
+ return -1;
+ if ((args[start].length() == 2) && (args[start+1].length() > 0))
+ ddlFileName = args[++start];
+ return start;
+
+ case 'a':
+ if (args[start].equals("-append")) {
+ appendLogs = true;
+ return start;
+ }
+ return -1;
+
+ case 'n':
+ if (args[start].equals("-noview")) {
+ skipViews = true;
+ return start;
+ }
+ return -1;
+
+ case 'v':
+ if (args[start].equals("-verbose")) {
+ verbose = true;
+ return start;
+ }
+ return -1;
+
+ default:
+ return -1;
+
+ }
+
+ }
+
+ /* ************************************************
+ * loadDriver:
+ * Load db2j driver.
+ * @param precondition sourceDBUrl has been loaded.
+ * @return false if anything goes wrong; true otherwise.
+ ****/
+
+ private boolean loadDriver() {
+
+ String db2jDriver;
+ if (sourceDBUrl.indexOf(":net://") != -1)
+ db2jDriver = "com.ibm.db2.jcc.DB2Driver";
+ else
+ db2jDriver = "org.apache.derby.jdbc.EmbeddedDriver";
+ try {
+ Class.forName(db2jDriver).newInstance();
+ } catch (Exception e)
+ {
+ Logs.debug(e);
+ return false;
+ }
+
+ return true;
+
+ }
+
+ /* ************************************************
+ * extractDBNameFromUrl:
+ * Given a database url, parse out the actual name
+ * of the database. This is required for creation
+ * the DB2JJARS directory (the database name is part
+ * of the path to the jar).
+ * @param dbUrl The database url from which to extract the
+ * the database name.
+ * @return the name of the database (including its
+ * path, if provided) that is referenced by the url.
+ ****/
+
+ protected String extractDBNameFromUrl(String dbUrl) {
+
+ if (dbUrl == null)
+ // shouldn't happen; ignore it here, as an error
+ // will be thrown we try to connect.
+ return "";
+
+ int start = dbUrl.indexOf("jdbc:derby:");
+ if (start == -1)
+ // not a valid url; just ignore it (an error
+ // will be thrown when we try to connect).
+ return "";
+
+ start = dbUrl.indexOf("net://");
+ if (start == -1)
+ // standard url (jdbc:derby:<dbname>). Database
+ // name starts right after "cloudscape:". The "11" in
+ // the following line is the length of "cloudscape:".
+ start = dbUrl.indexOf("cloudscape:") + 11;
+ else
+ // Network Server url. Database name starts right
+ // after next slash (":net://hostname:port/<dbname>).
+ // The "6" in the following line is the length of
+ // "net://".
+ start = dbUrl.indexOf("/", start+6) + 1;
+
+ int stop = -1;
+ if (dbUrl.charAt(start) == '"') {
+ // database name is quoted; end of the name is the
+ // closing quote.
+ start++;
+ stop = dbUrl.indexOf("\"", start);
+ }
+ else {
+ // Database name ends with the start of a list of connection
+ // attributes. This list can begin with either a colon
+ // or a semi-colon.
+ stop = dbUrl.indexOf(":", start);
+ if (stop != -1) {
+ if ((dbUrl.charAt(stop+1) == '/') ||
+ (dbUrl.charAt(stop+1) == '\\'))
+ // then this colon is part of the path (ex. "C:"),
+ // so ignore it.
+ stop = dbUrl.indexOf(":", stop+2);
+ }
+ int stop2 = dbUrl.length();
+ if (stop == -1)
+ // no colons; see if we can find a semi-colon.
+ stop = dbUrl.indexOf(";", start);
+ else
+ stop2 = dbUrl.indexOf(";", start);
+ stop = (stop <= stop2 ? stop : stop2);
+ }
+
+ if (stop == -1)
+ // we have a url that ends with database name (no
+ // other attributes appended).
+ stop = dbUrl.length();
+
+ return dbUrl.substring(start, stop);
+
+ }
+
+ /* ************************************************
+ * extractTableNamesFromList:
+ * Given an array of command line arguments containing
+ * a list of table names beginning at start'th position,
+ * read the list of table names and store them as
+ * our target table list. Names without quotes are
+ * turned into ALL CAPS and then double quotes are
+ * added; names whcih already have double quotes are
+ * stored exactly as they are. NOTE: DB2 enforces
+ * maximum of 30 tables, and ignores the rest; so
+ * do we.
+ * @param args Array of command line arguments.
+ * @start Position of the start of the list of tables
+ * with the args array.
+ * @return The position of the last table name in
+ * the list of table names.
+ ****/
+
+ private int extractTableNamesFromList(String [] args,
+ int start)
+ {
+
+ int argIndex = start;
+ int count = 0;
+ tableList = new ArrayList();
+ while (argIndex < args.length) {
+
+ if (((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '-')) ||
+ (++count > DB2_MAX_NUMBER_OF_TABLES))
+ // we're done with the table list.
+ break;
+
+ if ((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '"'))
+ // it's quoted.
+ tableList.add(addQuotes(expandDoubleQuotes(
+ stripQuotes(args[argIndex++]))));
+ else
+ // not quoted, so make it all caps, then add
+ // quotes.
+ tableList.add(addQuotes(
+ expandDoubleQuotes(args[argIndex++].toUpperCase(
+ java.util.Locale.ENGLISH))));
+
+ }
+
+ if (tableList.size() == 0)
+ tableList = null;
+
+ return argIndex - 1;
+
+ }
+
+ /* ************************************************
+ * showVariables:
+ * Echo primary variables to output, so user can see
+ * what s/he specified.
+ ****/
+
+ private void showVariables() {
+
+ if (ddlFileName != null) {
+ Logs.reportString("============================\n");
+ Logs.reportMessage("CSLOOK_FileCreation");
+ if (verbose)
+ writeVerboseOutput("CSLOOK_OutputLocation",
+ ddlFileName);
+ }
+
+ Logs.reportMessage("CSLOOK_Timestamp",
+ new Timestamp(System.currentTimeMillis()).toString());
+ Logs.reportMessage("CSLOOK_DBName", sourceDBName);
+ Logs.reportMessage("CSLOOK_DBUrl", sourceDBUrl);
+ if (tableList != null)
+ Logs.reportMessage("CSLOOK_TargetTables");
+ if (schemaParam != null)
+ Logs.reportMessage("CSLOOK_TargetSchema", stripQuotes(schemaParam));
+ Logs.reportString("appendLogs: " + appendLogs + "\n");
+ return;
+
+ }
+
+ /* ************************************************
+ * go:
+ * Connect to the source database, prepare statements,
+ * and load a list of table id-to-name mappings. Then,
+ * generate the DDL for the various objects in the
+ * database by making calls to static methods of helper
+ * classes (one helper class for each type of database
+ * object). If a particular object type should not be
+ * generated (because of the user-specified command-
+ * line), then we enforce that here.
+ * @precondition all user-specified parameters have
+ * been loaded.
+ * @param srcUrl The full url of the database, as obtained
+ * from parseArgs().
+ * @param srcName The name of the database (as opposed to
+ * the URL), as obtained from parseArgs(). This is
+ * needed for locating any jar files that might'
+ * exist in the source database.
+ * @return DDL for the source database has been
+ * generated and printed to output, subject to
+ * user-specified restrictions.
+ * ****/
+
+ public void go(String srcUrl, String srcName)
+ throws Exception
+ {
+
+ try
+ {
+
+ // Connect to the database, prepare statements,
+ // and load id-to-name mappings.
+ this.conn = DriverManager.getConnection(srcUrl);
+ try {
+ prepForDump();
+ } catch (SQLException sqlE) {
+ Logs.debug(sqlE);
+ Logs.debug(Logs.unRollExceptions(sqlE), (String)null);
+ Logs.cleanup();
+ return;
+ }
+ catch (Exception e) {
+ Logs.debug(e);
+ Logs.cleanup();
+ return;
+ }
+
+ // Generate DDL.
+
+ // Start with schemas, since we might need them to
+ // exist for jars to load properly.
+ DB_Schema.doSchemas(this.conn,
+ (tableList != null) && (targetSchema == null));
+
+ if (tableList == null) {
+ // Don't do these if user just wants table-related objects.
+ DB_Jar.doJars(srcName, this.conn);
+ DB_StoredProcedure.doStoredProcedures(this.conn);
+ }
+
+ DB_Table.doTables(this.conn, tableIdToNameMap);
+ DB_Index.doIndexes(this.conn);
+ DB_Key.doKeys(this.conn);
+ DB_Check.doChecks(this.conn);
+
+ if (!skipViews)
+ DB_View.doViews(this.conn);
+
+ DB_Trigger.doTriggers(this.conn);
+
+ // That's it; we're done.
+ if (getColNameFromNumberQuery != null)
+ getColNameFromNumberQuery.close();
+ Logs.cleanup();
+
+ }
+ catch (SQLException sqlE)
+ {
+ Logs.debug(sqlE);
+ Logs.debug(Logs.unRollExceptions(sqlE), (String)null);
+ Logs.cleanup();
+ throw sqlE;
+ }
+ catch (Exception e)
+ {
+ Logs.debug(e);
+ Logs.cleanup();
+ throw e;
+ }
+ finally {
+ // Close our connection.
+ conn.commit();
+ conn.close();
+ }
+
+ }
+
+ /* ************************************************
+ * prepForDump:
+ * Prepare any useful statements (i.e. statements that
+ * are required by more than one helper class) and load
+ * the id-to-name mappings for the source database.
+ ****/
+
+ private void prepForDump() throws Exception {
+
+ // We're only SELECTing throughout all of this, so no need
+ // to commit (plus, disabling commit makes it easier to
+ // have multiple ResultSets open on the same connection).
+ this.conn.setAutoCommit(false);
+
+ // Prepare statements.
+ getColNameFromNumberQuery = conn.prepareStatement(
+ "SELECT COLUMNNAME FROM SYS.SYSCOLUMNS WHERE " +
+ "REFERENCEID = ? AND COLUMNNUMBER = ?");
+
+ // Load list of user tables and table ids, for general use.
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery("SELECT T.TABLEID, T.TABLENAME, " +
+ "S.SCHEMANAME FROM SYS.SYSTABLES T, SYS.SYSSCHEMAS S " +
+ "WHERE T.TABLETYPE = 'T' AND T.SCHEMAID = S.SCHEMAID");
+
+ while (rs.next()) {
+ String tableName = addQuotes(expandDoubleQuotes(rs.getString(2)));
+ String schemaName = addQuotes(expandDoubleQuotes(rs.getString(3)));
+ tableIdToNameMap.put(rs.getString(1),
+ schemaName + "." + tableName);
+ }
+
+ // Load schema id's and names.
+ rs = stmt.executeQuery("SELECT SCHEMAID, SCHEMANAME FROM " +
+ "SYS.SYSSCHEMAS");
+ while (rs.next()) {
+ schemaMap.put(rs.getString(1),
+ addQuotes(expandDoubleQuotes(rs.getString(2))));
+ }
+
+ stmt.close();
+
+ // Load default property values.
+ return;
+
+ }
+
+ /* ************************************************
+ * getColumnListFromDescription:
+ * Takes string description of column numbers in the
+ * form of "(2, 1, 3...)" and the id of the table
+ * having those columns, and then returns a string
+ * with the column numbers replaced by their actual
+ * names ('2' is replaced with the 2nd column in the
+ * table, '1' with the first column, etc.).
+ * @param tableId the id of the table to which the column
+ * numbers should be applied.
+ * @param description a string holding a list of column
+ * numbers, enclosed in parentheses and separated
+ * by commas.
+ * @return a new string with the column numbers in
+ * 'description' replaced by their column names;
+ * also, the parentheses have been stripped off.
+ ****/
+
+ public static String getColumnListFromDescription(String tableId,
+ String description) throws SQLException
+ {
+
+ StringBuffer sb = new StringBuffer();
+ StringTokenizer tokenizer = new StringTokenizer(
+ description.substring(description.indexOf("(") + 1,
+ description.lastIndexOf(")")), " ,", true);
+
+ boolean firstCol = true;
+ while (tokenizer.hasMoreTokens()) {
+
+ String tok = tokenizer.nextToken().trim();
+ if (tok.equals(""))
+ continue;
+ else if (tok.equals(",")) {
+ firstCol = false;
+ continue;
+ }
+ try {
+ String colName = getColNameFromNumber(tableId,
+ (Integer.valueOf(tok)).intValue());
+ if (!firstCol)
+ sb.append(", ");
+ sb.append(colName);
+ } catch (NumberFormatException e) {
+ // not a number; could be "ASC" or "DESC" tag,
+ // which is okay; otherwise, something's wrong.
+ tok = tok.toUpperCase();
+ if (tok.equals("DESC") || tok.equals("ASC"))
+ // then this is okay; just add the token to result.
+ sb.append(" " + tok);
+ else
+ // shouldn't happen.
+ Logs.debug("INTERNAL ERROR: read a non-number (" +
+ tok + ") when a column number was expected:\n" +
+ description, (String)null);
+ }
+
+ }
+
+ return sb.toString();
+
+ }
+
+ /* ************************************************
+ * getColNameFromNumber:
+ * Takes a tableid and a column number colNum, and
+ * returns the name of the colNum'th column in the
+ * table with tableid.
+ * @param tableid id of the table.
+ * @param colNum number of the column for which we want
+ * the name.
+ * @return The name of the colNum'th column in the
+ * table with tableid.
+ ****/
+
+ public static String getColNameFromNumber(String tableId,
+ int colNum) throws SQLException
+ {
+
+ getColNameFromNumberQuery.setString(1, tableId);
+ getColNameFromNumberQuery.setInt(2, colNum);
+ ResultSet rs = getColNameFromNumberQuery.executeQuery();
+
+ if (!rs.next()) {
+ // shouldn't happen.
+ Logs.debug("INTERNAL ERROR: Failed column number " +
+ "lookup for table " + lookupTableId(tableId) +
+ ", column " + colNum, (String)null);
+ rs.close();
+ return "";
+ }
+ else {
+ String colName = addQuotes(expandDoubleQuotes(rs.getString(1)));
+ rs.close();
+ return colName;
+ }
+
+ }
+
+ /* ************************************************
+ * addQuotes:
+ * Add quotes to the received object name, and return
+ * the result.
+ * @param name the name to which to add quotes.
+ * @return the name with double quotes around it.
+ ****/
+
+ public static String addQuotes(String name) {
+
+ if (name == null)
+ return null;
+
+ return "\"" + name + "\"";
+
+ }
+
+ /* ************************************************
+ * stripQuotes:
+ * Takes a name and, if the name is enclosed in
+ * quotes, strips the quotes off. This method
+ * assumes that the received String either has no quotes,
+ * or has a quote (double or single) as the very first
+ * AND very last character.
+ * @param quotedName a name with quotes as the first
+ * and last character, or else with no quotes at all.
+ * @return quotedName, without the quotes.
+ ****/
+
+ public static String stripQuotes(String quotedName) {
+
+ if (quotedName == null)
+ return null;
+
+ if ((quotedName.indexOf("\"") == -1) &&
+ (quotedName.indexOf("'") == -1))
+ // nothing to do.
+ return quotedName;
+
+ return quotedName.substring(1, quotedName.length() - 1);
+
+ }
+
+ /* ************************************************
+ * isExcludedTable:
+ * Takes a table name and determines whether or not
+ * the DDL for objects related to that table should be
+ * generated.
+ * @param tableName name of the table to check.
+ * @return true if 1) the user specified a table list
+ * and that list does NOT include the received name; or
+ * 2) if the user specified a schema restriction and
+ * the received name does NOT have that schema; false
+ * otherwise.
+ ****/
+
+ public static boolean isExcludedTable(String tableName) {
+
+ if (tableName == null)
+ return true;
+
+ int dot = tableName.indexOf(".");
+ if (dot != -1) {
+ // strip off the schema part of the name, and see if we're
+ // okay to use it.
+ if (isIgnorableSchema(tableName.substring(0, dot)))
+ // then we exclude this table.
+ return true;
+ tableName = tableName.substring(dot + 1,
+ tableName.length());
+ }
+
+ return ((tableList != null) && !tableList.contains(tableName));
+
+ }
+
+ /* ************************************************
+ * Takes a schema name and determines whether or
+ * not the DDL for objects with that schema should
+ * be generated.
+ * @param schemaName schema name to be checked.
+ * @return true if 1) the user specified a target
+ * schema and that target is NOT the same as the
+ * received schema name, or 2) the schema is a
+ * system schema (SYS, SYSVISUAL, or SYSIBM);
+ * false otherwise;
+ ****/
+
+ public static final String[] ignorableSchemaNames = {
+ "SYSIBM",
+ "SYS",
+ "SYSVISUAL",
+ "SYSCAT",
+ "SYSFUN",
+ "SYSPROC",
+ "SYSSTAT",
+ "NULLID",
+ "SYSCS_ADMIN",
+ "SYSCS_DIAG",
+ "SYSCS_UTIL",
+ "SQLJ"};
+
+ public static boolean isIgnorableSchema(String schemaName) {
+
+ if ((targetSchema != null) && (!schemaName.equals(targetSchema)))
+ return true;
+
+ schemaName = stripQuotes(schemaName);
+
+ boolean ret = false;
+
+ for (int i = ignorableSchemaNames.length - 1; i >= 0;)
+ {
+ if ((ret = ignorableSchemaNames[i--].equalsIgnoreCase(schemaName)))
+ break;
+ }
+
+ return(ret);
+ }
+
+ /* ************************************************
+ * Takes a string and determines whether or not that
+ * string makes reference to any of the table names
+ * in the user-specified table list.
+ * @param str The string in which to search for table names.
+ * @return true if 1) the user didn't specify a
+ * target table list, or 2) the received string
+ * contains at least one of the table names in the
+ * user-specified target list; false otherwise.
+ ****/
+
+ public static boolean stringContainsTargetTable(String str) {
+
+ if (str == null)
+ // if the string is null, it can't possibly contain
+ // any table names.
+ return false;
+
+ if (tableList == null)
+ // if we have no target tables, then default to true.
+ return true;
+
+ int strLen = str.length();
+ for (int i = 0; i < tableList.size(); i++) {
+
+ String tableName = (String)tableList.get(i);
+ tableName = expandDoubleQuotes(stripQuotes(tableName));
+ int nameLen = tableName.length();
+ String strCopy;
+ if (tableName.equals(tableName.toUpperCase(
+ java.util.Locale.ENGLISH)))
+ // case doesn't matter.
+ strCopy = str.toUpperCase();
+ else
+ strCopy = str;
+ int pos = strCopy.indexOf(tableName);
+ while (pos != -1) {
+
+ // If we found it, make sure it's really a match.
+ // First, see if it's part of another word.
+ if (!partOfWord(str, pos, nameLen, strLen)) {
+
+ // See if the match is in quotes--if so, then
+ // it should match the table name's case.
+ if ((pos >= 1) && (strCopy.charAt(pos-1) == '"') &&
+ (pos + nameLen < strCopy.length()) &&
+ (strCopy.charAt(pos+nameLen) == '"'))
+ { // match is quoted; check it's case.
+ if (str.substring(pos,
+ pos + nameLen).equals(tableName))
+ // everything checks out.
+ return true;
+ }
+ else
+ // match isn't quoted, so we're okay as is.
+ return true;
+ }
+
+ pos = str.indexOf(tableName, pos + nameLen);
+
+ }
+ }
+
+ // If we get here, we didn't find it.
+ return false;
+
+ }
+
+ /* ************************************************
+ * partOfWord:
+ * Returns true if the part of the string given by
+ * str.substring(pos, pos + nameLen) is part of
+ * another word.
+ * @param str The string in which we're looking.
+ * @param pos The position at which the substring in
+ * question begins.
+ * @param nameLen the length of the substring in
+ * question.
+ * @param strLen The length of the string in which
+ * we're looking.
+ * @return true if the substring from pos to
+ * pos+nameLen is part of larger word (i.e.
+ * if it has a letter/digit immediately before
+ * or after); false otherwise.
+ ****/
+
+ private static boolean partOfWord (String str,
+ int pos, int nameLen, int strLen)
+ {
+
+ boolean somethingBefore = false;
+ if (pos > 0) {
+ char c = str.charAt(pos-1);
+ somethingBefore = ((c == '_') ||
+ Character.isLetterOrDigit(c));
+ }
+
+ boolean somethingAfter = false;
+ if (pos + nameLen < strLen) {
+ char c = str.charAt(pos + nameLen);
+ somethingAfter = ((c == '_') ||
+ Character.isLetterOrDigit(c));
+ }
+
+ return (somethingBefore || somethingAfter);
+
+ }
+
+ /* ************************************************
+ * expandDoubleQuotes:
+ * If the received SQL id contains a quote, we have
+ * to expand it into TWO quotes so that it can be
+ * treated correctly at parse time.
+ * @param name Id that we want to print.
+ ****/
+
+ public static String expandDoubleQuotes(String name) {
+
+ if ((name == null) || (name.indexOf("\"") < 0))
+ // nothing to do.
+ return name;
+
+ char [] cA = name.toCharArray();
+
+ // Worst (and extremely unlikely) case is every
+ // character is a double quote, which means the
+ // escaped string would need to be 2 times as long.
+ char [] result = new char[2*cA.length];
+
+ int j = 0;
+ for (int i = 0; i < cA.length; i++) {
+
+ if (cA[i] == '"') {
+ result[j++] = '"';
+ result[j++] = '"';
+ }
+ else
+ result[j++] = cA[i];
+
+ }
+
+ return new String(result, 0, j);
+
+ }
+
+ /* ************************************************
+ * lookupSchemaId:
+ * Return the schema name corresponding to the
+ * received schema id.
+ * @param schemaId The id to look up.
+ * @return the schema name.
+ ****/
+
+ public static String lookupSchemaId(String schemaId) {
+
+ return (String)(schemaMap.get(schemaId));
+
+ }
+
+ /* ************************************************
+ * lookupTableId:
+ * Return the table name corresponding to the
+ * received table id.
+ * @param tableId The id to look up.
+ * @return the table name.
+ ****/
+
+ public static String lookupTableId(String tableId) {
+
+ return (String)(tableIdToNameMap.get(tableId));
+
+ }
+
+ /* ************************************************
+ * writeVerboseOutput:
+ * Writes the received string as "verbose" output,
+ * meaning that we write it to System.err. We
+ * choose System.err so that the string doesn't
+ * show up if the user pipes dblook output to
+ * a file (unless s/he explicitly pipes System.err
+ * output to that file, as well).
+ * @param key Key for the message to be printed as
+ * verbose output.
+ * @param value Value to be substituted into the
+ * message.
+ * @return message for received key has been printed
+ * to System.err.
+ ****/
+
+ public static void writeVerboseOutput(String key,
+ String value) {
+
+ if (value == null)
+ System.err.println(lookupMessage(key));
+ else
+ System.err.println(lookupMessage(key,
+ new String [] {value}));
+ return;
+
+ }
+
+ /* ************************************************
+ * lookupMessage:
+ * Retrieve a localized message.
+ * @param key The key for the localized message.
+ * @return the message corresponding to the received
+ * key.
+ ****/
+
+ public static String lookupMessage(String key) {
+
+ return lookupMessage(key, null);
+
+ }
+
+ /* ************************************************
+ * lookupMessage:
+ * Retreive a localized message.
+ * @param key The key for the localized message.
+ * @param vals Array of values to be used in the
+ * message.
+ * @return the message corresponding to the received
+ * key, with the received values substituted where
+ * appropriate.
+ ****/
+
+ public static String lookupMessage(String key, String[] vals) {
+
+ String msg = "";
+ if (vals == null)
+ msg = langUtil.getTextMessage(key);
+ else {
+ switch (vals.length) {
+ case 1: msg = langUtil.getTextMessage(
+ key, vals[0]);
+ break;
+ case 2: msg = langUtil.getTextMessage(
+ key, vals[0], vals[1]);
+ break;
+ default: /* shouldn't happen */
+ break;
+ }
+ }
+
+ return msg;
+
+ }
+
+ /* ************************************************
+ * removeNewlines:
+ * Remove any newline characters from the received
+ * string (replace them with spaces).
+ * @param str The string from which we are removing
+ * all newline characters.
+ * @return The string, with all newline characters
+ * replaced with spaces.
+ ****/
+
+ public static String removeNewlines(String str) {
+
+ if (str == null)
+ // don't do anything.
+ return null;
+
+ StringBuffer result = null;
+ try {
+
+ BufferedReader strVal = new BufferedReader (new StringReader(str));
+ for (String txt = strVal.readLine(); txt != null;
+ txt = strVal.readLine())
+ {
+ if (result == null)
+ result = new StringBuffer(txt);
+ else {
+ result.append(" ");
+ result.append(txt);
+ }
+ }
+
+ return result.toString();
+
+ } catch (Exception e) {
+ // if something went wrong, just return the string as is--
+ // worst case is that the generated DDL is correct, it just
+ // can't be run in a DB2 CLP script (because of the newline
+ // characters).
+ return str;
+ }
+
+ }
+
+}
+
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/tools/ij.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/tools/ij.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/tools/ij.java Fri Sep 24 10:33:20 2004
@@ -1,76 +1,76 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.tools
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.tools;
-
-import org.apache.derby.iapi.services.info.JVMInfo;
-
-import org.apache.derby.impl.tools.ij.Main;
-
-import java.io.IOException;
-
-/**
-
- ij is Cloudscape's interactive JDBC scripting tool.
- It is a simple utility for running scripts against a Cloudscape database.
- You can also use it interactively to run ad hoc queries.
- ij provides several commands for ease in accessing a variety of JDBC features.
- <P>
-
- To run from the command line enter the following:
- <p>
- java [options] org.apache.derby.tools.ij [arguments]
- <P>
- ij is can also be used with any database server that supports a JDBC driver.
-*/
-public class ij {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- /**
- @exception IOException thrown if cannot access input or output files.
- */
- static public void main(String[] args) throws IOException {
-
- /* We decide which verion of ij (2.0 or 4.0) to
- * load based on the same criteria that the JDBC driver
- * uses.
- */
- if (JVMInfo.JDK_ID == 2)
- {
- Main.main(args);
- }
- else
- {
- org.apache.derby.impl.tools.ij.Main14.main(args);
- }
- }
-
- private ij() { // no instances allowed
- }
-
- public static String getArg(String param, String[] args)
- {
- return org.apache.derby.impl.tools.ij.util.getArg(param, args);
- }
-
- public static void getPropertyArg(String[] args) throws IOException
- {
- org.apache.derby.impl.tools.ij.util.getPropertyArg(args);
- }
-
- public static java.sql.Connection startJBMS()
- throws java.sql.SQLException, IllegalAccessException, ClassNotFoundException, InstantiationException
- {
- return org.apache.derby.impl.tools.ij.util.startJBMS();
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.tools
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.tools;
+
+import org.apache.derby.iapi.services.info.JVMInfo;
+
+import org.apache.derby.impl.tools.ij.Main;
+
+import java.io.IOException;
+
+/**
+
+ ij is Cloudscape's interactive JDBC scripting tool.
+ It is a simple utility for running scripts against a Cloudscape database.
+ You can also use it interactively to run ad hoc queries.
+ ij provides several commands for ease in accessing a variety of JDBC features.
+ <P>
+
+ To run from the command line enter the following:
+ <p>
+ java [options] org.apache.derby.tools.ij [arguments]
+ <P>
+ ij is can also be used with any database server that supports a JDBC driver.
+*/
+public class ij {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ /**
+ @exception IOException thrown if cannot access input or output files.
+ */
+ static public void main(String[] args) throws IOException {
+
+ /* We decide which verion of ij (2.0 or 4.0) to
+ * load based on the same criteria that the JDBC driver
+ * uses.
+ */
+ if (JVMInfo.JDK_ID == 2)
+ {
+ Main.main(args);
+ }
+ else
+ {
+ org.apache.derby.impl.tools.ij.Main14.main(args);
+ }
+ }
+
+ private ij() { // no instances allowed
+ }
+
+ public static String getArg(String param, String[] args)
+ {
+ return org.apache.derby.impl.tools.ij.util.getArg(param, args);
+ }
+
+ public static void getPropertyArg(String[] args) throws IOException
+ {
+ org.apache.derby.impl.tools.ij.util.getPropertyArg(args);
+ }
+
+ public static java.sql.Connection startJBMS()
+ throws java.sql.SQLException, IllegalAccessException, ClassNotFoundException, InstantiationException
+ {
+ return org.apache.derby.impl.tools.ij.util.startJBMS();
+ }
+}
Modified: incubator/derby/code/trunk/java/tools/org/apache/derby/tools/sysinfo.java
==============================================================================
--- incubator/derby/code/trunk/java/tools/org/apache/derby/tools/sysinfo.java (original)
+++ incubator/derby/code/trunk/java/tools/org/apache/derby/tools/sysinfo.java Fri Sep 24 10:33:20 2004
@@ -1,196 +1,196 @@
-/*
-
- Licensed Materials - Property of IBM
- Cloudscape - Package org.apache.derby.tools
- (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
- US Government Users Restricted Rights - Use, duplication or
- disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-
- */
-
-package org.apache.derby.tools;
-
-import org.apache.derby.iapi.services.info.ProductVersionHolder;
-import org.apache.derby.iapi.services.info.JVMInfo;
-import org.apache.derby.impl.tools.sysinfo.Main;
-
-/**
-
- This class displays system information to system out.
-
- To run from the command-line, enter the following:
- <p>
- <code>java org.apache.derby.tools.sysinfo</code>
- <p>
- <p>
- Also available on this class are methods which allow you to determine
- the version of the code for the system without actually booting a database.
- Please note that this is the Cloudscape version of the .jar files, not of your databases.
- <p>
- The numbering scheme for released Cloudscape products is <b><code>m1.m2.m3 </code></b>
- where <b><code>m1</code></b> is the major release version, <b><code>m2</code></b> is the minor release version,
- and <b><code>m3</code></b> is the maintenance level. Versions of the product with the same
- major and minor version numbers are considered feature compatible.
- <p>Valid major and minor versions are always greater than zero. Valid maintenance
- versions are greater than or equal to zero.
-
-
-*/
-public class sysinfo {
- /**
- IBM Copyright © notice.
- */
- public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
-
- static public void main(String[] args) {
- Main.main(args);
- }
-
- private sysinfo() { // no instances allowed
- }
-
- /**
- The genus name for the IBM Cloudscape code. Use this to determine the version of the
- IBM Cloudscape embedded code in cs.jar.
- */
- public static final String DBMS="DBMS";
-
- /**
- * The genus name for the tools code. Use this to determine the version of
- code in cstools.jar
- */
- public static final String TOOLS="tools";
-
-
- /**
- gets the major version of the IBM Cloudscape embedded code.
- @return the major version. Returns -1 if not found.
- */
- static public int getMajorVersion()
- {
- return getMajorVersion(DBMS);
- }
-
-
- /**
- gets the major version of the specified code library.
- @param genus which library to get the version of. Valid inputs include
- DBMS, TOOLS
- @return the major version. Return -1 if the information is not found.
- */
- static public int getMajorVersion(String genus)
- {
- ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
- if (pvh == null)
- {
- return -1;
- }
-
- return pvh.getMajorVersion();
- }
-
-
- /**
- gets the minor version of the IBM Cloudscape embedded code.
- @return the minor version. Returns -1 if not found.
- */
- static public int getMinorVersion()
- {
- return getMinorVersion(DBMS);
- }
-
- /**
- gets the minor version of the specified code library.
- @param genus which library to get the version of. Valid inputs include
- DBMS, TOOLS.
- @return the minor version. Return -1 if the information is not found.
- */
- static public int getMinorVersion(String genus)
- {
- ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
- if (pvh == null)
- {
- return -1;
- }
-
- return pvh.getMinorVersion();
- }
-
- /**
- gets the build number for the IBM Cloudscape embedded library
- @return the build number, or -1 if the information is not found.
- */
- static public int getBuildNumber()
- {
- return getBuildNumber("DBMS");
- }
-
- /**
- gets the build number for the specified library
- @param genus which library to get the build number for. Valid inputs are
- DBMS, TOOLS
- @return the build number, or -1 if the information is not found.
- */
- static public int getBuildNumber(String genus)
- {
- ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
- if (pvh == null)
- {
- return -1;
- }
-
- return pvh.getBuildNumber();
- }
-
-
- /**
- gets the product name for the IBM Cloudscape embedded library
- @return the name
- */
- static public String getProductName()
- {
- return getProductName("DBMS");
- }
-
- /**
- gets the external name for the specified code library.
- @param genus which library to get the name for
- @return the name.
- */
-
- static public String getProductName(String genus)
- {
- ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
- if (pvh == null)
- {
- return Main.getTextMessage ("SIF01.K");
- }
-
- return pvh.getProductName();
- }
-
- /**
- Return the version information string for the specified library including alpha or beta indicators.
- */
- static public String getVersionString() {
- return getVersionString(DBMS);
- }
-
- /**
- Return the version information string for the IBM Cloudscape embedded library including alpha or beta indicators.
- */
- static public String getVersionString(String genus) {
-
- ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
- if (pvh == null)
- {
- return Main.getTextMessage ("SIF01.K");
- }
-
- return pvh.getVersionBuildString(false);
- }
-
- public static void getInfo (java.io.PrintWriter out) {
- Main.getMainInfo(out, false);
- }
-}
+/*
+
+ Licensed Materials - Property of IBM
+ Cloudscape - Package org.apache.derby.tools
+ (C) Copyright IBM Corp. 1998, 2004. All Rights Reserved.
+ US Government Users Restricted Rights - Use, duplication or
+ disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+
+ */
+
+package org.apache.derby.tools;
+
+import org.apache.derby.iapi.services.info.ProductVersionHolder;
+import org.apache.derby.iapi.services.info.JVMInfo;
+import org.apache.derby.impl.tools.sysinfo.Main;
+
+/**
+
+ This class displays system information to system out.
+
+ To run from the command-line, enter the following:
+ <p>
+ <code>java org.apache.derby.tools.sysinfo</code>
+ <p>
+ <p>
+ Also available on this class are methods which allow you to determine
+ the version of the code for the system without actually booting a database.
+ Please note that this is the Cloudscape version of the .jar files, not of your databases.
+ <p>
+ The numbering scheme for released Cloudscape products is <b><code>m1.m2.m3 </code></b>
+ where <b><code>m1</code></b> is the major release version, <b><code>m2</code></b> is the minor release version,
+ and <b><code>m3</code></b> is the maintenance level. Versions of the product with the same
+ major and minor version numbers are considered feature compatible.
+ <p>Valid major and minor versions are always greater than zero. Valid maintenance
+ versions are greater than or equal to zero.
+
+
+*/
+public class sysinfo {
+ /**
+ IBM Copyright © notice.
+ */
+ public static final String copyrightNotice = org.apache.derby.iapi.reference.Copyright.SHORT_1998_2004;
+
+ static public void main(String[] args) {
+ Main.main(args);
+ }
+
+ private sysinfo() { // no instances allowed
+ }
+
+ /**
+ The genus name for the IBM Cloudscape code. Use this to determine the version of the
+ IBM Cloudscape embedded code in cs.jar.
+ */
+ public static final String DBMS="DBMS";
+
+ /**
+ * The genus name for the tools code. Use this to determine the version of
+ code in cstools.jar
+ */
+ public static final String TOOLS="tools";
+
+
+ /**
+ gets the major version of the IBM Cloudscape embedded code.
+ @return the major version. Returns -1 if not found.
+ */
+ static public int getMajorVersion()
+ {
+ return getMajorVersion(DBMS);
+ }
+
+
+ /**
+ gets the major version of the specified code library.
+ @param genus which library to get the version of. Valid inputs include
+ DBMS, TOOLS
+ @return the major version. Return -1 if the information is not found.
+ */
+ static public int getMajorVersion(String genus)
+ {
+ ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
+ if (pvh == null)
+ {
+ return -1;
+ }
+
+ return pvh.getMajorVersion();
+ }
+
+
+ /**
+ gets the minor version of the IBM Cloudscape embedded code.
+ @return the minor version. Returns -1 if not found.
+ */
+ static public int getMinorVersion()
+ {
+ return getMinorVersion(DBMS);
+ }
+
+ /**
+ gets the minor version of the specified code library.
+ @param genus which library to get the version of. Valid inputs include
+ DBMS, TOOLS.
+ @return the minor version. Return -1 if the information is not found.
+ */
+ static public int getMinorVersion(String genus)
+ {
+ ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
+ if (pvh == null)
+ {
+ return -1;
+ }
+
+ return pvh.getMinorVersion();
+ }
+
+ /**
+ gets the build number for the IBM Cloudscape embedded library
+ @return the build number, or -1 if the information is not found.
+ */
+ static public int getBuildNumber()
+ {
+ return getBuildNumber("DBMS");
+ }
+
+ /**
+ gets the build number for the specified library
+ @param genus which library to get the build number for. Valid inputs are
+ DBMS, TOOLS
+ @return the build number, or -1 if the information is not found.
+ */
+ static public int getBuildNumber(String genus)
+ {
+ ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
+ if (pvh == null)
+ {
+ return -1;
+ }
+
+ return pvh.getBuildNumber();
+ }
+
+
+ /**
+ gets the product name for the IBM Cloudscape embedded library
+ @return the name
+ */
+ static public String getProductName()
+ {
+ return getProductName("DBMS");
+ }
+
+ /**
+ gets the external name for the specified code library.
+ @param genus which library to get the name for
+ @return the name.
+ */
+
+ static public String getProductName(String genus)
+ {
+ ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
+ if (pvh == null)
+ {
+ return Main.getTextMessage ("SIF01.K");
+ }
+
+ return pvh.getProductName();
+ }
+
+ /**
+ Return the version information string for the specified library including alpha or beta indicators.
+ */
+ static public String getVersionString() {
+ return getVersionString(DBMS);
+ }
+
+ /**
+ Return the version information string for the IBM Cloudscape embedded library including alpha or beta indicators.
+ */
+ static public String getVersionString(String genus) {
+
+ ProductVersionHolder pvh = ProductVersionHolder.getProductVersionHolderFromMyEnv(genus);
+ if (pvh == null)
+ {
+ return Main.getTextMessage ("SIF01.K");
+ }
+
+ return pvh.getVersionBuildString(false);
+ }
+
+ public static void getInfo (java.io.PrintWriter out) {
+ Main.getMainInfo(out, false);
+ }
+}