提交 66d4ce58 authored 作者: Noel Grandin's avatar Noel Grandin

enum for AggregateType

上级 426737dd
......@@ -105,6 +105,7 @@ import org.h2.engine.User;
import org.h2.engine.UserAggregate;
import org.h2.engine.UserDataType;
import org.h2.expression.Aggregate;
import org.h2.expression.Aggregate.AggregateType;
import org.h2.expression.Alias;
import org.h2.expression.CompareLike;
import org.h2.expression.Comparison;
......@@ -2610,34 +2611,34 @@ public class Parser {
}
}
private Expression readAggregate(int aggregateType, String aggregateName) {
private Expression readAggregate(AggregateType aggregateType, String aggregateName) {
if (currentSelect == null) {
throw getSyntaxError();
}
currentSelect.setGroupQuery();
Expression r;
if (aggregateType == Aggregate.COUNT) {
if (aggregateType == AggregateType.COUNT) {
if (readIf("*")) {
r = new Aggregate(Aggregate.COUNT_ALL, null, currentSelect,
r = new Aggregate(AggregateType.COUNT_ALL, null, currentSelect,
false);
} else {
boolean distinct = readIf("DISTINCT");
Expression on = readExpression();
if (on instanceof Wildcard && !distinct) {
// PostgreSQL compatibility: count(t.*)
r = new Aggregate(Aggregate.COUNT_ALL, null, currentSelect,
r = new Aggregate(AggregateType.COUNT_ALL, null, currentSelect,
false);
} else {
r = new Aggregate(Aggregate.COUNT, on, currentSelect,
r = new Aggregate(AggregateType.COUNT, on, currentSelect,
distinct);
}
}
} else if (aggregateType == Aggregate.GROUP_CONCAT) {
} else if (aggregateType == AggregateType.GROUP_CONCAT) {
Aggregate agg = null;
boolean distinct = readIf("DISTINCT");
if (equalsToken("GROUP_CONCAT", aggregateName)) {
agg = new Aggregate(Aggregate.GROUP_CONCAT,
agg = new Aggregate(AggregateType.GROUP_CONCAT,
readExpression(), currentSelect, distinct);
if (readIf("ORDER")) {
read("BY");
......@@ -2649,7 +2650,7 @@ public class Parser {
}
} else if (equalsToken("STRING_AGG", aggregateName)) {
// PostgreSQL compatibility: string_agg(expression, delimiter)
agg = new Aggregate(Aggregate.GROUP_CONCAT,
agg = new Aggregate(AggregateType.GROUP_CONCAT,
readExpression(), currentSelect, distinct);
read(",");
agg.setGroupConcatSeparator(readExpression());
......@@ -2721,7 +2722,7 @@ public class Parser {
return agg;
}
private int getAggregateType(String name) {
private AggregateType getAggregateType(String name) {
if (!identifiersToUpper) {
// if not yet converted to uppercase, do it now
name = StringUtils.toUpperEnglish(name);
......@@ -2733,8 +2734,8 @@ public class Parser {
if (schema != null) {
return readJavaFunction(schema, name);
}
int agg = getAggregateType(name);
if (agg >= 0) {
AggregateType agg = getAggregateType(name);
if (agg != null) {
return readAggregate(agg, name);
}
Function function = Function.getFunction(database, name);
......@@ -5026,7 +5027,7 @@ public class Parser {
command.setForce(force);
String name = readIdentifierWithSchema();
if (isKeyword(name) || Function.getFunction(database, name) != null ||
getAggregateType(name) >= 0) {
getAggregateType(name) != null) {
throw DbException.get(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1,
name);
}
......@@ -5160,7 +5161,7 @@ public class Parser {
// fine
} else if (isKeyword(aliasName) ||
Function.getFunction(database, aliasName) != null ||
getAggregateType(aliasName) >= 0) {
getAggregateType(aliasName) != null) {
throw DbException.get(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1,
aliasName);
}
......
......@@ -39,94 +39,96 @@ import org.h2.value.ValueString;
*/
public class Aggregate extends Expression {
public enum AggregateType {
/**
* The aggregate type for COUNT(*).
*/
public static final int COUNT_ALL = 0;
COUNT_ALL,
/**
* The aggregate type for COUNT(expression).
*/
public static final int COUNT = 1;
COUNT,
/**
* The aggregate type for GROUP_CONCAT(...).
*/
public static final int GROUP_CONCAT = 2;
GROUP_CONCAT,
/**
* The aggregate type for SUM(expression).
*/
static final int SUM = 3;
SUM,
/**
* The aggregate type for MIN(expression).
*/
static final int MIN = 4;
MIN,
/**
* The aggregate type for MAX(expression).
*/
static final int MAX = 5;
MAX,
/**
* The aggregate type for AVG(expression).
*/
static final int AVG = 6;
AVG,
/**
* The aggregate type for STDDEV_POP(expression).
*/
static final int STDDEV_POP = 7;
STDDEV_POP,
/**
* The aggregate type for STDDEV_SAMP(expression).
*/
static final int STDDEV_SAMP = 8;
STDDEV_SAMP,
/**
* The aggregate type for VAR_POP(expression).
*/
static final int VAR_POP = 9;
VAR_POP,
/**
* The aggregate type for VAR_SAMP(expression).
*/
static final int VAR_SAMP = 10;
VAR_SAMP,
/**
* The aggregate type for BOOL_OR(expression).
*/
static final int BOOL_OR = 11;
BOOL_OR,
/**
* The aggregate type for BOOL_AND(expression).
*/
static final int BOOL_AND = 12;
BOOL_AND,
/**
* The aggregate type for BOOL_OR(expression).
*/
static final int BIT_OR = 13;
BIT_OR,
/**
* The aggregate type for BOOL_AND(expression).
*/
static final int BIT_AND = 14;
BIT_AND,
/**
* The aggregate type for SELECTIVITY(expression).
*/
static final int SELECTIVITY = 15;
SELECTIVITY,
/**
* The aggregate type for HISTOGRAM(expression).
*/
static final int HISTOGRAM = 16;
HISTOGRAM
}
private static final HashMap<String, Integer> AGGREGATES = new HashMap<>(24);
private static final HashMap<String, AggregateType> AGGREGATES = new HashMap<>(24);
private final int type;
private final AggregateType type;
private final Select select;
private final boolean distinct;
......@@ -147,7 +149,7 @@ public class Aggregate extends Expression {
* @param select the select statement
* @param distinct if distinct is used
*/
public Aggregate(int type, Expression on, Select select, boolean distinct) {
public Aggregate(AggregateType type, Expression on, Select select, boolean distinct) {
this.type = type;
this.on = on;
this.select = select;
......@@ -158,36 +160,36 @@ public class Aggregate extends Expression {
/*
* Update initial size of AGGREGATES after editing the following list.
*/
addAggregate("COUNT", COUNT);
addAggregate("SUM", SUM);
addAggregate("MIN", MIN);
addAggregate("MAX", MAX);
addAggregate("AVG", AVG);
addAggregate("GROUP_CONCAT", GROUP_CONCAT);
addAggregate("COUNT", AggregateType.COUNT);
addAggregate("SUM", AggregateType.SUM);
addAggregate("MIN", AggregateType.MIN);
addAggregate("MAX", AggregateType.MAX);
addAggregate("AVG", AggregateType.AVG);
addAggregate("GROUP_CONCAT", AggregateType.GROUP_CONCAT);
// PostgreSQL compatibility: string_agg(expression, delimiter)
addAggregate("STRING_AGG", GROUP_CONCAT);
addAggregate("STDDEV_SAMP", STDDEV_SAMP);
addAggregate("STDDEV", STDDEV_SAMP);
addAggregate("STDDEV_POP", STDDEV_POP);
addAggregate("STDDEVP", STDDEV_POP);
addAggregate("VAR_POP", VAR_POP);
addAggregate("VARP", VAR_POP);
addAggregate("VAR_SAMP", VAR_SAMP);
addAggregate("VAR", VAR_SAMP);
addAggregate("VARIANCE", VAR_SAMP);
addAggregate("BOOL_OR", BOOL_OR);
addAggregate("STRING_AGG", AggregateType.GROUP_CONCAT);
addAggregate("STDDEV_SAMP", AggregateType.STDDEV_SAMP);
addAggregate("STDDEV", AggregateType.STDDEV_SAMP);
addAggregate("STDDEV_POP", AggregateType.STDDEV_POP);
addAggregate("STDDEVP", AggregateType.STDDEV_POP);
addAggregate("VAR_POP", AggregateType.VAR_POP);
addAggregate("VARP", AggregateType.VAR_POP);
addAggregate("VAR_SAMP", AggregateType.VAR_SAMP);
addAggregate("VAR", AggregateType.VAR_SAMP);
addAggregate("VARIANCE", AggregateType.VAR_SAMP);
addAggregate("BOOL_OR", AggregateType.BOOL_OR);
// HSQLDB compatibility, but conflicts with x > EVERY(...)
addAggregate("SOME", BOOL_OR);
addAggregate("BOOL_AND", BOOL_AND);
addAggregate("SOME", AggregateType.BOOL_OR);
addAggregate("BOOL_AND", AggregateType.BOOL_AND);
// HSQLDB compatibility, but conflicts with x > SOME(...)
addAggregate("EVERY", BOOL_AND);
addAggregate("SELECTIVITY", SELECTIVITY);
addAggregate("HISTOGRAM", HISTOGRAM);
addAggregate("BIT_OR", BIT_OR);
addAggregate("BIT_AND", BIT_AND);
addAggregate("EVERY", AggregateType.BOOL_AND);
addAggregate("SELECTIVITY", AggregateType.SELECTIVITY);
addAggregate("HISTOGRAM", AggregateType.HISTOGRAM);
addAggregate("BIT_OR", AggregateType.BIT_OR);
addAggregate("BIT_AND", AggregateType.BIT_AND);
}
private static void addAggregate(String name, int type) {
private static void addAggregate(String name, AggregateType type) {
AGGREGATES.put(name, type);
}
......@@ -196,11 +198,10 @@ public class Aggregate extends Expression {
* found.
*
* @param name the aggregate function name
* @return -1 if no aggregate function has been found, or the aggregate type
* @return null if no aggregate function has been found, or the aggregate type
*/
public static int getAggregateType(String name) {
Integer type = AGGREGATES.get(name);
return type == null ? -1 : type.intValue();
public static AggregateType getAggregateType(String name) {
return AGGREGATES.get(name);
}
/**
......@@ -259,7 +260,7 @@ public class Aggregate extends Expression {
group.put(this, data);
}
Value v = on == null ? null : on.getValue(session);
if (type == GROUP_CONCAT) {
if (type == AggregateType.GROUP_CONCAT) {
if (v != ValueNull.INSTANCE) {
v = v.convertTo(Value.STRING);
if (groupConcatOrderList != null) {
......@@ -287,7 +288,7 @@ public class Aggregate extends Expression {
return ValueLong.get(table.getRowCount(session));
case MIN:
case MAX:
boolean first = type == MIN;
boolean first = type == AggregateType.MIN;
Index index = getMinMaxColumnIndex();
int sortType = index.getIndexColumns()[0].sortType;
if ((sortType & SortOrder.DESCENDING) != 0) {
......@@ -315,7 +316,7 @@ public class Aggregate extends Expression {
data = AggregateData.create(type);
}
Value v = data.getValue(session.getDatabase(), dataType, distinct);
if (type == GROUP_CONCAT) {
if (type == AggregateType.GROUP_CONCAT) {
ArrayList<Value> list = ((AggregateDataGroupConcat) data).getList();
if (list == null || list.size() == 0) {
return ValueNull.INSTANCE;
......
......@@ -6,6 +6,7 @@
package org.h2.expression;
import org.h2.engine.Database;
import org.h2.expression.Aggregate.AggregateType;
import org.h2.value.Value;
/**
......@@ -19,16 +20,16 @@ abstract class AggregateData {
* @param aggregateType the type of the aggregate operation
* @return the aggregate data object of the specified type
*/
static AggregateData create(int aggregateType) {
if (aggregateType == Aggregate.SELECTIVITY) {
static AggregateData create(AggregateType aggregateType) {
if (aggregateType == AggregateType.SELECTIVITY) {
return new AggregateDataSelectivity();
} else if (aggregateType == Aggregate.GROUP_CONCAT) {
} else if (aggregateType == AggregateType.GROUP_CONCAT) {
return new AggregateDataGroupConcat();
} else if (aggregateType == Aggregate.COUNT_ALL) {
} else if (aggregateType == AggregateType.COUNT_ALL) {
return new AggregateDataCountAll();
} else if (aggregateType == Aggregate.COUNT) {
} else if (aggregateType == AggregateType.COUNT) {
return new AggregateDataCount();
} else if (aggregateType == Aggregate.HISTOGRAM) {
} else if (aggregateType == AggregateType.HISTOGRAM) {
return new AggregateDataHistogram();
} else {
return new AggregateDataDefault(aggregateType);
......
......@@ -6,6 +6,7 @@
package org.h2.expression;
import org.h2.engine.Database;
import org.h2.expression.Aggregate.AggregateType;
import org.h2.message.DbException;
import org.h2.util.ValueHashMap;
import org.h2.value.DataType;
......@@ -19,7 +20,7 @@ import org.h2.value.ValueNull;
* Data stored while calculating an aggregate.
*/
class AggregateDataDefault extends AggregateData {
private final int aggregateType;
private final AggregateType aggregateType;
private long count;
private ValueHashMap<AggregateDataDefault> distinctValues;
private Value value;
......@@ -28,7 +29,7 @@ class AggregateDataDefault extends AggregateData {
/**
* @param aggregateType the type of the aggregate operation
*/
AggregateDataDefault(int aggregateType) {
AggregateDataDefault(AggregateType aggregateType) {
this.aggregateType = aggregateType;
}
......@@ -46,7 +47,7 @@ class AggregateDataDefault extends AggregateData {
return;
}
switch (aggregateType) {
case Aggregate.SUM:
case SUM:
if (value == null) {
value = v.convertTo(dataType);
} else {
......@@ -54,7 +55,7 @@ class AggregateDataDefault extends AggregateData {
value = value.add(v);
}
break;
case Aggregate.AVG:
case AVG:
if (value == null) {
value = v.convertTo(DataType.getAddProofType(dataType));
} else {
......@@ -62,20 +63,20 @@ class AggregateDataDefault extends AggregateData {
value = value.add(v);
}
break;
case Aggregate.MIN:
case MIN:
if (value == null || database.compare(v, value) < 0) {
value = v;
}
break;
case Aggregate.MAX:
case MAX:
if (value == null || database.compare(v, value) > 0) {
value = v;
}
break;
case Aggregate.STDDEV_POP:
case Aggregate.STDDEV_SAMP:
case Aggregate.VAR_POP:
case Aggregate.VAR_SAMP: {
case STDDEV_POP:
case STDDEV_SAMP:
case VAR_POP:
case VAR_SAMP: {
// Using Welford's method, see also
// http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
// http://www.johndcook.com/standard_deviation.html
......@@ -90,7 +91,7 @@ class AggregateDataDefault extends AggregateData {
}
break;
}
case Aggregate.BOOL_AND:
case BOOL_AND:
v = v.convertTo(Value.BOOLEAN);
if (value == null) {
value = v;
......@@ -98,7 +99,7 @@ class AggregateDataDefault extends AggregateData {
value = ValueBoolean.get(value.getBoolean() && v.getBoolean());
}
break;
case Aggregate.BOOL_OR:
case BOOL_OR:
v = v.convertTo(Value.BOOLEAN);
if (value == null) {
value = v;
......@@ -106,14 +107,14 @@ class AggregateDataDefault extends AggregateData {
value = ValueBoolean.get(value.getBoolean() || v.getBoolean());
}
break;
case Aggregate.BIT_AND:
case BIT_AND:
if (value == null) {
value = v.convertTo(dataType);
} else {
value = ValueLong.get(value.getLong() & v.getLong()).convertTo(dataType);
}
break;
case Aggregate.BIT_OR:
case BIT_OR:
if (value == null) {
value = v.convertTo(dataType);
} else {
......@@ -133,42 +134,42 @@ class AggregateDataDefault extends AggregateData {
}
Value v = null;
switch (aggregateType) {
case Aggregate.SUM:
case Aggregate.MIN:
case Aggregate.MAX:
case Aggregate.BIT_OR:
case Aggregate.BIT_AND:
case Aggregate.BOOL_OR:
case Aggregate.BOOL_AND:
case SUM:
case MIN:
case MAX:
case BIT_OR:
case BIT_AND:
case BOOL_OR:
case BOOL_AND:
v = value;
break;
case Aggregate.AVG:
case AVG:
if (value != null) {
v = divide(value, count);
}
break;
case Aggregate.STDDEV_POP: {
case STDDEV_POP: {
if (count < 1) {
return ValueNull.INSTANCE;
}
v = ValueDouble.get(Math.sqrt(m2 / count));
break;
}
case Aggregate.STDDEV_SAMP: {
case STDDEV_SAMP: {
if (count < 2) {
return ValueNull.INSTANCE;
}
v = ValueDouble.get(Math.sqrt(m2 / (count - 1)));
break;
}
case Aggregate.VAR_POP: {
case VAR_POP: {
if (count < 1) {
return ValueNull.INSTANCE;
}
v = ValueDouble.get(m2 / count);
break;
}
case Aggregate.VAR_SAMP: {
case VAR_SAMP: {
if (count < 2) {
return ValueNull.INSTANCE;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论