001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.BaseJoinStrategy
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.iapi.services.loader.GeneratedMethod;
025:
026: import org.apache.derby.iapi.services.compiler.MethodBuilder;
027:
028: import org.apache.derby.iapi.sql.compile.ExpressionClassBuilderInterface;
029: import org.apache.derby.iapi.sql.compile.JoinStrategy;
030: import org.apache.derby.iapi.sql.compile.Optimizable;
031: import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
032:
033: import org.apache.derby.iapi.sql.Activation;
034:
035: import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
036: import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
037: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
038: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
039:
040: import org.apache.derby.iapi.store.access.Qualifier;
041: import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
042: import org.apache.derby.iapi.store.access.TransactionController;
043:
044: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
045:
046: import org.apache.derby.iapi.error.StandardException;
047:
048: import org.apache.derby.iapi.services.sanity.SanityManager;
049: import org.apache.derby.iapi.reference.ClassName;
050:
051: import org.apache.derby.iapi.util.PropertyUtil;
052:
053: abstract class BaseJoinStrategy implements JoinStrategy {
054: BaseJoinStrategy() {
055: }
056:
057: /** @see JoinStrategy#bulkFetchOK */
058: public boolean bulkFetchOK() {
059: return true;
060: }
061:
062: /** @see JoinStrategy#ignoreBulkFetch */
063: public boolean ignoreBulkFetch() {
064: return false;
065: }
066:
067: /**
068: * Push the first set of common arguments for obtaining a scan ResultSet from
069: * ResultSetFactory.
070: * The first 11 arguments are common for these ResultSet getters
071: * <UL>
072: * <LI> ResultSetFactory.getBulkTableScanResultSet
073: * <LI> ResultSetFactory.getHashScanResultSet
074: * <LI> ResultSetFactory.getTableScanResultSet
075: * <LI> ResultSetFactory.getRaDependentTableScanResultSet
076: * </UL>
077: * @param tc
078: * @param mb
079: * @param innerTable
080: * @param predList
081: * @param acbi
082: * @param resultRowAllocator
083: * @throws StandardException
084: */
085: void fillInScanArgs1(TransactionController tc, MethodBuilder mb,
086: Optimizable innerTable, OptimizablePredicateList predList,
087: ExpressionClassBuilderInterface acbi,
088: MethodBuilder resultRowAllocator) throws StandardException {
089: boolean sameStartStopPosition = predList
090: .sameStartStopPosition();
091: ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
092: long conglomNumber = innerTable.getTrulyTheBestAccessPath()
093: .getConglomerateDescriptor().getConglomerateNumber();
094: StaticCompiledOpenConglomInfo scoci = tc
095: .getStaticCompiledConglomInfo(conglomNumber);
096:
097: acb.pushThisAsActivation(mb);
098: mb.push(conglomNumber);
099: mb.push(acb.addItem(scoci));
100:
101: acb.pushMethodReference(mb, resultRowAllocator);
102: mb.push(innerTable.getResultSetNumber());
103:
104: predList.generateStartKey(acb, mb, innerTable);
105: mb.push(predList.startOperator(innerTable));
106:
107: if (!sameStartStopPosition) {
108: predList.generateStopKey(acb, mb, innerTable);
109: } else {
110: mb.pushNull(ClassName.GeneratedMethod);
111: }
112:
113: mb.push(predList.stopOperator(innerTable));
114: mb.push(sameStartStopPosition);
115:
116: predList.generateQualifiers(acb, mb, innerTable, true);
117: mb.upCast(ClassName.Qualifier + "[][]");
118: }
119:
120: final void fillInScanArgs2(MethodBuilder mb,
121: Optimizable innerTable, int bulkFetch, int colRefItem,
122: int indexColItem, int lockMode, boolean tableLocked,
123: int isolationLevel) throws StandardException {
124: mb.push(innerTable.getBaseTableName());
125: //User may have supplied optimizer overrides in the sql
126: //Pass them onto execute phase so it can be shown in
127: //run time statistics.
128: if (innerTable.getProperties() != null)
129: mb.push(PropertyUtil.sortProperties(innerTable
130: .getProperties()));
131: else
132: mb.pushNull("java.lang.String");
133:
134: ConglomerateDescriptor cd = innerTable
135: .getTrulyTheBestAccessPath()
136: .getConglomerateDescriptor();
137: if (cd.isConstraint()) {
138: DataDictionary dd = innerTable.getDataDictionary();
139: TableDescriptor td = innerTable.getTableDescriptor();
140: ConstraintDescriptor constraintDesc = dd
141: .getConstraintDescriptor(td, cd.getUUID());
142: mb.push(constraintDesc.getConstraintName());
143: } else if (cd.isIndex()) {
144: mb.push(cd.getConglomerateName());
145: } else {
146: mb.pushNull("java.lang.String");
147: }
148:
149: // Whether or not the conglomerate is the backing index for a constraint
150: mb.push(cd.isConstraint());
151:
152: // tell it whether it's to open for update, which we should do if
153: // it's an update or delete statement, or if it's the target
154: // table of an updatable cursor.
155: mb.push(innerTable.forUpdate());
156:
157: mb.push(colRefItem);
158:
159: mb.push(indexColItem);
160:
161: mb.push(lockMode);
162:
163: mb.push(tableLocked);
164:
165: mb.push(isolationLevel);
166:
167: if (bulkFetch > 0) {
168: mb.push(bulkFetch);
169: }
170:
171: /* 1 row scans (avoiding 2nd next()) are
172: * only meaningful for some join strategies.
173: * (Only an issue for outer table, which currently
174: * can only be nested loop, as avoidance of 2nd next
175: * on inner table already factored in to join node.)
176: */
177: if (validForOutermostTable()) {
178: mb.push(innerTable.isOneRowScan());
179: }
180:
181: mb.push(innerTable.getTrulyTheBestAccessPath()
182: .getCostEstimate().rowCount());
183:
184: mb.push(innerTable.getTrulyTheBestAccessPath()
185: .getCostEstimate().getEstimatedCost());
186: }
187:
188: /**
189: * @see JoinStrategy#isHashJoin
190: */
191: public boolean isHashJoin() {
192: return false;
193: }
194:
195: /**
196: * Can this join strategy be used on the
197: * outermost table of a join.
198: *
199: * @return Whether or not this join strategy
200: * can be used on the outermose table of a join.
201: */
202: protected boolean validForOutermostTable() {
203: return false;
204: }
205: }
|