Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / sql / compile / ActivationClassBuilder.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/ActivationClassBuilder.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/sql/compile/ActivationClassBuilder.java
new file mode 100644 (file)
index 0000000..b47dc42
--- /dev/null
@@ -0,0 +1,445 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.ActivationClassBuilder\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.services.compiler.ClassBuilder;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+import org.apache.derby.iapi.sql.compile.CodeGeneration;\r
+\r
+import org.apache.derby.iapi.sql.execute.CursorResultSet;\r
+\r
+import org.apache.derby.iapi.sql.ResultSet;\r
+\r
+import org.apache.derby.iapi.sql.execute.ExecRow;\r
+\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.TypeId;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.loader.GeneratedMethod;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.lang.reflect.Modifier;\r
+\r
+import java.io.PrintWriter;\r
+\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.util.Hashtable;\r
+\r
+/**\r
+ * ActivationClassBuilder\r
+ * provides an interface to satisfy generation's\r
+ * common tasks in building an activation class,\r
+ * as well as a repository for the JavaFactory used\r
+ * to generate the basic language constructs for the methods in the class.\r
+ * Common tasks include the setting of a static field for each\r
+ * expression function that gets added, the creation\r
+ * of the execute method that gets expanded as the query tree\r
+ * is walked, setting the superclass.\r
+ * <p>\r
+ * An activation class is defined for each statement. It has\r
+ * the following basic layout: TBD\r
+ * See the document\r
+ * \\Jeeves\Unversioned Repository 1\Internal Technical Documents\Other\GenAndExec.doc\r
+ * for details.\r
+ * <p>\r
+ * We could also verify methods as they are\r
+ * added, to have 0 parameters, ...\r
+ *\r
+ */\r
+class ActivationClassBuilder   extends ExpressionClassBuilder\r
+{\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // CONSTANTS\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // STATE\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       private LocalField      targetResultSetField;\r
+       private LocalField  cursorResultSetField;\r
+\r
+       private MethodBuilder closeActivationMethod;\r
+\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // CONSTRUCTOR\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+        * By the time this is done, it has constructed the following class:\r
+        * <pre>\r
+        *    public class #className extends #superClass {\r
+        *              // public void reset() { return; }\r
+        *              public ResultSet execute() throws StandardException {\r
+        *                      throwIfClosed("execute");\r
+        *                      // statements must be added here\r
+        *              }\r
+        *              public #className() { super(); }\r
+        *    }\r
+        * </pre>\r
+        *\r
+        * @exception StandardException thrown on failure\r
+        */\r
+       ActivationClassBuilder (String superClass, CompilerContext cc) throws StandardException\r
+       {\r
+               super( superClass, (String) null, cc );\r
+               executeMethod = beginExecuteMethod();\r
+       }\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // ACCESSORS\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+         *     Get the package name that this generated class lives in\r
+         *\r
+         *     @return package name\r
+         */\r
+    public     String  getPackageName()\r
+       {       return  CodeGeneration.GENERATED_PACKAGE_PREFIX; }\r
+\r
+       /**\r
+               The base class for activations is BaseActivation\r
+        */\r
+       String getBaseClassName() {\r
+           return ClassName.BaseActivation;\r
+       }\r
+\r
+\r
+       /**\r
+         *     Get the number of ExecRows to allocate\r
+         *\r
+         * @exception StandardException thrown on failure\r
+         *     @return package name\r
+         */\r
+       public  int             getRowCount()\r
+                throws StandardException\r
+       {\r
+               return  myCompCtx.getNumResultSets();\r
+       }\r
+\r
+       /**\r
+        * Generate the assignment for numSubqueries = x\r
+        *\r
+        * @exception StandardException thrown on failure\r
+        */\r
+       public   void   setNumSubqueries()\r
+       {\r
+               int                             numSubqueries = myCompCtx.getNumSubquerys();\r
+\r
+               // If there are no subqueries then\r
+               // the field is set to the correctly\r
+               // value (0) by java.\r
+               if (numSubqueries == 0)\r
+                       return;\r
+\r
+               /* Generated code is:\r
+                *              numSubqueries = x;\r
+                */\r
+               constructor.pushThis();\r
+               constructor.push(numSubqueries);\r
+               constructor.putField(ClassName.BaseActivation, "numSubqueries", "int");\r
+               constructor.endStatement();\r
+       }\r
+\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // EXECUTE METHODS\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+        * By the time this is done, it has generated the following code\r
+        * <pre>\r
+        *              public ResultSet execute() throws StandardException {\r
+        *                      throwIfClosed("execute");\r
+        *                      // statements must be added here\r
+        *              }\r
+        *    }\r
+        * </pre>\r
+        *\r
+        * @exception StandardException thrown on failure\r
+        */\r
+       private MethodBuilder   beginExecuteMethod()\r
+               throws StandardException\r
+       {\r
+               // create a reset method that does nothing.\r
+               // REVISIT: this might better belong in the Activation\r
+               // superclasses ?? not clear yet what it needs to do.\r
+\r
+               // don't yet need a reset method here. when we do,\r
+               // it will need to call super.reset() as well as\r
+               // whatever it does.\r
+               // mb = cb.newMethodBuilder(\r
+               //      Modifier.PUBLIC, "void", "reset");\r
+               // mb.addStatement(javaFac.newStatement(\r
+               //              javaFac.newSpecialMethodCall(\r
+               //                      thisExpression(),\r
+               //                      BaseActivation.CLASS_NAME,\r
+               //                      "reset", "void")));\r
+               // mb.addStatement(javaFac.newReturnStatement());\r
+               // mb.complete(); // there is nothing else.\r
+\r
+\r
+               // This method is an implementation of the interface method\r
+               // Activation - ResultSet execute()\r
+\r
+               // create an empty execute method\r
+               MethodBuilder mb = cb.newMethodBuilder(Modifier.PUBLIC,\r
+                       ClassName.ResultSet, "execute");\r
+               mb.addThrownException(ClassName.StandardException);\r
+\r
+               // put a 'throwIfClosed("execute");' statement into the execute method.\r
+               mb.pushThis(); // instance\r
+               mb.push("execute");\r
+               mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "throwIfClosed", "void", 1);\r
+\r
+               // call this.startExecution(), so the parent class can know an execution\r
+               // has begun.\r
+\r
+               mb.pushThis(); // instance\r
+               mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "startExecution", "void", 0);\r
+\r
+               return  mb;\r
+       }\r
+\r
+       MethodBuilder startResetMethod() {\r
+               MethodBuilder mb = cb.newMethodBuilder(Modifier.PUBLIC,\r
+                       "void", "reset");\r
+\r
+               mb.addThrownException(ClassName.StandardException);\r
+               mb.pushThis();\r
+               mb.callMethod(VMOpcode.INVOKESPECIAL, ClassName.BaseActivation, "reset", "void", 0);\r
+\r
+\r
+               return mb;\r
+       }\r
+\r
+       /**\r
+        * An execute method always ends in a return statement, returning\r
+        * the result set that has been constructed.  We want to\r
+        * do some bookkeeping on that statement, so we generate\r
+        * the return given the result set.\r
+\r
+          Upon entry the only word on the stack is the result set expression\r
+        */\r
+       void finishExecuteMethod(boolean genMarkAsTopNode) {\r
+\r
+               /* We only call markAsTopResultSet() for selects.\r
+                * Non-select DML marks the top NoPutResultSet in the constructor.\r
+                * Needed for closing down resultSet on an error.\r
+                */\r
+               if (genMarkAsTopNode)\r
+               {\r
+                       // dup the result set to leave one for the return and one for this call\r
+                       executeMethod.dup();\r
+                       executeMethod.cast(ClassName.NoPutResultSet);\r
+                       executeMethod.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "markAsTopResultSet", "void", 0);\r
+               }\r
+\r
+               /* return resultSet */\r
+               executeMethod.methodReturn();\r
+               executeMethod.complete();\r
+\r
+               getClassBuilder().newFieldWithAccessors("getExecutionCount", "setExecutionCount",\r
+                       Modifier.PROTECTED, true, "int");\r
+\r
+               getClassBuilder().newFieldWithAccessors("getRowCountCheckVector", "setRowCountCheckVector",\r
+                       Modifier.PROTECTED, true, "java.util.Vector");\r
+\r
+               getClassBuilder().newFieldWithAccessors("getStalePlanCheckInterval", "setStalePlanCheckInterval",\r
+                       Modifier.PROTECTED, true, "int");\r
+\r
+               if (closeActivationMethod != null) {\r
+                       closeActivationMethod.methodReturn();\r
+                       closeActivationMethod.complete();\r
+               }\r
+       }\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // CURSOR SUPPORT\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+        * Updatable cursors\r
+        * need to add a getter method for use in BaseActivation to access\r
+        * the result set that identifies target rows for a positioned\r
+        * update or delete.\r
+        * <p>\r
+        * The code that is generated is:\r
+        * <pre><verbatim>\r
+        *  public CursorResultSet getTargetResultSet() {\r
+        *          return targetResultSet;\r
+        *  }\r
+        *\r
+        *  public CursorResultSet getCursorResultSet() {\r
+        *              return cursorResultSet;\r
+        *  }\r
+        * </verbatim></pre>\r
+        *\r
+        */\r
+       void addCursorPositionCode() {\r
+\r
+               // the getter\r
+               // This method is an implementation of the interface method\r
+               // CursorActivation - CursorResultSet getTargetResultSet()\r
+               MethodBuilder getter = cb.newMethodBuilder(Modifier.PUBLIC, \r
+                       ClassName.CursorResultSet, "getTargetResultSet");\r
+\r
+               getter.getField(targetResultSetField);\r
+               getter.methodReturn();\r
+               getter.complete();\r
+\r
+               // This method is an implementation of the interface method\r
+               // CursorActivation - CursorResultSet getCursorResultSet()\r
+\r
+               getter = cb.newMethodBuilder(Modifier.PUBLIC, \r
+                       ClassName.CursorResultSet, "getCursorResultSet");\r
+\r
+               getter.getField(cursorResultSetField);\r
+               getter.methodReturn();\r
+               getter.complete();\r
+       }\r
+\r
+       /**\r
+        * Updatable cursors\r
+        * need to add a field and its initialization\r
+        * for use in BaseActivation to access the result set that\r
+        * identifies target rows for a positioned update or delete.\r
+        * <p>\r
+        * The code that is generated is:\r
+        * <pre><verbatim>\r
+        *  private CursorResultSet targetResultSet;\r
+        *\r
+        * </verbatim></pre>\r
+        *\r
+        * The expression that is generated is:\r
+        * <pre><verbatim>\r
+        *  (ResultSet) (targetResultSet = (CursorResultSet) #expression#)\r
+        * </verbatim></pre>\r
+        *\r
+        */\r
+       void rememberCursorTarget(MethodBuilder mb) {\r
+\r
+               // the field\r
+               targetResultSetField = cb.addField(ClassName.CursorResultSet,\r
+                                       "targetResultSet",\r
+                                       Modifier.PRIVATE);\r
+\r
+               mb.cast(ClassName.CursorResultSet);\r
+               mb.putField(targetResultSetField);\r
+               mb.cast(ClassName.NoPutResultSet);\r
+       }\r
+\r
+       /**\r
+        * Updatable cursors\r
+        * need to add a field and its initialization\r
+        * for use in BaseActivation to access the result set that\r
+        * identifies cursor result rows for a positioned update or delete.\r
+        * <p>\r
+        * The code that is generated is:\r
+        * <pre><verbatim>\r
+        *  private CursorResultSet cursorResultSet;\r
+        *\r
+        * </verbatim></pre>\r
+        *\r
+        * The expression that is generated is:\r
+        * <pre><verbatim>\r
+        *  (ResultSet) (cursorResultSet = (CursorResultSet) #expression#)\r
+        * </verbatim></pre>\r
+\r
+       The expression must be the top stack word when this method is called.\r
+        *\r
+        */\r
+       void rememberCursor(MethodBuilder mb) {\r
+\r
+               // the field\r
+               cursorResultSetField = cb.addField(ClassName.CursorResultSet,\r
+                                       "cursorResultSet",\r
+                                       Modifier.PRIVATE);\r
+\r
+               mb.cast(ClassName.CursorResultSet);\r
+               mb.putField(cursorResultSetField);\r
+               mb.cast(ClassName.ResultSet);\r
+       }\r
+\r
+       ///////////////////////////////////////////////////////////////////////\r
+       //\r
+       // CURRENT DATE/TIME SUPPORT\r
+       //\r
+       ///////////////////////////////////////////////////////////////////////\r
+\r
+       /*\r
+               The first time a current datetime is needed, create the class\r
+               level support for it. The first half of the logic is in our parent\r
+               class.\r
+        */\r
+       protected LocalField getCurrentSetup()\r
+       {\r
+               if (cdtField != null) return cdtField;\r
+\r
+               LocalField lf = super.getCurrentSetup();\r
+\r
+               // 3) the execute method gets a statement (prior to the return)\r
+               //    to tell cdt to restart:\r
+               //        cdt.forget();\r
+\r
+               executeMethod.getField(lf);\r
+               executeMethod.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "forget", "void", 0);\r
+\r
+               return lf;\r
+       }\r
+\r
+       MethodBuilder getCloseActivationMethod() {\r
+\r
+               if (closeActivationMethod == null) {\r
+                       closeActivationMethod = cb.newMethodBuilder(Modifier.PUBLIC, "void", "closeActivationAction");\r
+                       closeActivationMethod.addThrownException("java.lang.Exception");\r
+               }\r
+               return closeActivationMethod;\r
+       }\r
+}\r
+\r