KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > GroupedResult


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb;
33
34 import org.hsqldb.lib.ArrayUtil;
35 import org.hsqldb.lib.HashSet;
36 import org.hsqldb.lib.Iterator;
37
38 /**
39  * This class is used for grouping select results, especially for select
40  * statements that include group by clause and nested aggregate functions.
41  * It is used by the <b>Select</b> class regardless the existence of group by
42  * clause.
43  * <p>
44  * When a group by clause is defined, a <b>ResultGroup</b> is used to hold
45  * all column values and <b>AggregatingValue</b>s for each group. When a group
46  * by clause is not defined, one <b>ResultGroup</b> is used to hold all the
47  * results.<p>
48  *
49  * All <b>ResultGroup</b>s are placed in a <b>HashSet</b>. Adding a new row
50  * will first retrieve the corresponding group from the table, based on the
51  * values in the group by columns. If a group is found, then the row
52  * associated with the group will be returned. Otherwise a new group is
53  * created with the new row, and the new row is returned.
54  * <p>
55  * The <b>Select</b> can then update the values and <b>AggregatingValue</b>s
56  * in the returned row, rather than the original row. This approach enables
57  * nested aggregate functions, such as "count(id)+2, 20-count(id),
58  * max(id)-min(id)" support.
59  *
60  * @author Tony Lai
61  * @version 1.7.2
62  * @since 1.7.2
63  * @see Expression
64  * @see Select
65  */

66
67 // fredt@users - patch 1.7.2 - mods to use new HashSet class and to separate addRow and getRow operations
68
class GroupedResult {
69
70 /** @todo fredt - initialise results on first use */
71     private Result result;
72     int groupBegin;
73     int groupEnd;
74     private final boolean isGrouped;
75     private final boolean isAggregated;
76     private HashSet groups;
77     private ResultGroup currGroup;
78
79     GroupedResult(Select select, Result.ResultMetaData meta) {
80
81         result = new Result(meta);
82         groupBegin = select.iResultLen;
83         groupEnd = groupBegin + select.iGroupLen;
84         isGrouped = groupBegin != groupEnd;
85         isAggregated = select.isAggregated;
86
87         if (isGrouped) {
88             groups = new HashSet();
89         }
90     }
91
92     Object JavaDoc[] getRow(Object JavaDoc[] row) {
93
94         if (isGrouped) {
95             ResultGroup newGroup = new ResultGroup(row);
96             ResultGroup group = (ResultGroup) groups.get(newGroup);
97
98             if (group != null) {
99                 ArrayUtil.copyArray(group.row, row, row.length);
100             }
101         } else if (isAggregated) {
102             if (currGroup != null) {
103                 ArrayUtil.copyArray(currGroup.row, row, row.length);
104             }
105         }
106
107         return row;
108     }
109
110     void addRow(Object JavaDoc[] row) {
111
112         if (isGrouped) {
113             ResultGroup newGroup = new ResultGroup(row);
114
115             currGroup = (ResultGroup) groups.get(newGroup);
116
117             if (currGroup == null) {
118                 currGroup = newGroup;
119
120                 groups.add(currGroup);
121                 result.add(row);
122             } else {
123                 System.arraycopy(row, 0, currGroup.row, 0, row.length);
124             }
125         } else if (isAggregated) {
126             if (currGroup == null) {
127                 currGroup = new ResultGroup(row);
128
129                 result.add(row);
130             } else {
131                 System.arraycopy(row, 0, currGroup.row, 0, row.length);
132             }
133         } else {
134             result.add(row);
135         }
136     }
137
138     int size() {
139         return result.getSize();
140     }
141
142     Iterator iterator() {
143         return result.iterator();
144     }
145
146     Result getResult() {
147         return result;
148     }
149
150     class ResultGroup {
151
152         Object JavaDoc[] row;
153         int hashCode;
154
155         private ResultGroup(Object JavaDoc[] row) {
156
157             this.row = row;
158             hashCode = 0;
159
160             for (int i = groupBegin; i < groupEnd; i++) {
161                 if (row[i] != null) {
162                     hashCode += row[i].hashCode();
163                 }
164             }
165         }
166
167         public int hashCode() {
168             return hashCode;
169         }
170
171         public boolean equals(Object JavaDoc obj) {
172
173             if (obj == this) {
174                 return true;
175             }
176
177             if (obj == null ||!(obj instanceof ResultGroup)) {
178                 return false;
179             }
180
181             ResultGroup group = (ResultGroup) obj;
182
183             for (int i = groupBegin; i < groupEnd; i++) {
184                 if (!equals(row[i], group.row[i])) {
185                     return false;
186                 }
187             }
188
189             return true;
190         }
191
192         private boolean equals(Object JavaDoc o1, Object JavaDoc o2) {
193             return (o1 == null) ? o2 == null
194                                 : o1.equals(o2);
195         }
196     }
197 }
198
Popular Tags