KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.MergeJoinResultSet
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.NoPutResultSet;
39
40 import org.apache.derby.iapi.services.loader.GeneratedMethod;
41
42 /////////////////////////////////////////////
43
// WARNING: THIS HAS NOT BEEN TESTED (OR USED)
44
// YET, SO USE AT YOUR OWN RISK
45
/////////////////////////////////////////////
46

47 /**
48  * Merge two result sets. The left result set (the outer
49  * result set) MUST be unique for this to work correctly.
50  *
51  */

52 class MergeJoinResultSet extends JoinResultSet
53 {
54     private static final int GREATER_THAN = 1;
55     private static final int EQUAL = 0;
56     private static final int LESS_THAN = -1;
57
58     private GeneratedMethod leftGreaterThanRight;
59
60     /**
61      * Create a MergeJoinResultSet
62      *
63      * @param leftResultSet the left (outer) result set
64      * @param leftNumCols columns in left row
65      * @param rightResultSet the right (outer) result set
66      * @param rightNumCols columns in right row
67      * @param activation activation
68      * @param leftGreaterThanRight a generated method that is used to
69      * ascertain whether the row from the left result set is
70      * greater than the row from the right result set. returns
71      * 1,0,or -1 to indicate greater than, equal, or less than,
72      * respectively
73      * @param restriction generated method for additional qualification
74      * @param resultSetNumber the result set number
75      * @param oneRowRightSide ignored
76      * @param optimizerEstimatedRowCount self-explanatory
77      * @param optimizerEstimatedCost self-explanatory
78      */

79     MergeJoinResultSet(NoPutResultSet leftResultSet,
80                                    int leftNumCols,
81                                    NoPutResultSet rightResultSet,
82                                    int rightNumCols,
83                                    Activation activation,
84                                    GeneratedMethod leftGreaterThanRight,
85                                    GeneratedMethod restriction,
86                                    int resultSetNumber,
87                                    boolean oneRowRightSide,
88                                    boolean notExistsRightSide,
89                                    double optimizerEstimatedRowCount,
90                                    double optimizerEstimatedCost)
91     {
92         super(leftResultSet, leftNumCols, rightResultSet, rightNumCols,
93               activation, restriction, resultSetNumber,
94               oneRowRightSide, notExistsRightSide, optimizerEstimatedRowCount,
95               optimizerEstimatedCost, null);
96
97         this.leftGreaterThanRight = leftGreaterThanRight;
98     }
99
100     //////////////////////////////////////////////////////////////////////
101
//
102
// ResultSet interface (leftover from NoPutResultSet)
103
//
104
//////////////////////////////////////////////////////////////////////
105
/**
106      * Return the requested values computed
107      * from the next row (if any) for which
108      * the restriction evaluates to true.
109      * <p>
110      * restriction parameters
111      * are evaluated for each row.
112      *
113      * @exception StandardException Thrown on error
114      * @exception StandardException ResultSetNotOpen thrown if closed
115      * @return the next row in the join result
116      */

117     public ExecRow getNextRowCore() throws StandardException
118     {
119         beginTime = getCurrentTimeMillis();
120         if (! isOpen)
121             throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");
122
123         if (!isRightOpen)
124         {
125             openRight();
126         }
127
128         int compareResult;
129
130         /*
131         ** For each row in the outer table
132         */

133         while (leftRow != null)
134         {
135             /*
136             ** If outer > inner, then go to the
137             ** next row in the inner table
138             */

139             while ((compareResult = ((Integer JavaDoc)leftGreaterThanRight.invoke(activation)).intValue())
140                         == GREATER_THAN)
141             {
142                 rightRow = rightResultSet.getNextRowCore();
143                 rowsSeenRight++;
144
145                 /*
146                 ** If there are no more rows in the right
147                 ** result set, then done.
148                 */

149                 if (rightRow == null)
150                 {
151                     clearCurrentRow();
152                     return (ExecRow)null;
153                 }
154             }
155
156             /*
157             ** If they match and the restriction passes,
158             ** then return the row.
159             */

160             if ((compareResult == EQUAL) && restrictionIsTrue())
161             {
162                 ExecRow returnRow = getReturnRow(leftRow, rightRow);
163
164                 /*
165                 ** Move the left scan up one for the next
166                 ** getNextRowCore() call.
167                 */

168                 leftRow = leftResultSet.getNextRowCore();
169
170                 return returnRow;
171             }
172
173             /*
174             ** Next row left
175             */

176             leftRow = leftResultSet.getNextRowCore();
177             rowsSeenLeft++;
178         }
179
180         clearCurrentRow();
181         return (ExecRow)null;
182     }
183
184     /**
185      * If the result set has been opened,
186      * close the open scan.
187      *
188      * @exception StandardException thrown on error
189      */

190     public void close() throws StandardException
191     {
192         beginTime = getCurrentTimeMillis();
193         if (SanityManager.DEBUG)
194             SanityManager.ASSERT( isOpen, "MergeJoinResultSet not open");
195
196         if ( isOpen )
197         {
198
199             // we don't want to keep around a pointer to the
200
// row ... so it can be thrown away.
201
// REVISIT: does this need to be in a finally
202
// block, to ensure that it is executed?
203
clearCurrentRow();
204
205             super.close();
206         }
207
208         closeTime += getElapsedMillis(beginTime);
209     }
210
211     /**
212      * Return the total amount of time spent in this ResultSet
213      *
214      * @param type CURRENT_RESULTSET_ONLY - time spent only in this ResultSet
215      * ENTIRE_RESULTSET_TREE - time spent in this ResultSet and below.
216      *
217      * @return long The total amount of time spent (in milliseconds).
218      */

219     public long getTimeSpent(int type)
220     {
221         long totTime = constructorTime + openTime + nextTime + closeTime;
222
223         if (type == NoPutResultSet.CURRENT_RESULTSET_ONLY)
224         {
225             return totTime - leftResultSet.getTimeSpent(ENTIRE_RESULTSET_TREE) -
226                               rightResultSet.getTimeSpent(ENTIRE_RESULTSET_TREE);
227         }
228         else
229         {
230             return totTime;
231         }
232     }
233
234
235     //////////////////////////////////////////////////////////////////
236
//
237
// SERVILE METHODS
238
//
239
//////////////////////////////////////////////////////////////////
240
private ExecRow getReturnRow(ExecRow leftRow, ExecRow rightRow)
241         throws StandardException
242     {
243         int colInCtr;
244         int colOutCtr;
245
246         /* Merge the rows, doing just in time allocation for mergedRow.
247          * (By convention, left Row is to left of right Row.)
248          */

249         if (mergedRow == null)
250         {
251             mergedRow = getExecutionFactory().getValueRow(leftNumCols + rightNumCols);
252         }
253
254         for (colInCtr = 1, colOutCtr = 1; colInCtr <= leftNumCols;
255              colInCtr++, colOutCtr++)
256         {
257                  mergedRow.setColumn(colOutCtr,
258                                      leftRow.getColumn(colInCtr));
259         }
260
261         for (colInCtr = 1; colInCtr <= rightNumCols;
262              colInCtr++, colOutCtr++)
263         {
264                  mergedRow.setColumn(colOutCtr,
265                                      rightRow.getColumn(colInCtr));
266         }
267
268         setCurrentRow(mergedRow);
269         rowsReturned++;
270         nextTime += getElapsedMillis(beginTime);
271
272         return mergedRow;
273     }
274
275     private boolean restrictionIsTrue()
276         throws StandardException
277     {
278         if (restriction != null)
279         {
280             DataValueDescriptor restrictBoolean =
281                 (DataValueDescriptor) restriction.invoke(activation);
282
283             /*
284             ** if the result is null, we make it false --
285             ** so the row won't be returned.
286             */

287             if (restrictBoolean.isNull() ||
288                     !restrictBoolean.getBoolean())
289             {
290                 /* Update the run time statistics */
291                 rowsFiltered++;
292                 return false;
293             }
294         }
295         return true;
296     }
297
298 }
299
Popular Tags