Unverified 提交 7dc28ecd authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1705 from katzyn/aggregate

Fix GROUP_CONCAT with variable separator
...@@ -3545,6 +3545,7 @@ GROUP_CONCAT ( [ DISTINCT|ALL ] string ...@@ -3545,6 +3545,7 @@ GROUP_CONCAT ( [ DISTINCT|ALL ] string
[FILTER (WHERE expression)] [OVER windowNameOrSpecification] [FILTER (WHERE expression)] [OVER windowNameOrSpecification]
"," ","
Concatenates strings with a separator. Concatenates strings with a separator.
Separator must be the same for all rows in the same group.
The default separator is a ',' (without space). The default separator is a ',' (without space).
This method returns a string. This method returns a string.
If no rows are selected, the result is NULL. If no rows are selected, the result is NULL.
......
...@@ -3041,43 +3041,50 @@ public class Parser { ...@@ -3041,43 +3041,50 @@ public class Parser {
switch (aggregateType) { switch (aggregateType) {
case COUNT: case COUNT:
if (readIf(ASTERISK)) { if (readIf(ASTERISK)) {
r = new Aggregate(AggregateType.COUNT_ALL, null, currentSelect, false); r = new Aggregate(AggregateType.COUNT_ALL, new Expression[0], currentSelect, false);
} else { } else {
boolean distinct = readDistinctAgg(); boolean distinct = readDistinctAgg();
Expression on = readExpression(); Expression on = readExpression();
if (on instanceof Wildcard && !distinct) { if (on instanceof Wildcard && !distinct) {
// PostgreSQL compatibility: count(t.*) // PostgreSQL compatibility: count(t.*)
r = new Aggregate(AggregateType.COUNT_ALL, null, currentSelect, false); r = new Aggregate(AggregateType.COUNT_ALL, new Expression[0], currentSelect, false);
} else { } else {
r = new Aggregate(AggregateType.COUNT, on, currentSelect, distinct); r = new Aggregate(AggregateType.COUNT, new Expression[] { on }, currentSelect, distinct);
} }
} }
break; break;
case GROUP_CONCAT: { case GROUP_CONCAT: {
boolean distinct = readDistinctAgg(); boolean distinct = readDistinctAgg();
r = new Aggregate(AggregateType.GROUP_CONCAT, readExpression(), currentSelect, distinct); Expression arg = readExpression(), separator = null;
ArrayList<SelectOrderBy> orderByList = null;
if (equalsToken("STRING_AGG", aggregateName)) { if (equalsToken("STRING_AGG", aggregateName)) {
// PostgreSQL compatibility: string_agg(expression, delimiter) // PostgreSQL compatibility: string_agg(expression, delimiter)
read(COMMA); read(COMMA);
r.setGroupConcatSeparator(readExpression()); separator = readExpression();
if (readIf(ORDER)) { if (readIf(ORDER)) {
read("BY"); read("BY");
r.setOrderByList(parseSimpleOrderList()); orderByList = parseSimpleOrderList();
} }
} else { } else {
if (readIf(ORDER)) { if (readIf(ORDER)) {
read("BY"); read("BY");
r.setOrderByList(parseSimpleOrderList()); orderByList = parseSimpleOrderList();
} }
if (readIf("SEPARATOR")) { if (readIf("SEPARATOR")) {
r.setGroupConcatSeparator(readExpression()); separator = readExpression();
} }
} }
r = new Aggregate(AggregateType.GROUP_CONCAT,
separator == null ? new Expression[] { arg } : new Expression[] { arg, separator },
currentSelect, distinct);
if (orderByList != null) {
r.setOrderByList(orderByList);
}
break; break;
} }
case ARRAY_AGG: { case ARRAY_AGG: {
boolean distinct = readDistinctAgg(); boolean distinct = readDistinctAgg();
r = new Aggregate(AggregateType.ARRAY_AGG, readExpression(), currentSelect, distinct); r = new Aggregate(AggregateType.ARRAY_AGG, new Expression[] { readExpression() }, currentSelect, distinct);
if (readIf(ORDER)) { if (readIf(ORDER)) {
read("BY"); read("BY");
r.setOrderByList(parseSimpleOrderList()); r.setOrderByList(parseSimpleOrderList());
...@@ -3088,15 +3095,15 @@ public class Parser { ...@@ -3088,15 +3095,15 @@ public class Parser {
case PERCENTILE_DISC: { case PERCENTILE_DISC: {
Expression num = readExpression(); Expression num = readExpression();
read(CLOSE_PAREN); read(CLOSE_PAREN);
r = readWithinGroup(aggregateType, num); r = readWithinGroup(aggregateType, new Expression[] { num });
break; break;
} }
case MODE: { case MODE: {
if (readIf(CLOSE_PAREN)) { if (readIf(CLOSE_PAREN)) {
r = readWithinGroup(AggregateType.MODE, null); r = readWithinGroup(AggregateType.MODE, new Expression[0]);
} else { } else {
Expression expr = readExpression(); Expression expr = readExpression();
r = new Aggregate(aggregateType, null, currentSelect, false); r = new Aggregate(aggregateType, new Expression[0], currentSelect, false);
if (readIf(ORDER)) { if (readIf(ORDER)) {
read("BY"); read("BY");
Expression expr2 = readExpression(); Expression expr2 = readExpression();
...@@ -3114,7 +3121,7 @@ public class Parser { ...@@ -3114,7 +3121,7 @@ public class Parser {
} }
default: default:
boolean distinct = readDistinctAgg(); boolean distinct = readDistinctAgg();
r = new Aggregate(aggregateType, readExpression(), currentSelect, distinct); r = new Aggregate(aggregateType, new Expression[] { readExpression() }, currentSelect, distinct);
break; break;
} }
read(CLOSE_PAREN); read(CLOSE_PAREN);
...@@ -3122,7 +3129,7 @@ public class Parser { ...@@ -3122,7 +3129,7 @@ public class Parser {
return r; return r;
} }
private Aggregate readWithinGroup(AggregateType aggregateType, Expression argument) { private Aggregate readWithinGroup(AggregateType aggregateType, Expression[] args) {
Aggregate r; Aggregate r;
read("WITHIN"); read("WITHIN");
read(GROUP); read(GROUP);
...@@ -3130,7 +3137,7 @@ public class Parser { ...@@ -3130,7 +3137,7 @@ public class Parser {
read(ORDER); read(ORDER);
read("BY"); read("BY");
Expression expr = readExpression(); Expression expr = readExpression();
r = new Aggregate(aggregateType, argument, currentSelect, false); r = new Aggregate(aggregateType, args, currentSelect, false);
readAggregateOrder(r, expr, true); readAggregateOrder(r, expr, true);
return r; return r;
} }
......
...@@ -22,6 +22,7 @@ import org.h2.expression.analysis.WindowFrameExclusion; ...@@ -22,6 +22,7 @@ import org.h2.expression.analysis.WindowFrameExclusion;
import org.h2.expression.analysis.WindowFrameUnits; import org.h2.expression.analysis.WindowFrameUnits;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value; import org.h2.value.Value;
/** /**
...@@ -34,13 +35,24 @@ public abstract class AbstractAggregate extends DataAnalysisOperation { ...@@ -34,13 +35,24 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
*/ */
protected final boolean distinct; protected final boolean distinct;
/**
* The arguments.
*/
protected final Expression[] args;
/** /**
* FILTER condition for aggregate * FILTER condition for aggregate
*/ */
protected Expression filterCondition; protected Expression filterCondition;
AbstractAggregate(Select select, boolean distinct) { /**
* The type of the result.
*/
protected TypeInfo type;
AbstractAggregate(Select select, Expression[] args, boolean distinct) {
super(select); super(select);
this.args = args;
this.distinct = distinct; this.distinct = distinct;
} }
...@@ -59,8 +71,16 @@ public abstract class AbstractAggregate extends DataAnalysisOperation { ...@@ -59,8 +71,16 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
this.filterCondition = filterCondition; this.filterCondition = filterCondition;
} }
@Override
public TypeInfo getType() {
return type;
}
@Override @Override
public void mapColumnsAnalysis(ColumnResolver resolver, int level, int innerState) { public void mapColumnsAnalysis(ColumnResolver resolver, int level, int innerState) {
for (Expression arg : args) {
arg.mapColumns(resolver, level, innerState);
}
if (filterCondition != null) { if (filterCondition != null) {
filterCondition.mapColumns(resolver, level, innerState); filterCondition.mapColumns(resolver, level, innerState);
} }
...@@ -69,6 +89,9 @@ public abstract class AbstractAggregate extends DataAnalysisOperation { ...@@ -69,6 +89,9 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
@Override @Override
public Expression optimize(Session session) { public Expression optimize(Session session) {
for (int i = 0; i < args.length; i++) {
args[i] = args[i].optimize(session);
}
if (filterCondition != null) { if (filterCondition != null) {
filterCondition = filterCondition.optimize(session); filterCondition = filterCondition.optimize(session);
} }
...@@ -77,6 +100,9 @@ public abstract class AbstractAggregate extends DataAnalysisOperation { ...@@ -77,6 +100,9 @@ public abstract class AbstractAggregate extends DataAnalysisOperation {
@Override @Override
public void setEvaluatable(TableFilter tableFilter, boolean b) { public void setEvaluatable(TableFilter tableFilter, boolean b) {
for (Expression arg : args) {
arg.setEvaluatable(tableFilter, b);
}
if (filterCondition != null) { if (filterCondition != null) {
filterCondition.setEvaluatable(tableFilter, b); filterCondition.setEvaluatable(tableFilter, b);
} }
......
...@@ -53,31 +53,27 @@ public class Aggregate extends AbstractAggregate { ...@@ -53,31 +53,27 @@ public class Aggregate extends AbstractAggregate {
private final AggregateType aggregateType; private final AggregateType aggregateType;
private Expression on;
private Expression groupConcatSeparator;
private ArrayList<SelectOrderBy> orderByList; private ArrayList<SelectOrderBy> orderByList;
private SortOrder orderBySort; private SortOrder orderBySort;
private TypeInfo type;
/** /**
* Create a new aggregate object. * Create a new aggregate object.
* *
* @param aggregateType * @param aggregateType
* the aggregate type * the aggregate type
* @param on * @param args
* the aggregated expression * the aggregated expressions
* @param select * @param select
* the select statement * the select statement
* @param distinct * @param distinct
* if distinct is used * if distinct is used
*/ */
public Aggregate(AggregateType aggregateType, Expression on, Select select, boolean distinct) { public Aggregate(AggregateType aggregateType, Expression[] args, Select select, boolean distinct) {
super(select, distinct); super(select, args, distinct);
if (distinct && aggregateType == AggregateType.COUNT_ALL) { if (distinct && aggregateType == AggregateType.COUNT_ALL) {
throw DbException.throwInternalError(); throw DbException.throwInternalError();
} }
this.aggregateType = aggregateType; this.aggregateType = aggregateType;
this.on = on;
} }
static { static {
...@@ -149,16 +145,6 @@ public class Aggregate extends AbstractAggregate { ...@@ -149,16 +145,6 @@ public class Aggregate extends AbstractAggregate {
this.orderByList = orderByList; this.orderByList = orderByList;
} }
/**
* Set the separator for the GROUP_CONCAT() aggregate.
*
* @param separator
* the separator expression
*/
public void setGroupConcatSeparator(Expression separator) {
this.groupConcatSeparator = separator;
}
/** /**
* Returns the type of this aggregate. * Returns the type of this aggregate.
* *
...@@ -185,7 +171,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -185,7 +171,7 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
protected void updateAggregate(Session session, Object aggregateData) { protected void updateAggregate(Session session, Object aggregateData) {
AggregateData data = (AggregateData) aggregateData; AggregateData data = (AggregateData) aggregateData;
Value v = on == null ? null : on.getValue(session); Value v = args.length == 0 ? null : args[0].getValue(session);
updateData(session, data, v, null); updateData(session, data, v, null);
} }
...@@ -195,6 +181,10 @@ public class Aggregate extends AbstractAggregate { ...@@ -195,6 +181,10 @@ public class Aggregate extends AbstractAggregate {
if (v != ValueNull.INSTANCE) { if (v != ValueNull.INSTANCE) {
v = updateCollecting(session, v.convertTo(Value.STRING), remembered); v = updateCollecting(session, v.convertTo(Value.STRING), remembered);
} }
if (args.length >= 2) {
((AggregateDataCollecting) data).setSharedArgument(
remembered != null ? remembered[1] : args[1].getValue(session));
}
break; break;
case ARRAY_AGG: case ARRAY_AGG:
if (v != ValueNull.INSTANCE) { if (v != ValueNull.INSTANCE) {
...@@ -218,8 +208,8 @@ public class Aggregate extends AbstractAggregate { ...@@ -218,8 +208,8 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
protected void updateGroupAggregates(Session session, int stage) { protected void updateGroupAggregates(Session session, int stage) {
super.updateGroupAggregates(session, stage); super.updateGroupAggregates(session, stage);
if (on != null) { for (Expression arg : args) {
on.updateAggregate(session, stage); arg.updateAggregate(session, stage);
} }
if (orderByList != null) { if (orderByList != null) {
for (SelectOrderBy orderBy : orderByList) { for (SelectOrderBy orderBy : orderByList) {
...@@ -248,7 +238,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -248,7 +238,7 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
protected int getNumExpressions() { protected int getNumExpressions() {
int n = on != null ? 1 : 0; int n = args.length;
if (orderByList != null) { if (orderByList != null) {
n += orderByList.size(); n += orderByList.size();
} }
...@@ -261,8 +251,8 @@ public class Aggregate extends AbstractAggregate { ...@@ -261,8 +251,8 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
protected void rememberExpressions(Session session, Value[] array) { protected void rememberExpressions(Session session, Value[] array) {
int offset = 0; int offset = 0;
if (on != null) { for (Expression arg : args) {
array[offset++] = on.getValue(session); array[offset++] = arg.getValue(session);
} }
if (orderByList != null) { if (orderByList != null) {
for (SelectOrderBy o : orderByList) { for (SelectOrderBy o : orderByList) {
...@@ -278,7 +268,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -278,7 +268,7 @@ public class Aggregate extends AbstractAggregate {
protected void updateFromExpressions(Session session, Object aggregateData, Value[] array) { protected void updateFromExpressions(Session session, Object aggregateData, Value[] array) {
if (filterCondition == null || array[getNumExpressions() - 1].getBoolean()) { if (filterCondition == null || array[getNumExpressions() - 1].getBoolean()) {
AggregateData data = (AggregateData) aggregateData; AggregateData data = (AggregateData) aggregateData;
Value v = on == null ? null : array[0]; Value v = args.length == 0 ? null : array[0];
updateData(session, data, v, array); updateData(session, data, v, array);
} }
} }
...@@ -319,7 +309,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -319,7 +309,7 @@ public class Aggregate extends AbstractAggregate {
} }
case PERCENTILE_CONT: case PERCENTILE_CONT:
case PERCENTILE_DISC: { case PERCENTILE_DISC: {
Value v = on.getValue(session); Value v = args[0].getValue(session);
if (v == ValueNull.INSTANCE) { if (v == ValueNull.INSTANCE) {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
...@@ -333,9 +323,9 @@ public class Aggregate extends AbstractAggregate { ...@@ -333,9 +323,9 @@ public class Aggregate extends AbstractAggregate {
} }
} }
case MEDIAN: case MEDIAN:
return Percentile.getFromIndex(session, on, type.getValueType(), orderByList, Percentile.HALF, true); return Percentile.getFromIndex(session, args[0], type.getValueType(), orderByList, Percentile.HALF, true);
case ENVELOPE: case ENVELOPE:
return ((MVSpatialIndex) AggregateDataEnvelope.getGeometryColumnIndex(on)).getBounds(session); return ((MVSpatialIndex) AggregateDataEnvelope.getGeometryColumnIndex(args[0])).getBounds(session);
default: default:
throw DbException.throwInternalError("type=" + aggregateType); throw DbException.throwInternalError("type=" + aggregateType);
} }
...@@ -429,7 +419,8 @@ public class Aggregate extends AbstractAggregate { ...@@ -429,7 +419,8 @@ public class Aggregate extends AbstractAggregate {
} }
private Value getGroupConcat(Session session, AggregateData data) { private Value getGroupConcat(Session session, AggregateData data) {
Value[] array = ((AggregateDataCollecting) data).getArray(); AggregateDataCollecting collectingData = (AggregateDataCollecting) data;
Value[] array = collectingData.getArray();
if (array == null) { if (array == null) {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
...@@ -437,7 +428,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -437,7 +428,7 @@ public class Aggregate extends AbstractAggregate {
sortWithOrderBy(array); sortWithOrderBy(array);
} }
StatementBuilder buff = new StatementBuilder(); StatementBuilder buff = new StatementBuilder();
String sep = groupConcatSeparator == null ? "," : groupConcatSeparator.getValue(session).getString(); String sep = args.length < 2 ? "," : collectingData.getSharedArgument().getString();
for (Value val : array) { for (Value val : array) {
String s; String s;
if (val.getValueType() == Value.ARRAY) { if (val.getValueType() == Value.ARRAY) {
...@@ -521,33 +512,21 @@ public class Aggregate extends AbstractAggregate { ...@@ -521,33 +512,21 @@ public class Aggregate extends AbstractAggregate {
return v.convertTo(type.getValueType()); return v.convertTo(type.getValueType());
} }
@Override
public TypeInfo getType() {
return type;
}
@Override @Override
public void mapColumnsAnalysis(ColumnResolver resolver, int level, int innerState) { public void mapColumnsAnalysis(ColumnResolver resolver, int level, int innerState) {
if (on != null) {
on.mapColumns(resolver, level, innerState);
}
if (orderByList != null) { if (orderByList != null) {
for (SelectOrderBy o : orderByList) { for (SelectOrderBy o : orderByList) {
o.expression.mapColumns(resolver, level, innerState); o.expression.mapColumns(resolver, level, innerState);
} }
} }
if (groupConcatSeparator != null) {
groupConcatSeparator.mapColumns(resolver, level, innerState);
}
super.mapColumnsAnalysis(resolver, level, innerState); super.mapColumnsAnalysis(resolver, level, innerState);
} }
@Override @Override
public Expression optimize(Session session) { public Expression optimize(Session session) {
super.optimize(session); super.optimize(session);
if (on != null) { if (args.length == 1) {
on = on.optimize(session); type = args[0].getType();
type = on.getType();
} }
if (orderByList != null) { if (orderByList != null) {
for (SelectOrderBy o : orderByList) { for (SelectOrderBy o : orderByList) {
...@@ -555,9 +534,6 @@ public class Aggregate extends AbstractAggregate { ...@@ -555,9 +534,6 @@ public class Aggregate extends AbstractAggregate {
} }
orderBySort = createOrder(session, orderByList, 1); orderBySort = createOrder(session, orderByList, 1);
} }
if (groupConcatSeparator != null) {
groupConcatSeparator = groupConcatSeparator.optimize(session);
}
switch (aggregateType) { switch (aggregateType) {
case GROUP_CONCAT: case GROUP_CONCAT:
type = TypeInfo.TYPE_STRING_DEFAULT; type = TypeInfo.TYPE_STRING_DEFAULT;
...@@ -642,17 +618,11 @@ public class Aggregate extends AbstractAggregate { ...@@ -642,17 +618,11 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
public void setEvaluatable(TableFilter tableFilter, boolean b) { public void setEvaluatable(TableFilter tableFilter, boolean b) {
if (on != null) {
on.setEvaluatable(tableFilter, b);
}
if (orderByList != null) { if (orderByList != null) {
for (SelectOrderBy o : orderByList) { for (SelectOrderBy o : orderByList) {
o.expression.setEvaluatable(tableFilter, b); o.expression.setEvaluatable(tableFilter, b);
} }
} }
if (groupConcatSeparator != null) {
groupConcatSeparator.setEvaluatable(tableFilter, b);
}
super.setEvaluatable(tableFilter, b); super.setEvaluatable(tableFilter, b);
} }
...@@ -661,11 +631,11 @@ public class Aggregate extends AbstractAggregate { ...@@ -661,11 +631,11 @@ public class Aggregate extends AbstractAggregate {
if (distinct) { if (distinct) {
builder.append("DISTINCT "); builder.append("DISTINCT ");
} }
on.getSQL(builder); args[0].getSQL(builder);
Window.appendOrderBy(builder, orderByList); Window.appendOrderBy(builder, orderByList);
if (groupConcatSeparator != null) { if (args.length >= 2) {
builder.append(" SEPARATOR "); builder.append(" SEPARATOR ");
groupConcatSeparator.getSQL(builder); args[1].getSQL(builder);
} }
builder.append(')'); builder.append(')');
return appendTailConditions(builder); return appendTailConditions(builder);
...@@ -676,7 +646,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -676,7 +646,7 @@ public class Aggregate extends AbstractAggregate {
if (distinct) { if (distinct) {
builder.append("DISTINCT "); builder.append("DISTINCT ");
} }
on.getSQL(builder); args[0].getSQL(builder);
Window.appendOrderBy(builder, orderByList); Window.appendOrderBy(builder, orderByList);
builder.append(')'); builder.append(')');
return appendTailConditions(builder); return appendTailConditions(builder);
...@@ -758,14 +728,14 @@ public class Aggregate extends AbstractAggregate { ...@@ -758,14 +728,14 @@ public class Aggregate extends AbstractAggregate {
builder.append(text); builder.append(text);
if (distinct) { if (distinct) {
builder.append("(DISTINCT "); builder.append("(DISTINCT ");
on.getSQL(builder).append(')'); args[0].getSQL(builder).append(')');
} else { } else {
builder.append('('); builder.append('(');
if (on != null) { for (Expression arg : args) {
if (on instanceof Subquery) { if (arg instanceof Subquery) {
on.getSQL(builder); arg.getSQL(builder);
} else { } else {
on.getUnenclosedSQL(builder); arg.getUnenclosedSQL(builder);
} }
} }
builder.append(')'); builder.append(')');
...@@ -779,8 +749,9 @@ public class Aggregate extends AbstractAggregate { ...@@ -779,8 +749,9 @@ public class Aggregate extends AbstractAggregate {
} }
private Index getMinMaxColumnIndex() { private Index getMinMaxColumnIndex() {
if (on instanceof ExpressionColumn) { Expression arg = args[0];
ExpressionColumn col = (ExpressionColumn) on; if (arg instanceof ExpressionColumn) {
ExpressionColumn col = (ExpressionColumn) arg;
Column column = col.getColumn(); Column column = col.getColumn();
TableFilter filter = col.getTableFilter(); TableFilter filter = col.getTableFilter();
if (filter != null) { if (filter != null) {
...@@ -802,7 +773,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -802,7 +773,7 @@ public class Aggregate extends AbstractAggregate {
if (visitor.getType() == ExpressionVisitor.OPTIMIZABLE_AGGREGATE) { if (visitor.getType() == ExpressionVisitor.OPTIMIZABLE_AGGREGATE) {
switch (aggregateType) { switch (aggregateType) {
case COUNT: case COUNT:
if (!distinct && on.getNullable() == Column.NOT_NULLABLE) { if (!distinct && args[0].getNullable() == Column.NOT_NULLABLE) {
return visitor.getTable().canGetRowCount(); return visitor.getTable().canGetRowCount();
} }
return false; return false;
...@@ -814,23 +785,22 @@ public class Aggregate extends AbstractAggregate { ...@@ -814,23 +785,22 @@ public class Aggregate extends AbstractAggregate {
return index != null; return index != null;
case PERCENTILE_CONT: case PERCENTILE_CONT:
case PERCENTILE_DISC: case PERCENTILE_DISC:
return on.isConstant() && Percentile.getColumnIndex(orderByList.get(0).expression) != null; return args[0].isConstant() && Percentile.getColumnIndex(orderByList.get(0).expression) != null;
case MEDIAN: case MEDIAN:
if (distinct) { if (distinct) {
return false; return false;
} }
return Percentile.getColumnIndex(on) != null; return Percentile.getColumnIndex(args[0]) != null;
case ENVELOPE: case ENVELOPE:
return AggregateDataEnvelope.getGeometryColumnIndex(on) != null; return AggregateDataEnvelope.getGeometryColumnIndex(args[0]) != null;
default: default:
return false; return false;
} }
} }
if (on != null && !on.isEverything(visitor)) { for (Expression arg : args) {
return false; if (!arg.isEverything(visitor)) {
} return false;
if (groupConcatSeparator != null && !groupConcatSeparator.isEverything(visitor)) { }
return false;
} }
if (orderByList != null) { if (orderByList != null) {
for (SelectOrderBy o : orderByList) { for (SelectOrderBy o : orderByList) {
...@@ -845,8 +815,13 @@ public class Aggregate extends AbstractAggregate { ...@@ -845,8 +815,13 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
public int getCost() { public int getCost() {
int cost = 1; int cost = 1;
if (on != null) { for (Expression arg : args) {
cost += on.getCost(); cost += arg.getCost();
}
if (orderByList != null) {
for (SelectOrderBy o : orderByList) {
cost += o.expression.getCost();
}
} }
if (filterCondition != null) { if (filterCondition != null) {
cost += filterCondition.getCost(); cost += filterCondition.getCost();
......
...@@ -15,8 +15,6 @@ import org.h2.engine.UserAggregate; ...@@ -15,8 +15,6 @@ import org.h2.engine.UserAggregate;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor; import org.h2.expression.ExpressionVisitor;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.TypeInfo; import org.h2.value.TypeInfo;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -30,16 +28,13 @@ import org.h2.value.ValueRow; ...@@ -30,16 +28,13 @@ import org.h2.value.ValueRow;
public class JavaAggregate extends AbstractAggregate { public class JavaAggregate extends AbstractAggregate {
private final UserAggregate userAggregate; private final UserAggregate userAggregate;
private final Expression[] args;
private int[] argTypes; private int[] argTypes;
private TypeInfo type;
private int dataType; private int dataType;
private Connection userConnection; private Connection userConnection;
public JavaAggregate(UserAggregate userAggregate, Expression[] args, Select select, boolean distinct) { public JavaAggregate(UserAggregate userAggregate, Expression[] args, Select select, boolean distinct) {
super(select, distinct); super(select, args, distinct);
this.userAggregate = userAggregate; this.userAggregate = userAggregate;
this.args = args;
} }
@Override @Override
...@@ -62,11 +57,6 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -62,11 +57,6 @@ public class JavaAggregate extends AbstractAggregate {
return appendTailConditions(builder); return appendTailConditions(builder);
} }
@Override
public TypeInfo getType() {
return type;
}
@Override @Override
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
if (!super.isEverything(visitor)) { if (!super.isEverything(visitor)) {
...@@ -92,14 +82,6 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -92,14 +82,6 @@ public class JavaAggregate extends AbstractAggregate {
return filterCondition == null || filterCondition.isEverything(visitor); return filterCondition == null || filterCondition.isEverything(visitor);
} }
@Override
public void mapColumnsAnalysis(ColumnResolver resolver, int level, int innerState) {
for (Expression arg : args) {
arg.mapColumns(resolver, level, innerState);
}
super.mapColumnsAnalysis(resolver, level, innerState);
}
@Override @Override
public Expression optimize(Session session) { public Expression optimize(Session session) {
super.optimize(session); super.optimize(session);
...@@ -107,9 +89,7 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -107,9 +89,7 @@ public class JavaAggregate extends AbstractAggregate {
int len = args.length; int len = args.length;
argTypes = new int[len]; argTypes = new int[len];
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Expression expr = args[i]; int type = args[i].getType().getValueType();
args[i] = expr.optimize(session);
int type = expr.getType().getValueType();
argTypes[i] = type; argTypes[i] = type;
} }
try { try {
...@@ -122,14 +102,6 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -122,14 +102,6 @@ public class JavaAggregate extends AbstractAggregate {
return this; return this;
} }
@Override
public void setEvaluatable(TableFilter tableFilter, boolean b) {
for (Expression e : args) {
e.setEvaluatable(tableFilter, b);
}
super.setEvaluatable(tableFilter, b);
}
private Aggregate getInstance() { private Aggregate getInstance() {
Aggregate agg = userAggregate.getInstance(); Aggregate agg = userAggregate.getInstance();
try { try {
......
...@@ -67,3 +67,32 @@ select group_concat(distinct v order by v desc) from test; ...@@ -67,3 +67,32 @@ select group_concat(distinct v order by v desc) from test;
drop table test; drop table test;
> ok > ok
create table test(g varchar, v int) as values ('-', 1), ('-', 2), ('-', 3), ('|', 4), ('|', 5), ('|', 6), ('*', null);
> ok
select g, group_concat(v separator g) from test group by g;
> G GROUP_CONCAT(V SEPARATOR G)
> - ---------------------------
> * null
> - 1-2-3
> | 4|5|6
> rows: 3
select g, group_concat(v separator g) over (partition by g) from test order by v;
> G GROUP_CONCAT(V SEPARATOR G) OVER (PARTITION BY G)
> - -------------------------------------------------
> * null
> - 1-2-3
> - 1-2-3
> - 1-2-3
> | 4|5|6
> | 4|5|6
> | 4|5|6
> rows (ordered): 7
select g, group_concat(v separator v) from test group by g;
> exception INVALID_VALUE_2
drop table test;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论