KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.AggregateSortObserver
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.store.access.SortObserver;
25 import org.apache.derby.iapi.services.io.Storable;
26
27 import org.apache.derby.iapi.types.UserDataValue;
28
29 import org.apache.derby.iapi.types.CloneableObject;
30
31 import org.apache.derby.iapi.services.io.Storable;
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33
34 import org.apache.derby.iapi.error.StandardException;
35
36 import org.apache.derby.iapi.sql.execute.ExecRow;
37
38 import org.apache.derby.iapi.types.DataValueDescriptor;
39
40
41 import java.util.Vector JavaDoc;
42
43 /**
44  * This sort observer performs aggregation.
45  *
46  * @author jamie
47  */

48 public class AggregateSortObserver extends BasicSortObserver
49 {
50
51     protected GenericAggregator[] aggsToProcess;
52     protected GenericAggregator[] aggsToInitialize;
53
54     private int firstAggregatorColumn;
55
56     /**
57      * Simple constructor
58      *
59      * @param doClone If true, then rows that are retained
60      * by the sorter will be cloned. This is needed
61      * if language is reusing row wrappers.
62      *
63      * @param aggsToProcess the array of aggregates that
64      * need to be accumulated/merged in the sorter.
65      *
66      * @param aggsToInitialize the array of aggregates that
67      * need to be iniitialized as they are inserted
68      * into the sorter. This may be different than
69      * aggsToProcess in the case where some distinct
70      * aggregates are dropped in the initial pass of
71      * a two phase aggregation for scalar or vector
72      * distinct aggregation. The initialization process
73      * consists of replacing an empty UserValue with a new,
74      * initialized aggregate of the appropriate type.
75      * Note that for each row, only the first aggregate
76      * in this list is checked to see whether initialization
77      * is needed. If so, ALL aggregates are initialized;
78      * otherwise, NO aggregates are initialized.
79      *
80      * @param execRow ExecRow to use as source of clone for store.
81      */

82     public AggregateSortObserver(boolean doClone, GenericAggregator[] aggsToProcess,
83                                  GenericAggregator[] aggsToInitialize,
84                                  ExecRow execRow)
85     {
86         super(doClone, false, execRow, true);
87         this.aggsToProcess = aggsToProcess;
88         this.aggsToInitialize = aggsToInitialize;
89
90         /*
91         ** We expect aggsToInitialize and aggsToProcess to
92         ** be non null. However, if it is deemed ok for them
93         ** to be null, it shouldn't be too hard to add the
94         ** extra null checks herein.
95         */

96         if (SanityManager.DEBUG)
97         {
98             SanityManager.ASSERT(aggsToInitialize != null, "aggsToInitialize argument to AggregateSortObserver is null");
99             SanityManager.ASSERT(aggsToProcess != null, "aggsToProcess argument to AggregateSortObserver is null");
100         }
101
102         if (aggsToInitialize.length > 0)
103         {
104             firstAggregatorColumn = aggsToInitialize[0].aggregatorColumnId;
105         }
106     }
107
108     /**
109      * Called prior to inserting a distinct sort
110      * key.
111      *
112      * @param insertRow the current row that the sorter
113      * is on the verge of retaining
114      *
115      * @return the row to be inserted by the sorter. If null,
116      * then nothing is inserted by the sorter. Distinct
117      * sorts will want to return null.
118      *
119      * @exception StandardException never thrown
120      */

121     public DataValueDescriptor[] insertNonDuplicateKey(DataValueDescriptor[] insertRow)
122         throws StandardException
123     {
124         DataValueDescriptor[] returnRow =
125             super.insertNonDuplicateKey(insertRow);
126
127         /*
128         ** If we have an aggregator column that hasn't been
129         ** initialized, then initialize the entire row now.
130         */

131         if (aggsToInitialize.length > 0 &&
132             ((Storable)returnRow[firstAggregatorColumn]).isNull())
133         {
134             for (int i = 0; i < aggsToInitialize.length; i++)
135             {
136                 GenericAggregator aggregator = aggsToInitialize[i];
137                 UserDataValue wrapper = ((UserDataValue)returnRow[aggregator.aggregatorColumnId]);
138                 if (SanityManager.DEBUG)
139                 {
140                     if (!wrapper.isNull())
141                     {
142                         SanityManager.THROWASSERT("during aggregate "+
143                         "initialization, all wrappers expected to be empty; "+
144                         "however, the wrapper for the following aggregate " +
145                         "was not empty:" +aggregator+". The value stored is "+
146                         wrapper.getObject());
147                     }
148                 }
149                 wrapper.setValue(aggregator.getAggregatorInstance());
150                 aggregator.accumulate(returnRow, returnRow);
151             }
152         }
153
154         return returnRow;
155     
156     }
157     /**
158      * Called prior to inserting a duplicate sort
159      * key. We do aggregation here.
160      *
161      * @param insertRow the current row that the sorter
162      * is on the verge of retaining. It is a duplicate
163      * of existingRow.
164      *
165      * @param existingRow the row that is already in the
166      * the sorter which is a duplicate of insertRow
167      *
168      * @exception StandardException never thrown
169      */

170     public DataValueDescriptor[] insertDuplicateKey(DataValueDescriptor[] insertRow, DataValueDescriptor[] existingRow)
171             throws StandardException
172     {
173         if (aggsToProcess.length == 0)
174         {
175             return null;
176         }
177
178         /*
179         ** If the other row already has an aggregator, then
180         ** we need to merge with it. Otherwise, accumulate
181         ** it.
182         */

183         for (int i = 0; i < aggsToProcess.length; i++)
184         {
185             GenericAggregator aggregator = aggsToProcess[i];
186             if (((Storable)insertRow[aggregator.getColumnId()]).isNull())
187             {
188                 aggregator.accumulate(insertRow, existingRow);
189             }
190             else
191             {
192                 aggregator.merge(insertRow, existingRow);
193             }
194         }
195         return null;
196     }
197 }
198
Popular Tags