--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.BaseJoinStrategy\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.loader.GeneratedMethod;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.sql.compile.ExpressionClassBuilderInterface;\r
+import org.apache.derby.iapi.sql.compile.JoinStrategy;\r
+import org.apache.derby.iapi.sql.compile.Optimizable;\r
+import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+\r
+import org.apache.derby.iapi.util.PropertyUtil;\r
+\r
+abstract class BaseJoinStrategy implements JoinStrategy {\r
+ BaseJoinStrategy() {\r
+ }\r
+\r
+ /** @see JoinStrategy#bulkFetchOK */\r
+ public boolean bulkFetchOK() {\r
+ return true;\r
+ }\r
+\r
+ /** @see JoinStrategy#ignoreBulkFetch */\r
+ public boolean ignoreBulkFetch() {\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Push the first set of common arguments for obtaining a scan ResultSet from\r
+ * ResultSetFactory.\r
+ * The first 11 arguments are common for these ResultSet getters\r
+ * <UL>\r
+ * <LI> ResultSetFactory.getBulkTableScanResultSet\r
+ * <LI> ResultSetFactory.getHashScanResultSet\r
+ * <LI> ResultSetFactory.getTableScanResultSet\r
+ * <LI> ResultSetFactory.getRaDependentTableScanResultSet\r
+ * </UL>\r
+ * @param tc\r
+ * @param mb\r
+ * @param innerTable\r
+ * @param predList\r
+ * @param acbi\r
+ * @param resultRowAllocator\r
+ * @throws StandardException\r
+ */\r
+ void fillInScanArgs1(\r
+ TransactionController tc,\r
+ MethodBuilder mb,\r
+ Optimizable innerTable,\r
+ OptimizablePredicateList predList,\r
+ ExpressionClassBuilderInterface acbi,\r
+ MethodBuilder resultRowAllocator\r
+ )\r
+ throws StandardException {\r
+ boolean sameStartStopPosition = predList.sameStartStopPosition();\r
+ ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;\r
+ long conglomNumber = \r
+ innerTable.getTrulyTheBestAccessPath().\r
+ getConglomerateDescriptor().\r
+ getConglomerateNumber();\r
+ StaticCompiledOpenConglomInfo scoci = tc.getStaticCompiledConglomInfo(conglomNumber);\r
+ \r
+ acb.pushThisAsActivation(mb);\r
+ mb.push(conglomNumber);\r
+ mb.push(acb.addItem(scoci));\r
+\r
+ acb.pushMethodReference(mb, resultRowAllocator);\r
+ mb.push(innerTable.getResultSetNumber());\r
+\r
+ predList.generateStartKey(acb, mb, innerTable);\r
+ mb.push(predList.startOperator(innerTable));\r
+\r
+ if (! sameStartStopPosition) {\r
+ predList.generateStopKey(acb, mb, innerTable);\r
+ } else {\r
+ mb.pushNull(ClassName.GeneratedMethod);\r
+ }\r
+\r
+ mb.push(predList.stopOperator(innerTable));\r
+ mb.push(sameStartStopPosition);\r
+\r
+ predList.generateQualifiers(acb, mb, innerTable, true);\r
+ mb.upCast(ClassName.Qualifier + "[][]");\r
+ }\r
+\r
+ final void fillInScanArgs2(MethodBuilder mb,\r
+ Optimizable innerTable,\r
+ int bulkFetch,\r
+ int colRefItem,\r
+ int indexColItem,\r
+ int lockMode,\r
+ boolean tableLocked,\r
+ int isolationLevel) \r
+ throws StandardException\r
+ {\r
+ mb.push(innerTable.getBaseTableName());\r
+ //User may have supplied optimizer overrides in the sql\r
+ //Pass them onto execute phase so it can be shown in \r
+ //run time statistics.\r
+ if (innerTable.getProperties() != null)\r
+ mb.push(PropertyUtil.sortProperties(innerTable.getProperties()));\r
+ else\r
+ mb.pushNull("java.lang.String");\r
+\r
+ ConglomerateDescriptor cd =\r
+ innerTable.getTrulyTheBestAccessPath().getConglomerateDescriptor();\r
+ if (cd.isConstraint())\r
+ {\r
+ DataDictionary dd = innerTable.getDataDictionary();\r
+ TableDescriptor td = innerTable.getTableDescriptor();\r
+ ConstraintDescriptor constraintDesc = dd.getConstraintDescriptor(\r
+ td, cd.getUUID());\r
+ mb.push(constraintDesc.getConstraintName());\r
+ } else if (cd.isIndex()) {\r
+ mb.push(cd.getConglomerateName());\r
+ } else {\r
+ mb.pushNull("java.lang.String");\r
+ }\r
+\r
+ // Whether or not the conglomerate is the backing index for a constraint\r
+ mb.push(cd.isConstraint());\r
+\r
+ // tell it whether it's to open for update, which we should do if\r
+ // it's an update or delete statement, or if it's the target\r
+ // table of an updatable cursor.\r
+ mb.push(innerTable.forUpdate());\r
+\r
+ mb.push(colRefItem);\r
+\r
+ mb.push(indexColItem);\r
+\r
+ mb.push(lockMode);\r
+\r
+ mb.push(tableLocked);\r
+\r
+ mb.push(isolationLevel);\r
+\r
+ if (bulkFetch > 0) {\r
+ mb.push(bulkFetch);\r
+ }\r
+\r
+ /* 1 row scans (avoiding 2nd next()) are\r
+ * only meaningful for some join strategies.\r
+ * (Only an issue for outer table, which currently\r
+ * can only be nested loop, as avoidance of 2nd next\r
+ * on inner table already factored in to join node.)\r
+ */\r
+ if (validForOutermostTable())\r
+ {\r
+ mb.push(innerTable.isOneRowScan());\r
+ }\r
+\r
+ mb.push(\r
+ innerTable.getTrulyTheBestAccessPath().\r
+ getCostEstimate().rowCount());\r
+\r
+ mb.push(\r
+ innerTable.getTrulyTheBestAccessPath().\r
+ getCostEstimate().getEstimatedCost());\r
+ }\r
+\r
+ /**\r
+ * @see JoinStrategy#isHashJoin\r
+ */\r
+ public boolean isHashJoin()\r
+ {\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Can this join strategy be used on the\r
+ * outermost table of a join.\r
+ *\r
+ * @return Whether or not this join strategy\r
+ * can be used on the outermose table of a join.\r
+ */\r
+ protected boolean validForOutermostTable()\r
+ {\r
+ return false;\r
+ }\r
+}\r