KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet
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  */

48 class NestedLoopJoinResultSet extends JoinResultSet
49 {
50     private boolean returnedRowMatchingRightSide = false;
51     private ExecRow rightTemplate;
52
53     //
54
// ResultSet interface (leftover from NoPutResultSet)
55
//
56

57     /**
58      * Clear any private state that changes during scans.
59      * This includes things like the last row seen, etc.
60      * THis does not include immutable things that are
61      * typically set up in the constructor.
62      * <p>
63      * This method is called on open()/close() and reopen()
64      * <p>
65      * WARNING: this should be implemented in every sub
66      * class and it should always call super.clearScanState().
67      */

68     void clearScanState()
69     {
70         returnedRowMatchingRightSide = false;
71         super.clearScanState();
72     }
73
74     /**
75      * Return the requested values computed
76      * from the next row (if any) for which
77      * the restriction evaluates to true.
78      * <p>
79      * restriction parameters
80      * are evaluated for each row.
81      *
82      * @exception StandardException Thrown on error
83      * @exception StandardException ResultSetNotOpen thrown if closed
84      * @return the next row in the join result
85      */

86     public ExecRow getNextRowCore() throws StandardException
87     {
88         ExecRow result = null;
89         boolean haveRow = false;
90         boolean restrict = false;
91         int colInCtr;
92         int colOutCtr;
93         DataValueDescriptor restrictBoolean;
94
95         beginTime = getCurrentTimeMillis();
96         if (! isOpen)
97             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");
98
99         /* If we have a row from the left side and the right side is not open,
100          * then we get an error on the previous next, either on the next on
101          * the left or the open on the right. So, we do a next on the left
102          * and then open the right if that succeeds.
103          */

104         if (! isRightOpen && leftRow != null)
105         {
106             leftRow = leftResultSet.getNextRowCore();
107             if (leftRow == null)
108             {
109                 closeRight();
110             }
111             else
112             {
113                 rowsSeenLeft++;
114                 openRight();
115             }
116         }
117
118         while (leftRow != null && !haveRow)
119         {
120             if (oneRowRightSide && returnedRowMatchingRightSide)
121             {
122                 rightRow = null;
123                 returnedRowMatchingRightSide = false;
124             }
125             else
126             {
127                 rightRow = rightResultSet.getNextRowCore();
128
129                 /* If this is a NOT EXISTS join, we just need to reverse the logic
130                  * of EXISTS join. To make the implementation simple, we create a
131                  * right side template, which is never really needed. (beetle 5173)
132                  */

133                 if (notExistsRightSide)
134                 {
135                     if (rightRow == null) //none satisfied
136
rightRow = rightTemplate; //then we are
137
else
138                         rightRow = null;
139                 }
140
141                 returnedRowMatchingRightSide = (rightRow != null);
142             }
143
144             if (rightRow == null)
145             {
146                 /* Current scan on right is exhausted. Need to close old scan
147                  * and open new scan with new "parameters". openRight()
148                  * will reopen if already open.
149                  */

150                 leftRow = leftResultSet.getNextRowCore();
151                 if (leftRow == null)
152                 {
153                     closeRight();
154                 }
155                 else
156                 {
157                     rowsSeenLeft++;
158                     openRight();
159                 }
160             }
161             else
162             {
163                 rowsSeenRight++;
164
165                 if (restriction != null)
166                 {
167                     restrictBoolean =
168                         (DataValueDescriptor) restriction.invoke(activation);
169
170                     // if the result is null, we make it false --
171
// so the row won't be returned.
172
restrict = (! restrictBoolean.isNull()) &&
173                                     restrictBoolean.getBoolean();
174
175                     if (! restrict)
176                     {
177                         /* Update the run time statistics */
178                         rowsFiltered++;
179                         continue;
180                     }
181                 }
182
183                 /* Merge the rows, doing just in time allocation for mergedRow.
184                  * (By convention, left Row is to left of right Row.)
185                  */

186                 if (mergedRow == null)
187                 {
188                     mergedRow = getExecutionFactory().getValueRow(leftNumCols + rightNumCols);
189                 }
190
191                 for (colInCtr = 1, colOutCtr = 1; colInCtr <= leftNumCols;
192                      colInCtr++, colOutCtr++)
193                     {
194                          mergedRow.setColumn(colOutCtr,
195                                              leftRow.getColumn(colInCtr));
196                     }
197                 if (! notExistsRightSide)
198                 {
199                     for (colInCtr = 1; colInCtr <= rightNumCols;
200                          colInCtr++, colOutCtr++)
201                     {
202                          mergedRow.setColumn(colOutCtr,
203                                              rightRow.getColumn(colInCtr));
204                     }
205                 }
206
207                 setCurrentRow(mergedRow);
208                 haveRow = true;
209             }
210         }
211
212         /* Do we have a row to return? */
213         if (haveRow)
214         {
215             result = mergedRow;
216             rowsReturned++;
217         }
218         else
219         {
220             clearCurrentRow();
221         }
222
223         nextTime += getElapsedMillis(beginTime);
224         return result;
225     }
226
227     /**
228      * If the result set has been opened,
229      * close the open scan.
230      *
231      * @exception StandardException thrown on error
232      */

233     public void close() throws StandardException
234     {
235         if ( isOpen )
236         {
237             beginTime = getCurrentTimeMillis();
238
239             // we don't want to keep around a pointer to the
240
// row ... so it can be thrown away.
241
// REVISIT: does this need to be in a finally
242
// block, to ensure that it is executed?
243
clearCurrentRow();
244
245             super.close();
246             returnedRowMatchingRightSide = false;
247             closeTime += getElapsedMillis(beginTime);
248         }
249
250     }
251
252
253     /**
254      * Return the total amount of time spent in this ResultSet
255      *
256      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
257      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
258      *
259      * @return long The total amount of time spent (in milliseconds).
260      */

261     public long getTimeSpent(int type)
262     {
263         long totTime = constructorTime + openTime + nextTime + closeTime;
264
265         if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY)
266         {
267             return totTime - leftResultSet.getTimeSpent(ENTIRE_RESULTSET_TREE) -
268                               rightResultSet.getTimeSpent(ENTIRE_RESULTSET_TREE);
269         }
270         else
271         {
272             return totTime;
273         }
274     }
275
276     /*
277      * class interface
278      *
279      */

280     NestedLoopJoinResultSet(NoPutResultSet leftResultSet,
281                                    int leftNumCols,
282                                    NoPutResultSet rightResultSet,
283                                    int rightNumCols,
284                                    Activation activation,
285                                    GeneratedMethod restriction,
286                                    int resultSetNumber,
287                                    boolean oneRowRightSide,
288                                    boolean notExistsRightSide,
289                                    double optimizerEstimatedRowCount,
290                                    double optimizerEstimatedCost,
291                                    String JavaDoc userSuppliedOptimizerOverrides)
292     {
293         super(leftResultSet, leftNumCols, rightResultSet, rightNumCols,
294               activation, restriction, resultSetNumber,
295               oneRowRightSide, notExistsRightSide, optimizerEstimatedRowCount,
296               optimizerEstimatedCost, userSuppliedOptimizerOverrides);
297         if (notExistsRightSide)
298             rightTemplate = getExecutionFactory().getValueRow(rightNumCols);
299     }
300 }
301
Popular Tags