KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > expression > AggregateData


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.expression;
6
7 import java.sql.SQLException JavaDoc;
8
9 import org.h2.engine.Constants;
10 import org.h2.engine.Database;
11 import org.h2.message.Message;
12 import org.h2.util.ObjectArray;
13 import org.h2.util.ValueHashMap;
14 import org.h2.value.Value;
15 import org.h2.value.ValueBoolean;
16 import org.h2.value.ValueDouble;
17 import org.h2.value.ValueInt;
18 import org.h2.value.ValueNull;
19
20 public class AggregateData {
21     private int aggregateType;
22     private int count;
23     private ValueHashMap distinctValues;
24     private Value value;
25     private double sum, vpn;
26     private ObjectArray list;
27     
28     AggregateData(int aggregateType) {
29         this.aggregateType = aggregateType;
30     }
31     
32     void add(Database database, boolean distinct, Value v) throws SQLException JavaDoc {
33         if(aggregateType == Aggregate.SELECTIVITY) {
34             count++;
35             if(distinctValues == null) {
36                 distinctValues = new ValueHashMap(database);
37             }
38             int size = distinctValues.size();
39             if(size > Constants.SELECTIVITY_DISTINCT_COUNT) {
40                 distinctValues = new ValueHashMap(database);
41                 sum += size;
42             }
43             distinctValues.put(v, this);
44             return;
45         }
46         if(aggregateType == Aggregate.COUNT_ALL) {
47             count++;
48             return;
49         }
50         if(v == ValueNull.INSTANCE) {
51             return;
52         }
53         count++;
54         if(distinct) {
55             if(distinctValues == null) {
56                 distinctValues = new ValueHashMap(database);
57             }
58             distinctValues.put(v, this);
59             return;
60         }
61         switch(aggregateType) {
62         case Aggregate.COUNT:
63             return;
64         case Aggregate.SUM:
65         case Aggregate.AVG:
66             if(value == null) {
67                 value = v;
68             } else {
69                 value = value.add(v);
70             }
71             break;
72         case Aggregate.MIN:
73             if(value == null || database.compare(v, value) < 0) {
74                 value = v;
75             }
76             break;
77         case Aggregate.MAX:
78             if(value == null || database.compare(v, value) > 0) {
79                 value = v;
80             }
81             break;
82         case Aggregate.GROUP_CONCAT: {
83             if(list == null) {
84                 list = new ObjectArray();
85             }
86             list.add(v);
87             break;
88         }
89         case Aggregate.STDDEV_POP:
90         case Aggregate.STDDEV_SAMP:
91         case Aggregate.VAR_POP:
92         case Aggregate.VAR_SAMP: {
93             double x = v.getDouble();
94             if(count == 1) {
95                 sum = x;
96                 vpn = 0;
97             } else {
98                 double xs = sum - (x*(count-1));
99                 vpn += (xs*xs) / count / (count-1);
100                 sum += x;
101             }
102             break;
103         }
104         case Aggregate.EVERY:
105             v = v.convertTo(Value.BOOLEAN);
106             if(value == null) {
107                 value = v;
108             } else {
109                 value = ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue());
110             }
111             break;
112         case Aggregate.SOME:
113             v = v.convertTo(Value.BOOLEAN);
114             if(value == null) {
115                 value = v;
116             } else {
117                 value = ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue());
118             }
119             break;
120         default:
121             throw Message.getInternalError("type="+aggregateType);
122         }
123     }
124     
125     ObjectArray getList() {
126         return list;
127     }
128     
129     Value getValue(Database database, boolean distinct) throws SQLException JavaDoc {
130         if(distinct) {
131             count = 0;
132             groupDistinct(database);
133         }
134         Value v = null;
135         switch(aggregateType) {
136         case Aggregate.SELECTIVITY: {
137             int s = 0;
138             if(count == 0) {
139                 s = 0;
140             } else {
141                 sum += distinctValues.size();
142                 sum = (100 * sum / count);
143                 s = (int)sum;
144                 s = s <= 0 ? 1 : s > 100 ? 100 : s;
145             }
146             v = ValueInt.get(s);
147             break;
148         }
149         case Aggregate.COUNT:
150         case Aggregate.COUNT_ALL:
151             v = ValueInt.get(count);
152             break;
153         case Aggregate.SUM:
154         case Aggregate.MIN:
155         case Aggregate.MAX:
156         case Aggregate.SOME:
157         case Aggregate.EVERY:
158             v = value;
159             break;
160         case Aggregate.AVG:
161             if(value != null) {
162                 v = divide(value, count);
163             }
164             break;
165         case Aggregate.GROUP_CONCAT:
166             return null;
167         case Aggregate.STDDEV_POP: {
168             if(count < 1) {
169                 return ValueNull.INSTANCE;
170             }
171             v = ValueDouble.get(Math.sqrt(vpn / count));
172             break;
173         }
174         case Aggregate.STDDEV_SAMP: {
175             if(count < 2) {
176                 return ValueNull.INSTANCE;
177             }
178             v = ValueDouble.get(Math.sqrt(vpn / (count-1)));
179             break;
180         }
181         case Aggregate.VAR_POP: {
182             if(count < 1) {
183                 return ValueNull.INSTANCE;
184             }
185             v = ValueDouble.get(vpn / count);
186             break;
187         }
188         case Aggregate.VAR_SAMP: {
189             if(count < 2) {
190                 return ValueNull.INSTANCE;
191             }
192             v = ValueDouble.get(vpn / (count-1));
193             break;
194         }
195         default:
196             throw Message.getInternalError("type="+aggregateType);
197         }
198         return v == null ? ValueNull.INSTANCE : v;
199     }
200     
201     private Value divide(Value a, int count) throws SQLException JavaDoc {
202         if(count == 0) {
203             return ValueNull.INSTANCE;
204         }
205         int type = Value.getHigherOrder(a.getType(), Value.INT);
206         Value b = ValueInt.get(count).convertTo(type);
207         a = a.convertTo(type).divide(b);
208         return a;
209     }
210
211     private void groupDistinct(Database database) throws SQLException JavaDoc {
212         if(distinctValues == null) {
213             return;
214         }
215         if(aggregateType == Aggregate.COUNT) {
216             count = distinctValues.size();
217         } else {
218             count = 0;
219             ObjectArray l2 = distinctValues.keys();
220             for(int i=0; i<l2.size(); i++) {
221                 add(database, false, (Value)l2.get(i));
222             }
223         }
224     }
225
226 }
227
Popular Tags