KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > execute > NestedLoopLeftOuterJoinResultSet


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.NestedLoopLeftOuterJoinResultSet
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.execute;
23
24 import org.apache.derby.iapi.services.monitor.Monitor;
25
26 import org.apache.derby.iapi.services.sanity.SanityManager;
27
28 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
29 import org.apache.derby.iapi.services.stream.InfoStreams;
30
31 import org.apache.derby.iapi.error.StandardException;
32 import org.apache.derby.iapi.sql.Activation;
33 import org.apache.derby.iapi.sql.ResultSet;
34 import org.apache.derby.iapi.types.DataValueDescriptor;
35 import org.apache.derby.iapi.reference.SQLState;
36
37 import org.apache.derby.iapi.sql.execute.ExecRow;
38 import org.apache.derby.iapi.sql.execute.ExecutionContext;
39 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
40
41 import org.apache.derby.iapi.services.loader.GeneratedMethod;
42
43
44 /**
45  * Takes 2 NoPutResultSets and a join filter and returns
46  * the join's rows satisfying the filter as a result set
47  * plus the rows from the left joined with a null row from
48  * the right when there is no matching row in the right
49  * result set.
50  */

51 class NestedLoopLeftOuterJoinResultSet extends NestedLoopJoinResultSet
52 {
53     protected GeneratedMethod emptyRowFun;
54     /* Was this originally a right outer join? */
55     private boolean wasRightOuterJoin;
56
57     /* Have we found a matching row from the right yet? */
58     private boolean matchRight = false;
59     private boolean returnedEmptyRight = false;
60     private ExecRow rightEmptyRow = null;
61
62     public int emptyRightRowsReturned = 0;
63
64     //
65
// ResultSet interface (leftover from NoPutResultSet)
66
//
67

68     /**
69      * Return the requested values computed
70      * from the next row (if any) for which
71      * the restriction evaluates to true.
72      * <p>
73      * restriction parameters
74      * are evaluated for each row.
75      *
76      * @exception StandardException Thrown on error
77      * @exception StandardException ResultSetNotOpen thrown if closed
78      * @return the next row in the join result
79      */

80     public ExecRow getNextRowCore() throws StandardException
81     {
82         ExecRow result = null;
83         boolean haveRow = false;
84         boolean restrict = false;
85         DataValueDescriptor restrictBoolean;
86
87         beginTime = getCurrentTimeMillis();
88         if (! isOpen)
89             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");
90
91         /* Close right and advance left if we found no match
92          * on right on last next().
93          */

94         if (returnedEmptyRight)
95         {
96             /* Current scan on right is exhausted. Need to close old scan
97              * and open new scan with new "parameters". openRight will
98              * reopen the scan.
99              */

100             leftRow = leftResultSet.getNextRowCore();
101             if (leftRow == null)
102             {
103                 closeRight();
104             }
105             else
106             {
107                 rowsSeenLeft++;
108                 openRight();
109             }
110             returnedEmptyRight = false;
111         }
112
113         while (leftRow != null && !haveRow)
114         {
115             rightRow = rightResultSet.getNextRowCore();
116
117             if (rightRow == null)
118             {
119                 /* If we haven't found a match on the right, then
120                  * we join the left with a row of nulls from the
121                  * right.
122                  */

123                 if (! matchRight)
124                 {
125                     haveRow = true;
126                     returnedEmptyRight = true;
127                     if (rightEmptyRow == null)
128                     {
129                         rightEmptyRow = (ExecRow) emptyRowFun.invoke(activation);
130                     }
131
132                     getMergedRow(leftRow, rightEmptyRow);
133                     emptyRightRowsReturned++;
134                     continue;
135                 }
136
137                 /* Current scan on right is exhausted. Need to close old scan
138                  * and open new scan with new "parameters". openRight()
139                  * will reopen the scan.
140                  */

141                 matchRight = false;
142                 leftRow = leftResultSet.getNextRowCore();
143                 if (leftRow == null)
144                 {
145                     closeRight();
146                 }
147                 else
148                 {
149                     rowsSeenLeft++;
150                     openRight();
151                 }
152             }
153             else
154             {
155                 rowsSeenRight++;
156
157                 if (restriction != null)
158                 {
159                     restrictBoolean =
160                         (DataValueDescriptor) restriction.invoke(activation);
161
162                     // if the result is null, we make it false --
163
// so the row won't be returned.
164
restrict = (! restrictBoolean.isNull()) &&
165                                     restrictBoolean.getBoolean();
166
167                     if (! restrict)
168                     {
169                         /* Update the run time statistics */
170                         rowsFiltered++;
171                         continue;
172                     }
173                 }
174
175                 matchRight = true;
176
177                 getMergedRow(leftRow, rightRow);
178                 haveRow = true;
179             }
180         }
181
182         /* Do we have a row to return? */
183         if (haveRow)
184         {
185             result = mergedRow;
186             setCurrentRow(mergedRow);
187             rowsReturned++;
188         }
189         else
190         {
191             clearCurrentRow();
192         }
193
194         nextTime += getElapsedMillis(beginTime);
195         return result;
196     }
197
198     protected void getMergedRow(ExecRow leftRow, ExecRow rightRow)
199             throws StandardException
200     {
201         int colInCtr;
202         int colOutCtr;
203         int leftNumCols;
204         int rightNumCols;
205
206         /* Reverse left and right for return of row if this was originally
207          * a right outer join. (Result columns ordered according to
208          * original query.)
209          */

210         if (wasRightOuterJoin)
211         {
212             ExecRow tmp;
213
214             tmp = leftRow;
215             leftRow = rightRow;
216             rightRow = tmp;
217             leftNumCols = this.rightNumCols;
218             rightNumCols = this.leftNumCols;
219         }
220         else
221         {
222             leftNumCols = this.leftNumCols;
223             rightNumCols = this.rightNumCols;
224         }
225
226         /* Merge the rows, doing just in time allocation for mergedRow.
227          * (By convention, left Row is to left of right Row.)
228          */

229         if (mergedRow == null)
230         {
231             mergedRow = getExecutionFactory().getValueRow(leftNumCols + rightNumCols);
232         }
233
234         for (colInCtr = 1, colOutCtr = 1; colInCtr <= leftNumCols;
235              colInCtr++, colOutCtr++)
236         {
237              mergedRow.setColumn(colOutCtr,
238                                  leftRow.getColumn(colInCtr));
239         }
240         for (colInCtr = 1; colInCtr <= rightNumCols;
241              colInCtr++, colOutCtr++)
242         {
243              mergedRow.setColumn(colOutCtr,
244                                  rightRow.getColumn(colInCtr));
245         }
246     }
247
248     /**
249      * Clear any private state that changes during scans.
250      * This includes things like the last row seen, etc.
251      * THis does not include immutable things that are
252      * typically set up in the constructor.
253      * <p>
254      * This method is called on open()/close() and reopen()
255      * <p>
256      * WARNING: this should be implemented in every sub
257      * class and it should always call super.clearScanState().
258      */

259     void clearScanState()
260     {
261         matchRight = false;
262         returnedEmptyRight = false;
263         rightEmptyRow = null;
264         emptyRightRowsReturned = 0;
265         super.clearScanState();
266     }
267
268
269     /*
270      * class interface
271      *
272      */

273     NestedLoopLeftOuterJoinResultSet(
274                         NoPutResultSet leftResultSet,
275                         int leftNumCols,
276                         NoPutResultSet rightResultSet,
277                         int rightNumCols,
278                         Activation activation,
279                         GeneratedMethod restriction,
280                         int resultSetNumber,
281                         GeneratedMethod emptyRowFun,
282                         boolean wasRightOuterJoin,
283                         boolean oneRowRightSide,
284                         boolean notExistsRightSide,
285                         double optimizerEstimatedRowCount,
286                         double optimizerEstimatedCost,
287                         String JavaDoc userSuppliedOptimizerOverrides)
288     {
289         super(leftResultSet, leftNumCols, rightResultSet, rightNumCols,
290               activation, restriction, resultSetNumber,
291               oneRowRightSide, notExistsRightSide,
292               optimizerEstimatedRowCount, optimizerEstimatedCost,
293               userSuppliedOptimizerOverrides);
294         this.emptyRowFun = emptyRowFun;
295         this.wasRightOuterJoin = wasRightOuterJoin;
296     }
297 }
298
Popular Tags