1 30 31 32 package org.hsqldb; 33 34 import java.lang.Math ; 35 import java.math.BigDecimal ; 36 import java.math.BigInteger ; 37 38 import org.hsqldb.lib.HashSet; 39 import org.hsqldb.store.ValuePool; 40 41 52 public class SetFunction { 53 54 private HashSet distinctValues; 55 private boolean isDistinct; 56 57 private int setType; 59 private int type; 60 61 private int count; 63 64 private boolean hasNull; 66 private boolean every = true; 67 private boolean some = false; 68 private long currentLong; 69 private double currentDouble; 70 private BigDecimal currentBigDecimal; 71 private Object currentValue; 72 73 SetFunction(int setType, int type, boolean isDistinct) { 74 75 this.setType = setType; 76 this.type = type; 77 78 if (isDistinct) { 79 this.isDistinct = true; 80 distinctValues = new HashSet(); 81 } 82 83 if (setType == Expression.VAR_SAMP 84 || setType == Expression.STDDEV_SAMP) { 85 this.sample = true; 86 } 87 } 88 89 void add(Session session, Object item) throws HsqlException { 90 91 if (item == null) { 92 hasNull = true; 93 94 return; 95 } 96 97 if (isDistinct &&!distinctValues.add(item)) { 98 return; 99 } 100 101 count++; 102 103 switch (setType) { 104 105 case Expression.COUNT : 106 return; 107 108 case Expression.AVG : 109 case Expression.SUM : { 110 switch (type) { 111 112 case Types.TINYINT : 113 case Types.SMALLINT : 114 case Types.INTEGER : 115 currentLong += ((Number ) item).intValue(); 116 117 return; 118 119 case Types.BIGINT : 120 addLong(((Number ) item).longValue()); 121 122 return; 123 124 case Types.REAL : 125 case Types.FLOAT : 126 case Types.DOUBLE : 127 currentDouble += ((Number ) item).doubleValue(); 128 129 return; 130 131 case Types.NUMERIC : 132 case Types.DECIMAL : 133 if (currentBigDecimal == null) { 134 currentBigDecimal = (BigDecimal ) item; 135 } else { 136 currentBigDecimal = 137 currentBigDecimal.add((BigDecimal ) item); 138 } 139 140 return; 141 142 default : 143 throw Trace.error(Trace.SUM_OF_NON_NUMERIC); 144 } 145 } 146 case Expression.MIN : { 147 if (currentValue == null) { 148 currentValue = item; 149 150 return; 151 } 152 153 if (Column.compare( 154 session.database.collation, currentValue, item, 155 type) > 0) { 156 currentValue = item; 157 } 158 159 return; 160 } 161 case Expression.MAX : { 162 if (currentValue == null) { 163 currentValue = item; 164 165 return; 166 } 167 168 if (Column.compare( 169 session.database.collation, currentValue, item, 170 type) < 0) { 171 currentValue = item; 172 } 173 174 return; 175 } 176 case Expression.EVERY : 177 if (!(item instanceof Boolean )) { 178 throw Trace.error(Trace.WRONG_DATA_TYPE); 179 } 180 181 every &= ((Boolean ) item).booleanValue(); 182 183 return; 184 185 case Expression.SOME : 186 if (!(item instanceof Boolean )) { 187 throw Trace.error(Trace.WRONG_DATA_TYPE); 188 } 189 190 some |= ((Boolean ) item).booleanValue(); 191 192 return; 193 194 case Expression.STDDEV_POP : 195 case Expression.STDDEV_SAMP : 196 case Expression.VAR_POP : 197 case Expression.VAR_SAMP : 198 if (!(item instanceof Number )) { 199 throw Trace.error(Trace.WRONG_DATA_TYPE); 200 } 201 202 addDataPoint((Number ) item); 203 204 return; 205 } 206 } 207 208 Object getValue() throws HsqlException { 209 210 if (setType == Expression.COUNT) { 211 return ValuePool.getInt(count); 212 } 213 214 if (count == 0) { 215 return null; 216 } 217 218 switch (setType) { 219 220 case Expression.AVG : { 221 switch (type) { 222 223 case Types.TINYINT : 224 case Types.SMALLINT : 225 case Types.INTEGER : 226 return new Long (currentLong / count); 227 228 case Types.BIGINT : { 229 long value = getLongSum().divide( 230 BigInteger.valueOf(count)).longValue(); 231 232 return new Long (value); 233 } 234 case Types.REAL : 235 case Types.FLOAT : 236 case Types.DOUBLE : 237 return new Double (currentDouble / count); 238 239 case Types.NUMERIC : 240 case Types.DECIMAL : 241 return currentBigDecimal.divide( 242 new BigDecimal (count), 243 BigDecimal.ROUND_HALF_DOWN); 244 245 default : 246 throw Trace.error(Trace.SUM_OF_NON_NUMERIC); 247 } 248 } 249 case Expression.SUM : { 250 switch (type) { 251 252 case Types.TINYINT : 253 case Types.SMALLINT : 254 case Types.INTEGER : 255 return new Long (currentLong); 256 257 case Types.BIGINT : 258 return new BigDecimal (getLongSum()); 259 260 case Types.REAL : 261 case Types.FLOAT : 262 case Types.DOUBLE : 263 return new Double (currentDouble); 264 265 case Types.NUMERIC : 266 case Types.DECIMAL : 267 return currentBigDecimal; 268 269 default : 270 throw Trace.error(Trace.SUM_OF_NON_NUMERIC); 271 } 272 } 273 case Expression.MIN : 274 case Expression.MAX : 275 return currentValue; 276 277 case Expression.EVERY : 278 return every ? Boolean.TRUE 279 : Boolean.FALSE; 280 281 case Expression.SOME : 282 return some ? Boolean.TRUE 283 : Boolean.FALSE; 284 285 case Expression.STDDEV_POP : 286 case Expression.STDDEV_SAMP : 287 return getStdDev(); 288 289 case Expression.VAR_POP : 290 case Expression.VAR_SAMP : 291 return getVariance(); 292 293 default : 294 throw Trace.error(Trace.INVALID_CONVERSION); 295 } 296 } 297 298 305 static int getType(int setType, int type) throws HsqlException { 306 307 switch (setType) { 308 309 case Expression.COUNT : 310 return Types.INTEGER; 311 312 case Expression.AVG : { 313 switch (type) { 314 315 case Types.TINYINT : 316 case Types.SMALLINT : 317 case Types.INTEGER : 318 case Types.BIGINT : 319 return Types.BIGINT; 320 321 case Types.REAL : 322 case Types.FLOAT : 323 case Types.DOUBLE : 324 return Types.DOUBLE; 325 326 case Types.NUMERIC : 327 case Types.DECIMAL : 328 return Types.DECIMAL; 329 330 default : 331 return Types.NULL; 332 } 333 } 334 case Expression.SUM : { 335 switch (type) { 336 337 case Types.TINYINT : 338 case Types.SMALLINT : 339 case Types.INTEGER : 340 return Types.BIGINT; 341 342 case Types.BIGINT : 343 return Types.DECIMAL; 344 345 case Types.REAL : 346 case Types.FLOAT : 347 case Types.DOUBLE : 348 return Types.DOUBLE; 349 350 case Types.NUMERIC : 351 case Types.DECIMAL : 352 return Types.DECIMAL; 353 354 default : 355 return Types.NULL; 356 } 357 } 358 case Expression.MIN : 359 case Expression.MAX : 360 return type; 361 362 case Expression.EVERY : 363 case Expression.SOME : 364 return Types.BOOLEAN; 365 366 case Expression.STDDEV_POP : 367 case Expression.STDDEV_SAMP : 368 case Expression.VAR_POP : 369 case Expression.VAR_SAMP : 370 return Types.DOUBLE; 371 372 default : 373 throw Trace.error(Trace.INVALID_CONVERSION); 374 } 375 } 376 377 379 383 static BigInteger multiplier = BigInteger.valueOf(0x0000000100000000L); 384 385 long hi; 387 long lo; 388 389 void addLong(long value) { 390 391 if (value == 0) {} 392 else if (value > 0) { 393 hi += value >> 32; 394 lo += value & 0x00000000ffffffffL; 395 } else { 396 if (value == Long.MIN_VALUE) { 397 hi -= 0x000000080000000L; 398 } else { 399 long temp = ~value + 1; 400 401 hi -= temp >> 32; 402 lo -= temp & 0x00000000ffffffffL; 403 } 404 } 405 406 } 408 409 BigInteger getLongSum() throws HsqlException { 410 411 BigInteger biglo = BigInteger.valueOf(lo); 412 BigInteger bighi = BigInteger.valueOf(hi); 413 BigInteger result = (bighi.multiply(multiplier)).add(biglo); 414 415 420 return result; 421 } 422 423 private double sk; 427 private double vk; 428 private long n; 429 private boolean initialized; 430 private boolean sample; 431 432 private void addDataPoint(Number x) { 434 double xi; 435 double xsi; 436 long nm1; 437 438 if (x == null) { 439 return; 440 } 441 442 xi = x.doubleValue(); 443 444 if (!initialized) { 445 n = 1; 446 sk = xi; 447 vk = 0.0; 448 initialized = true; 449 450 return; 451 } 452 453 n++; 454 455 nm1 = (n - 1); 456 xsi = (sk - (xi * nm1)); 457 vk += ((xsi * xsi) / n) / nm1; 458 sk += xi; 459 } 460 461 private Number getVariance() { 462 463 if (!initialized) { 464 return null; 465 } 466 467 return sample ? (n == 1) ? null : new Double (vk / (double) (n - 1)) 469 : new Double (vk / (double) (n)); 470 } 471 472 private Number getStdDev() { 473 474 if (!initialized) { 475 return null; 476 } 477 478 return sample ? (n == 1) ? null : new Double (Math.sqrt(vk 480 / (double) (n - 1))) 481 : new Double (Math.sqrt(vk / (double) (n))); 482 } 483 484 } 486 | Popular Tags |