KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.GenericAggregator
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.types.NumberDataValue;
25 import org.apache.derby.iapi.types.UserDataValue;
26
27 import org.apache.derby.iapi.reference.SQLState;
28
29 import org.apache.derby.iapi.sql.execute.ExecRow;
30 import org.apache.derby.iapi.store.access.TransactionController;
31 import org.apache.derby.iapi.services.io.Storable;
32
33 import org.apache.derby.iapi.types.DataValueDescriptor;
34 import org.apache.derby.iapi.types.DataValueDescriptor;
35 import org.apache.derby.iapi.sql.ResultDescription;
36
37 import org.apache.derby.iapi.services.sanity.SanityManager;
38 import org.apache.derby.iapi.services.loader.ClassFactory;
39
40 import org.apache.derby.iapi.sql.execute.ExecAggregator;
41 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
42 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
43
44 import org.apache.derby.iapi.error.StandardException;
45 import org.apache.derby.iapi.jdbc.ConnectionContext;
46 import java.sql.Statement JavaDoc;
47 /**
48  * Adaptor that sits between execution layer and aggregates.
49  *
50  * @author jamie
51  */

52 class GenericAggregator
53 {
54     AggregatorInfo aggInfo;
55     int aggregatorColumnId;
56     private int inputColumnId;
57     private int resultColumnId;
58     private ResultDescription inputColumnResultDescription;
59
60     private ExecRow[] rowArray;
61     private TemporaryRowHolderResultSet execResultSet;
62     private final ClassFactory cf;
63
64     /*
65     ** We cache an aggregator to speed up
66     ** the instantiation of lots of aggregators.
67     */

68     private ExecAggregator cachedAggregator;
69
70     /**
71      * Constructor:
72      *
73      * @param aggInfo information about the user aggregate
74      * @param cf the class factory.
75      */

76     GenericAggregator
77     (
78         AggregatorInfo aggInfo,
79         ClassFactory cf
80     )
81     {
82         this.aggInfo = aggInfo;
83         aggregatorColumnId = aggInfo.getAggregatorColNum();
84         inputColumnId = aggInfo.getInputColNum();
85         resultColumnId = aggInfo.getOutputColNum();
86         int[] colArray = new int[1];
87         inputColumnResultDescription = aggInfo.getResultDescription();
88         this.cf = cf;
89     }
90
91
92     /**
93      * Initialize the aggregator
94      *
95      * @param row the row with the aggregator to be initialized
96      *
97      * @exception StandardException on error
98      */

99     void initialize(ExecRow row)
100         throws StandardException
101     {
102         if (SanityManager.DEBUG)
103         {
104             SanityManager.ASSERT(row != null, "row is null");
105         }
106
107         UserDataValue aggregatorColumn = (UserDataValue) row.getColumn(aggregatorColumnId + 1);
108
109         ExecAggregator ua = (ExecAggregator) aggregatorColumn.getObject();
110         if (ua == null)
111         {
112             ua = getAggregatorInstance();
113             aggregatorColumn.setValue(ua);
114         }
115     }
116
117     /**
118      * Accumulate the aggregate results. This is the
119      * guts of the aggregation. We will call the user aggregate
120      * on itself to do the aggregation.
121      *
122      * @param inputRow the row with the input colum
123      * @param accumulateRow the row with the aggregator
124      *
125      * @exception StandardException on error
126      */

127     void accumulate(ExecRow inputRow,
128                             ExecRow accumulateRow)
129         throws StandardException
130     {
131         DataValueDescriptor inputColumn = null;
132
133         if (SanityManager.DEBUG)
134         {
135             SanityManager.ASSERT((inputRow != null) && (accumulateRow != null), "bad accumulate call");
136         }
137
138         DataValueDescriptor aggregatorColumn = accumulateRow.getColumn(aggregatorColumnId + 1);
139
140         inputColumn = inputRow.getColumn(inputColumnId + 1);
141
142         accumulate(inputColumn, aggregatorColumn);
143     }
144
145     /**
146      * Accumulate the aggregate results. This is the
147      * guts of the aggregation. We will call the user aggregate
148      * on itself to do the aggregation.
149      *
150      * @param inputRow the row with the input colum
151      * @param accumulateRow the row with the aggregator
152      *
153      * @exception StandardException on error
154      */

155     void accumulate(Object JavaDoc[] inputRow,
156                             Object JavaDoc[] accumulateRow)
157         throws StandardException
158     {
159         DataValueDescriptor inputColumn = null;
160
161         if (SanityManager.DEBUG)
162         {
163             SanityManager.ASSERT((inputRow != null) && (accumulateRow != null), "bad accumulate call");
164         }
165
166         DataValueDescriptor aggregatorColumn = (DataValueDescriptor) accumulateRow[aggregatorColumnId];
167         inputColumn = (DataValueDescriptor) inputRow[inputColumnId];
168
169         accumulate(inputColumn, aggregatorColumn);
170     }
171
172     /**
173      * Accumulate the aggregate results. This is the
174      * guts of the aggregation. We will call the user aggregate
175      * on itself to do the aggregation.
176      *
177      * @param inputColumn
178      * @param aggregatorColumn
179      *
180      * @exception StandardException on error
181      */

182     void accumulate(DataValueDescriptor inputColumn,
183                             DataValueDescriptor aggregatorColumn)
184         throws StandardException
185     {
186         ExecAggregator ua;
187
188         if (SanityManager.DEBUG)
189         {
190             /*
191             ** Just to be on the safe side, confirm that we actually
192             ** have a Aggregator in this column.
193             */

194             if (!(aggregatorColumn instanceof UserDataValue))
195             {
196                 SanityManager.THROWASSERT("accumlator column is not a UserDataValue as "+
197                     "expected, it is a "+aggregatorColumn.getClass().getName());
198             }
199         }
200         ua = (ExecAggregator) aggregatorColumn.getObject();
201
202         /*
203         ** If we don't have an aggregator, then we have to
204         ** create one now. This happens when the input result
205         ** set is null.
206         */

207         if (ua == null)
208         {
209             ua = getAggregatorInstance();
210         }
211     
212         ua.accumulate(inputColumn, this);
213     }
214
215     /**
216      * Merge the aggregate results. This is the
217      * guts of the aggregation. We will call the user aggregate
218      * on itself to do the aggregation.
219      *
220      * @param inputRow the row with the input colum
221      * @param mergeRow the row with the aggregator
222      *
223      * @exception StandardException on error
224      */

225     void merge(ExecRow inputRow,
226                             ExecRow mergeRow)
227         throws StandardException
228     {
229
230         DataValueDescriptor mergeColumn = mergeRow.getColumn(aggregatorColumnId + 1);
231         DataValueDescriptor inputColumn = inputRow.getColumn(aggregatorColumnId + 1);
232
233         merge(inputColumn, mergeColumn);
234     }
235
236     /**
237      * Merge the aggregate results. This is the
238      * guts of the aggregation. We will call the user aggregate
239      * on itself to do the aggregation.
240      *
241      * @param inputRow the row with the input colum
242      * @param mergeRow the row with the aggregator
243      *
244      * @exception StandardException on error
245      */

246     void merge(Object JavaDoc[] inputRow,
247                             Object JavaDoc[] mergeRow)
248         throws StandardException
249     {
250         DataValueDescriptor mergeColumn = (DataValueDescriptor) mergeRow[aggregatorColumnId];
251         DataValueDescriptor inputColumn = (DataValueDescriptor) inputRow[aggregatorColumnId];
252
253         merge(inputColumn, mergeColumn);
254     }
255
256     /**
257      * Get the results of the aggregation and put it
258      * in the result column.
259      *
260      * @param row the row with the result and the aggregator
261      *
262      * @exception StandardException on error
263      */

264     boolean finish(ExecRow row)
265         throws StandardException
266     {
267         DataValueDescriptor outputColumn = row.getColumn(resultColumnId + 1);
268         DataValueDescriptor aggregatorColumn = row.getColumn(aggregatorColumnId + 1);
269         /*
270         ** Just to be on the safe side, confirm that we actually
271         ** have a Aggregator in aggregatorColumn.
272         */

273         if (SanityManager.DEBUG)
274         {
275             SanityManager.ASSERT(aggregatorColumn != null, "aggregatorColumn is null");
276             SanityManager.ASSERT(outputColumn != null, "otuputColumn is null");
277             SanityManager.ASSERT(aggregatorColumn instanceof UserDataValue,
278                 "accumlator column is not a UserDataValue as expected");
279         }
280
281         ExecAggregator ua = (ExecAggregator) aggregatorColumn.getObject();
282
283         /*
284         ** If we don't have an aggregator, then we have to
285         ** create one now. This happens when the input result
286         ** set is null.
287         */

288         if (ua == null)
289         {
290             ua = getAggregatorInstance();
291         }
292
293         /*
294         **
295         ** We are going to copy
296         ** then entire DataValueDescriptor into the result column.
297         ** We could call setValue(result.setObject()), but we
298         ** might loose state (e.g. SQLBit.getObject() returns a
299         ** byte[] which looses the precision of the bit.
300         **
301         */

302         
303         DataValueDescriptor result = ua.getResult();
304         if (result == null)
305             outputColumn.setToNull();
306         else
307             outputColumn.setValue(result);
308
309         return ua.didEliminateNulls();
310     }
311
312     /**
313      * Get a new instance of the aggregator and initialize it.
314      *
315      * @return an exec aggregator
316      *
317      * @exception StandardException on error
318      */

319     ExecAggregator getAggregatorInstance()
320         throws StandardException
321     {
322         ExecAggregator aggregatorInstance;
323         if (cachedAggregator == null)
324         {
325             try
326             {
327                 Class JavaDoc aggregatorClass = cf.loadApplicationClass(aggInfo.getAggregatorClassName());
328                 Object JavaDoc agg = aggregatorClass.newInstance();
329                 aggregatorInstance = (ExecAggregator)agg;
330                 cachedAggregator = aggregatorInstance;
331                 aggregatorInstance.setup(aggInfo.getAggregateName());
332
333             } catch (Exception JavaDoc e)
334             {
335                 throw StandardException.unexpectedUserException(e);
336             }
337         }
338         else
339         {
340             aggregatorInstance = cachedAggregator.newAggregator();
341         }
342
343
344         return aggregatorInstance;
345     }
346             
347     /////////////////////////////////////////////////////////////
348
//
349
/////////////////////////////////////////////////////////////
350

351     /**
352      * Return the column id that is being aggregated
353      */

354     int getColumnId()
355     {
356         // Every sort has to have at least one column.
357
return aggregatorColumnId;
358     }
359
360
361     /**
362      * Merge two partial aggregations. This is how the
363      * sorter merges partial aggregates.
364      *
365      * @exception StandardException on error
366      */

367     void merge(Storable aggregatorColumnIn,
368                         Storable aggregatorColumnOut)
369         throws StandardException
370     {
371         ExecAggregator uaIn;
372         ExecAggregator uaOut;
373
374         if (SanityManager.DEBUG)
375         {
376             /*
377             ** Just to be on the safe side, confirm that we actually
378             ** have a Aggregator in this column.
379             */

380             if (!(aggregatorColumnIn instanceof UserDataValue))
381             {
382                 SanityManager.THROWASSERT("aggregatorColumnOut column is not "+
383                     "a UserAggreator as expected, "+
384                     "it is a "+aggregatorColumnIn.getClass().getName());
385             }
386             if (!(aggregatorColumnOut instanceof UserDataValue))
387             {
388                 SanityManager.THROWASSERT("aggregatorColumnIn column is not"+
389                     " a UserAggreator as expected, "+
390                     "it is a "+aggregatorColumnOut.getClass().getName());
391             }
392         }
393         uaIn = (ExecAggregator)(((UserDataValue) aggregatorColumnIn).getObject());
394         uaOut = (ExecAggregator)(((UserDataValue) aggregatorColumnOut).getObject());
395
396         uaOut.merge(uaIn);
397     }
398
399     //////////////////////////////////////////////////////
400
//
401
// MISC
402
//
403
//////////////////////////////////////////////////////
404
AggregatorInfo getAggregatorInfo()
405     {
406         return aggInfo;
407     }
408
409
410 }
411
Popular Tags