|
HSQLDB example source code file (SetFunction.java)
The HSQLDB SetFunction.java source code/* Copyright (c) 2001-2008, The HSQL Development Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.hsqldb; import java.lang.Math; import java.math.BigDecimal; import java.math.BigInteger; import org.hsqldb.lib.HashSet; import org.hsqldb.store.ValuePool; /** * Implementation of SQL set functions (currently only aggregate functions). * This reduces temporary Object creation by SUM and AVG functions for * INTEGER and narrower types. * * @author fredt@users * @author boucherb@users * @version 1.7.3 * @since 1.7.2 * */ public class SetFunction { private HashSet distinctValues; private boolean isDistinct; // private int setType; private int type; // private int count; // private boolean hasNull; private boolean every = true; private boolean some = false; private long currentLong; private double currentDouble; private BigDecimal currentBigDecimal; private Object currentValue; SetFunction(int setType, int type, boolean isDistinct) { this.setType = setType; this.type = type; if (isDistinct) { this.isDistinct = true; distinctValues = new HashSet(); } if (setType == Expression.VAR_SAMP || setType == Expression.STDDEV_SAMP) { this.sample = true; } } void add(Session session, Object item) throws HsqlException { if (item == null) { hasNull = true; return; } if (isDistinct && !distinctValues.add(item)) { return; } count++; switch (setType) { case Expression.COUNT : return; case Expression.AVG : case Expression.SUM : { switch (type) { case Types.TINYINT : case Types.SMALLINT : case Types.INTEGER : currentLong += ((Number) item).intValue(); return; case Types.BIGINT : addLong(((Number) item).longValue()); return; case Types.REAL : case Types.FLOAT : case Types.DOUBLE : currentDouble += ((Number) item).doubleValue(); return; case Types.NUMERIC : case Types.DECIMAL : if (currentBigDecimal == null) { currentBigDecimal = (BigDecimal) item; } else { currentBigDecimal = currentBigDecimal.add((BigDecimal) item); } return; default : throw Trace.error(Trace.SUM_OF_NON_NUMERIC); } } case Expression.MIN : { if (currentValue == null) { currentValue = item; return; } if (Column.compare( session.database.collation, currentValue, item, type) > 0) { currentValue = item; } return; } case Expression.MAX : { if (currentValue == null) { currentValue = item; return; } if (Column.compare( session.database.collation, currentValue, item, type) < 0) { currentValue = item; } return; } case Expression.EVERY : if (!(item instanceof Boolean)) { throw Trace.error(Trace.WRONG_DATA_TYPE); } every &= ((Boolean) item).booleanValue(); return; case Expression.SOME : if (!(item instanceof Boolean)) { throw Trace.error(Trace.WRONG_DATA_TYPE); } some |= ((Boolean) item).booleanValue(); return; case Expression.STDDEV_POP : case Expression.STDDEV_SAMP : case Expression.VAR_POP : case Expression.VAR_SAMP : if (!(item instanceof Number)) { throw Trace.error(Trace.WRONG_DATA_TYPE); } addDataPoint((Number) item); return; } } Object getValue() throws HsqlException { if (setType == Expression.COUNT) { return ValuePool.getInt(count); } if (count == 0) { return null; } switch (setType) { case Expression.AVG : { switch (type) { case Types.TINYINT : case Types.SMALLINT : case Types.INTEGER : return new Long(currentLong / count); case Types.BIGINT : { long value = getLongSum().divide( BigInteger.valueOf(count)).longValue(); return new Long(value); } case Types.REAL : case Types.FLOAT : case Types.DOUBLE : return new Double(currentDouble / count); case Types.NUMERIC : case Types.DECIMAL : return currentBigDecimal.divide(new BigDecimal(count), BigDecimal.ROUND_DOWN); default : throw Trace.error(Trace.SUM_OF_NON_NUMERIC); } } case Expression.SUM : { switch (type) { case Types.TINYINT : case Types.SMALLINT : case Types.INTEGER : return new Long(currentLong); case Types.BIGINT : return new BigDecimal(getLongSum()); case Types.REAL : case Types.FLOAT : case Types.DOUBLE : return new Double(currentDouble); case Types.NUMERIC : case Types.DECIMAL : return currentBigDecimal; default : throw Trace.error(Trace.SUM_OF_NON_NUMERIC); } } case Expression.MIN : case Expression.MAX : return currentValue; case Expression.EVERY : return every ? Boolean.TRUE : Boolean.FALSE; case Expression.SOME : return some ? Boolean.TRUE : Boolean.FALSE; case Expression.STDDEV_POP : case Expression.STDDEV_SAMP : return getStdDev(); case Expression.VAR_POP : case Expression.VAR_SAMP : return getVariance(); default : throw Trace.error(Trace.INVALID_CONVERSION); } } /** * During parsing and before an instance of SetFunction is created, * getType is called with type parameter set to correct type when main * SELECT statements contain aggregates. It is called with Types.NULL * when SELECT statements within INSERT or UPDATE contian aggregates. * */ static int getType(int setType, int type) throws HsqlException { switch (setType) { case Expression.COUNT : return Types.INTEGER; case Expression.AVG : { switch (type) { case Types.TINYINT : case Types.SMALLINT : case Types.INTEGER : case Types.BIGINT : return Types.BIGINT; case Types.REAL : case Types.FLOAT : case Types.DOUBLE : return Types.DOUBLE; case Types.NUMERIC : case Types.DECIMAL : return Types.DECIMAL; default : return Types.NULL; } } case Expression.SUM : { switch (type) { case Types.TINYINT : case Types.SMALLINT : case Types.INTEGER : return Types.BIGINT; case Types.BIGINT : return Types.DECIMAL; case Types.REAL : case Types.FLOAT : case Types.DOUBLE : return Types.DOUBLE; case Types.NUMERIC : case Types.DECIMAL : return Types.DECIMAL; default : return Types.NULL; } } case Expression.MIN : case Expression.MAX : return type; case Expression.EVERY : case Expression.SOME : return Types.BOOLEAN; case Expression.STDDEV_POP : case Expression.STDDEV_SAMP : case Expression.VAR_POP : case Expression.VAR_SAMP : return Types.DOUBLE; default : throw Trace.error(Trace.INVALID_CONVERSION); } } // long sum - originally a separate class /** * Maintain the sum of multiple long values without creating a new * BigInteger object for each addition. */ static BigInteger multiplier = BigInteger.valueOf(0x0000000100000000L); // BigInteger bigint = BigInteger.ZERO; long hi; long lo; void addLong(long value) { if (value == 0) {} else if (value > 0) { hi += value >> 32; lo += value & 0x00000000ffffffffL; } else { if (value == Long.MIN_VALUE) { hi -= 0x000000080000000L; } else { long temp = ~value + 1; hi -= temp >> 32; lo -= temp & 0x00000000ffffffffL; } } // bigint = bigint.add(BigInteger.valueOf(value)); } BigInteger getLongSum() throws HsqlException { BigInteger biglo = BigInteger.valueOf(lo); BigInteger bighi = BigInteger.valueOf(hi); BigInteger result = (bighi.multiply(multiplier)).add(biglo); /* if ( result.compareTo(bigint) != 0 ){ throw Trace.error(Trace.GENERAL_ERROR, "longSum mismatch"); } */ return result; } // end long sum // statistics support - written by Campbell // this section was orginally an independent class private double sk; private double vk; private long n; private boolean initialized; private boolean sample; private void addDataPoint(Number x) { // optimized double xi; double xsi; long nm1; if (x == null) { return; } xi = x.doubleValue(); if (!initialized) { n = 1; sk = xi; vk = 0.0; initialized = true; return; } n++; nm1 = (n - 1); xsi = (sk - (xi * nm1)); vk += ((xsi * xsi) / n) / nm1; sk += xi; } private Number getVariance() { if (!initialized) { return null; } return sample ? (n == 1) ? null // NULL (not NaN) is correct in this case : new Double(vk / (double) (n - 1)) : new Double(vk / (double) (n)); } private Number getStdDev() { if (!initialized) { return null; } return sample ? (n == 1) ? null // NULL (not NaN) is correct in this case : new Double(Math.sqrt(vk / (double) (n - 1))) : new Double(Math.sqrt(vk / (double) (n))); } // end statistics support } Other HSQLDB examples (source code examples)Here is a short list of links related to this HSQLDB SetFunction.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.