Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / IndexToBaseRowNode.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/IndexToBaseRowNode.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/IndexToBaseRowNode.java
new file mode 100644 (file)
index 0000000..1924537
--- /dev/null
@@ -0,0 +1,412 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.IndexToBaseRowNode\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.context.ContextManager;\r
+\r
+import org.apache.derby.iapi.sql.compile.AccessPath;\r
+import org.apache.derby.iapi.sql.compile.CostEstimate;\r
+import org.apache.derby.iapi.sql.compile.Optimizable;\r
+import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;\r
+\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.sql.execute.NoPutResultSet;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.ResultSet;\r
+\r
+import org.apache.derby.iapi.services.loader.GeneratedMethod;\r
+\r
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;\r
+\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+\r
+import org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.util.Properties;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * This node type translates an index row to a base row.  It takes a\r
+ * FromBaseTable as its source ResultSetNode, and generates an\r
+ * IndexRowToBaseRowResultSet that takes a TableScanResultSet on an\r
+ * index conglomerate as its source.\r
+ */\r
+public class IndexToBaseRowNode extends FromTable\r
+{\r
+       protected FromBaseTable source;\r
+       protected ConglomerateDescriptor        baseCD;\r
+       protected boolean       cursorTargetTable;\r
+       protected PredicateList restrictionList;\r
+       protected boolean       forUpdate;\r
+       private FormatableBitSet        heapReferencedCols;\r
+       private FormatableBitSet        indexReferencedCols;\r
+       private FormatableBitSet        allReferencedCols;\r
+       private FormatableBitSet        heapOnlyReferencedCols;\r
+\r
+       public void init(\r
+                       Object  source,\r
+                       Object  baseCD,\r
+                       Object  resultColumns,\r
+                       Object  cursorTargetTable,\r
+                       Object heapReferencedCols,\r
+                       Object indexReferencedCols,\r
+                       Object restrictionList,\r
+                       Object forUpdate,\r
+                       Object tableProperties)\r
+       {\r
+               super.init(null, tableProperties);\r
+               this.source = (FromBaseTable) source;\r
+               this.baseCD = (ConglomerateDescriptor) baseCD;\r
+               this.resultColumns = (ResultColumnList) resultColumns;\r
+               this.cursorTargetTable = ((Boolean) cursorTargetTable).booleanValue();\r
+               this.restrictionList = (PredicateList) restrictionList;\r
+               this.forUpdate = ((Boolean) forUpdate).booleanValue();\r
+               this.heapReferencedCols = (FormatableBitSet) heapReferencedCols;\r
+               this.indexReferencedCols = (FormatableBitSet) indexReferencedCols;\r
+\r
+               if (this.indexReferencedCols == null) {\r
+                       this.allReferencedCols = this.heapReferencedCols;\r
+                       heapOnlyReferencedCols = this.heapReferencedCols;\r
+               }\r
+               else {\r
+                       this.allReferencedCols =\r
+                               new FormatableBitSet(this.heapReferencedCols);\r
+                       this.allReferencedCols.or(this.indexReferencedCols);\r
+                       heapOnlyReferencedCols =\r
+                               new FormatableBitSet(allReferencedCols);\r
+                       heapOnlyReferencedCols.xor(this.indexReferencedCols);\r
+               }\r
+       }\r
+\r
+       /** @see Optimizable#forUpdate */\r
+       public boolean forUpdate()\r
+       {\r
+               return source.forUpdate();\r
+       }\r
+\r
+       /** @see Optimizable#getTrulyTheBestAccessPath */\r
+       public AccessPath getTrulyTheBestAccessPath()\r
+       {\r
+               // Get AccessPath comes from base table.\r
+               return ((Optimizable) source).getTrulyTheBestAccessPath();\r
+       }\r
+\r
+       public CostEstimate getCostEstimate()\r
+       {\r
+               return source.getTrulyTheBestAccessPath().getCostEstimate();\r
+       }\r
+\r
+       public CostEstimate getFinalCostEstimate()\r
+       {\r
+               return source.getFinalCostEstimate();\r
+       }\r
+\r
+       /**\r
+        * Return whether or not the underlying ResultSet tree\r
+        * is ordered on the specified columns.\r
+        * RESOLVE - This method currently only considers the outermost table \r
+        * of the query block.\r
+        *\r
+        * @param       crs                                     The specified ColumnReference[]\r
+        * @param       permuteOrdering         Whether or not the order of the CRs in the array can be permuted\r
+        * @param       fbtVector                       Vector that is to be filled with the FromBaseTable      \r
+        *\r
+        * @return      Whether the underlying ResultSet tree\r
+        * is ordered on the specified column.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       boolean isOrderedOn(ColumnReference[] crs, boolean permuteOrdering, Vector fbtVector)\r
+                               throws StandardException\r
+       {\r
+               return source.isOrderedOn(crs, permuteOrdering, fbtVector);\r
+       }\r
+\r
+       /**\r
+        * Generation of an IndexToBaseRowNode creates an\r
+        * IndexRowToBaseRowResultSet, which uses the RowLocation in the last\r
+        * column of an index row to get the row from the base conglomerate (heap).\r
+        *\r
+        * @param acb   The ActivationClassBuilder for the class being built\r
+        * @param mb the method  for the method to be built\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void generate(ActivationClassBuilder acb,\r
+                                                               MethodBuilder mb)\r
+                                                       throws StandardException\r
+       {\r
+               ValueNode               restriction = null;\r
+\r
+               /*\r
+               ** Get the next ResultSet #, so that we can number this ResultSetNode,\r
+               ** its ResultColumnList and ResultSet.\r
+               */\r
+               assignResultSetNumber();\r
+\r
+               // Get the CostEstimate info for the underlying scan\r
+               costEstimate = getFinalCostEstimate();\r
+\r
+               /* Put the predicates back into the tree */\r
+               if (restrictionList != null)\r
+               {\r
+                       restriction = restrictionList.restorePredicates();\r
+                       /* Allow the restrictionList to get garbage collected now\r
+                        * that we're done with it.\r
+                        */\r
+                       restrictionList = null;\r
+               }\r
+\r
+               // for the restriction, we generate an exprFun\r
+               // that evaluates the expression of the clause\r
+               // against the current row of the child's result.\r
+               // if the restriction is empty, simply pass null\r
+               // to optimize for run time performance.\r
+\r
+               // generate the function and initializer:\r
+               // Note: Boolean lets us return nulls (boolean would not)\r
+               // private Boolean exprN()\r
+               // {\r
+               //   return <<restriction.generate(ps)>>;\r
+               // }\r
+               // static Method exprN = method pointer to exprN;\r
+\r
+\r
+\r
+               int heapColRefItem = -1;\r
+               if (heapReferencedCols != null)\r
+               {\r
+                       heapColRefItem = acb.addItem(heapReferencedCols);\r
+               }\r
+               int allColRefItem = -1;\r
+               if (allReferencedCols != null)\r
+               {\r
+                       allColRefItem = acb.addItem(allReferencedCols);\r
+               }\r
+               int heapOnlyColRefItem = -1;\r
+               if (heapOnlyReferencedCols != null)\r
+               {\r
+                       heapOnlyColRefItem = acb.addItem(heapOnlyReferencedCols);\r
+               }\r
+\r
+               /* Create the ReferencedColumnsDescriptorImpl which tells which columns\r
+                * come from the index.\r
+                */\r
+               int indexColMapItem = acb.addItem(new ReferencedColumnsDescriptorImpl(getIndexColMapping()));\r
+               long heapConglomNumber = baseCD.getConglomerateNumber();\r
+               StaticCompiledOpenConglomInfo scoci = getLanguageConnectionContext().\r
+                                                                                               getTransactionCompile().\r
+                                                                                                       getStaticCompiledConglomInfo(heapConglomNumber);\r
+\r
+               acb.pushGetResultSetFactoryExpression(mb);\r
+\r
+               mb.push(heapConglomNumber);\r
+               mb.push(acb.addItem(scoci));\r
+               source.generate(acb, mb);\r
+               \r
+               mb.upCast(ClassName.NoPutResultSet);\r
+\r
+               resultColumns.generateHolder(acb, mb,  heapReferencedCols, indexReferencedCols);\r
+               mb.push(resultSetNumber);\r
+               mb.push(source.getBaseTableName());\r
+               mb.push(heapColRefItem);\r
+\r
+               mb.push(allColRefItem);\r
+               mb.push(heapOnlyColRefItem);\r
+\r
+               mb.push(indexColMapItem);\r
+\r
+               // if there is no restriction, we just want to pass null.\r
+               if (restriction == null)\r
+               {\r
+                       mb.pushNull(ClassName.GeneratedMethod);\r
+               }\r
+               else\r
+               {\r
+                       // this sets up the method and the static field.\r
+                       // generates:\r
+                       //      Object userExprFun { }\r
+                       MethodBuilder userExprFun = acb.newUserExprFun();\r
+\r
+                       // restriction knows it is returning its value;\r
+       \r
+                       /* generates:\r
+                        *    return <restriction.generate(acb)>;\r
+                        * and adds it to userExprFun\r
+                        * NOTE: The explicit cast to DataValueDescriptor is required\r
+                        * since the restriction may simply be a boolean column or subquery\r
+                        * which returns a boolean.  For example:\r
+                        *              where booleanColumn\r
+                        */\r
+                       restriction.generate(acb, userExprFun);\r
+                       userExprFun.methodReturn();\r
+\r
+                       // we are done modifying userExprFun, complete it.\r
+                       userExprFun.complete();\r
+\r
+                       // restriction is used in the final result set as an access of the new static\r
+                       // field holding a reference to this new method.\r
+                       // generates:\r
+                       //      ActivationClass.userExprFun\r
+                       // which is the static field that "points" to the userExprFun\r
+                       // that evaluates the where clause.\r
+                       acb.pushMethodReference(mb, userExprFun);\r
+               }\r
+\r
+               mb.push(forUpdate);\r
+               mb.push(costEstimate.rowCount());\r
+               mb.push(costEstimate.getEstimatedCost());\r
+\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getIndexRowToBaseRowResultSet",\r
+                                               ClassName.NoPutResultSet, 14);\r
+\r
+               /* The IndexRowToBaseRowResultSet generator is what we return */\r
+\r
+               /*\r
+               ** Remember if this result set is the cursor target table, so we\r
+               ** can know which table to use when doing positioned update and delete.\r
+               */\r
+               if (cursorTargetTable)\r
+               {\r
+                       acb.rememberCursorTarget(mb);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Return whether or not the underlying ResultSet tree will return\r
+        * a single row, at most.\r
+        * This is important for join nodes where we can save the extra next\r
+        * on the right side if we know that it will return at most 1 row.\r
+        *\r
+        * @return Whether or not the underlying ResultSet tree will return a single row.\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public boolean isOneRowResultSet()      throws StandardException\r
+       {\r
+               // Default is false\r
+               return source.isOneRowResultSet();\r
+       }\r
+\r
+       /**\r
+        * Return whether or not the underlying FBT is for NOT EXISTS.\r
+        *\r
+        * @return Whether or not the underlying FBT is for NOT EXISTS.\r
+        */\r
+       public boolean isNotExists()\r
+       {\r
+               return source.isNotExists();\r
+       }\r
+\r
+       /**\r
+        * Decrement (query block) level (0-based) for this FromTable.\r
+        * This is useful when flattening a subquery.\r
+        *\r
+        * @param decrement     The amount to decrement by.\r
+        */\r
+       void decrementLevel(int decrement)\r
+       {\r
+               source.decrementLevel(decrement);\r
+       }\r
+\r
+       /**\r
+        * Get the lock mode for the target of an update statement\r
+        * (a delete or update).  The update mode will always be row for\r
+        * CurrentOfNodes.  It will be table if there is no where clause.\r
+        *\r
+        * @return      The lock mode\r
+        */\r
+       public int updateTargetLockMode()\r
+       {\r
+               return source.updateTargetLockMode();\r
+       }\r
+\r
+       /**\r
+        * @see ResultSetNode#adjustForSortElimination\r
+        */\r
+       void adjustForSortElimination()\r
+       {\r
+               /* NOTE: We use a different method to tell a FBT that\r
+                * it cannot do a bulk fetch as the ordering issues are\r
+                * specific to a FBT being under an IRTBR as opposed to a\r
+                * FBT being under a PRN, etc.\r
+                */\r
+               source.disableBulkFetch();\r
+       }\r
+\r
+       /**\r
+        * @see ResultSetNode#adjustForSortElimination\r
+        */\r
+       void adjustForSortElimination(RequiredRowOrdering rowOrdering)\r
+               throws StandardException\r
+       {\r
+               /* rowOrdering is not important to this specific node, so\r
+                * just call the no-arg version of the method.\r
+                */\r
+               adjustForSortElimination();\r
+\r
+               /* Now pass the rowOrdering down to source, which may\r
+                * need to do additional work. DERBY-3279.\r
+                */\r
+               source.adjustForSortElimination(rowOrdering);\r
+       }\r
+\r
+       /** \r
+        * Fill in the column mapping for those columns coming from the index.\r
+        *\r
+        * @return The int[] with the mapping.\r
+        */\r
+       private int[] getIndexColMapping()\r
+       {\r
+               int             rclSize = resultColumns.size();\r
+               int[]   indexColMapping = new int[rclSize];\r
+\r
+               for (int index = 0; index < rclSize; index++)\r
+               {\r
+                       ResultColumn rc = (ResultColumn) resultColumns.elementAt(index);\r
+                       if (indexReferencedCols != null && rc.getExpression() instanceof VirtualColumnNode)\r
+                       {\r
+                               // Column is coming from index\r
+                               VirtualColumnNode vcn = (VirtualColumnNode) rc.getExpression();\r
+                               indexColMapping[index] =\r
+                                       vcn.getSourceColumn().getVirtualColumnId() - 1;\r
+                       }\r
+                       else\r
+                       {\r
+                               // Column is not coming from index\r
+                               indexColMapping[index] = -1;\r
+                       }\r
+               }\r
+\r
+               return indexColMapping;\r
+       }\r
+\r
+}\r