提交 4c2a4489 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Store window data in SelectGroups

上级 64ff1b54
...@@ -8,7 +8,6 @@ package org.h2.command.dml; ...@@ -8,7 +8,6 @@ package org.h2.command.dml;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.Trigger; import org.h2.api.Trigger;
...@@ -105,7 +104,8 @@ public class Select extends Query { ...@@ -105,7 +104,8 @@ public class Select extends Query {
SelectGroups groupData; SelectGroups groupData;
private int havingIndex; private int havingIndex;
private boolean isGroupQuery, isGroupSortedQuery; boolean isGroupQuery;
private boolean isGroupSortedQuery;
private boolean isWindowQuery; private boolean isWindowQuery;
private boolean isForUpdate, isForUpdateMvcc; private boolean isForUpdate, isForUpdateMvcc;
private double cost; private double cost;
...@@ -177,8 +177,8 @@ public class Select extends Query { ...@@ -177,8 +177,8 @@ public class Select extends Query {
return group; return group;
} }
public SelectGroups getGroupDataIfCurrent(boolean forAggregate) { public SelectGroups getGroupDataIfCurrent(boolean window) {
return groupData != null && (forAggregate || !isWindowQuery) && groupData.isCurrentGroup() ? groupData : null; return groupData != null && (window || groupData.isCurrentGroup()) ? groupData : null;
} }
@Override @Override
...@@ -357,10 +357,9 @@ public class Select extends Query { ...@@ -357,10 +357,9 @@ public class Select extends Query {
private void queryWindow(int columnCount, LocalResult result, long offset, boolean quickOffset) { private void queryWindow(int columnCount, LocalResult result, long offset, boolean quickOffset) {
if (groupData == null) { if (groupData == null) {
groupData = new SelectGroups(session, expressions, groupIndex); groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex);
} }
groupData.reset(); groupData.reset();
HashMap<ValueArray, ArrayList<Row>> rows = new HashMap<>();
try { try {
int rowNumber = 0; int rowNumber = 0;
setCurrentRowNumber(0); setCurrentRowNumber(0);
...@@ -369,13 +368,7 @@ public class Select extends Query { ...@@ -369,13 +368,7 @@ public class Select extends Query {
setCurrentRowNumber(rowNumber + 1); setCurrentRowNumber(rowNumber + 1);
if (isConditionMet()) { if (isConditionMet()) {
rowNumber++; rowNumber++;
ValueArray key = groupData.nextSource(); groupData.nextSource();
ArrayList<Row> groupRows = rows.get(key);
if (groupRows == null) {
groupRows = Utils.newSmallArrayList();
rows.put(key, groupRows);
}
groupRows.add(topTableFilter.get());
updateAgg(columnCount); updateAgg(columnCount);
if (sampleSize > 0 && rowNumber >= sampleSize) { if (sampleSize > 0 && rowNumber >= sampleSize) {
break; break;
...@@ -384,10 +377,7 @@ public class Select extends Query { ...@@ -384,10 +377,7 @@ public class Select extends Query {
} }
groupData.done(); groupData.done();
for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) { for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) {
for (Row originalRow : rows.get(currentGroupsKey)) { offset = processGroupedRow(columnCount, result, offset, quickOffset, currentGroupsKey);
topTableFilter.set(originalRow);
offset = processGroupedRow(columnCount, result, offset, quickOffset, currentGroupsKey);
}
} }
} finally { } finally {
groupData.reset(); groupData.reset();
...@@ -396,7 +386,7 @@ public class Select extends Query { ...@@ -396,7 +386,7 @@ public class Select extends Query {
private void queryGroup(int columnCount, LocalResult result, long offset, boolean quickOffset) { private void queryGroup(int columnCount, LocalResult result, long offset, boolean quickOffset) {
if (groupData == null) { if (groupData == null) {
groupData = new SelectGroups(session, expressions, groupIndex); groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex);
} }
groupData.reset(); groupData.reset();
try { try {
...@@ -1654,7 +1644,7 @@ public class Select extends Query { ...@@ -1654,7 +1644,7 @@ public class Select extends Query {
LazyResultGroupSorted(Expression[] expressions, int columnCount) { LazyResultGroupSorted(Expression[] expressions, int columnCount) {
super(expressions, columnCount); super(expressions, columnCount);
if (groupData == null) { if (groupData == null) {
groupData = new SelectGroups(getSession(), Select.this.expressions, groupIndex); groupData = SelectGroups.getInstance(getSession(), Select.this.expressions, isGroupQuery, groupIndex);
} else { } else {
// TODO is this branch possible? // TODO is this branch possible?
groupData.resetLazy(); groupData.resetLazy();
......
...@@ -164,9 +164,9 @@ public class ExpressionColumn extends Expression { ...@@ -164,9 +164,9 @@ public class ExpressionColumn extends Expression {
// this is a different level (the enclosing query) // this is a different level (the enclosing query)
return; return;
} }
Value v = (Value) groupData.getCurrentGroupExprData(this); Value v = (Value) groupData.getCurrentGroupExprData(this, false);
if (v == null) { if (v == null) {
groupData.setCurrentGroupExprData(this, now); groupData.setCurrentGroupExprData(this, now, false);
} else { } else {
if (!database.areEqual(now, v)) { if (!database.areEqual(now, v)) {
throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL()); throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL());
...@@ -180,7 +180,7 @@ public class ExpressionColumn extends Expression { ...@@ -180,7 +180,7 @@ public class ExpressionColumn extends Expression {
if (select != null) { if (select != null) {
SelectGroups groupData = select.getGroupDataIfCurrent(false); SelectGroups groupData = select.getGroupDataIfCurrent(false);
if (groupData != null) { if (groupData != null) {
Value v = (Value) groupData.getCurrentGroupExprData(this); Value v = (Value) groupData.getCurrentGroupExprData(this, false);
if (v != null) { if (v != null) {
return v; return v;
} }
......
...@@ -170,10 +170,14 @@ public class Aggregate extends AbstractAggregate { ...@@ -170,10 +170,14 @@ public class Aggregate extends AbstractAggregate {
/** /**
* Create a new aggregate object. * Create a new aggregate object.
* *
* @param type the aggregate type * @param type
* @param on the aggregated expression * the aggregate type
* @param select the select statement * @param on
* @param distinct if distinct is used * the aggregated expression
* @param select
* the select statement
* @param distinct
* if distinct is used
*/ */
public Aggregate(AggregateType type, Expression on, Select select, boolean distinct) { public Aggregate(AggregateType type, Expression on, Select select, boolean distinct) {
this.type = type; this.type = type;
...@@ -229,8 +233,10 @@ public class Aggregate extends AbstractAggregate { ...@@ -229,8 +233,10 @@ public class Aggregate extends AbstractAggregate {
* Get the aggregate type for this name, or -1 if no aggregate has been * Get the aggregate type for this name, or -1 if no aggregate has been
* found. * found.
* *
* @param name the aggregate function name * @param name
* @return null if no aggregate function has been found, or the aggregate type * the aggregate function name
* @return null if no aggregate function has been found, or the aggregate
* type
*/ */
public static AggregateType getAggregateType(String name) { public static AggregateType getAggregateType(String name) {
return AGGREGATES.get(name); return AGGREGATES.get(name);
...@@ -239,7 +245,8 @@ public class Aggregate extends AbstractAggregate { ...@@ -239,7 +245,8 @@ public class Aggregate extends AbstractAggregate {
/** /**
* Set the order for ARRAY_AGG() or GROUP_CONCAT() aggregate. * Set the order for ARRAY_AGG() or GROUP_CONCAT() aggregate.
* *
* @param orderByList the order by list * @param orderByList
* the order by list
*/ */
public void setOrderByList(ArrayList<SelectOrderBy> orderByList) { public void setOrderByList(ArrayList<SelectOrderBy> orderByList) {
this.orderByList = orderByList; this.orderByList = orderByList;
...@@ -248,7 +255,8 @@ public class Aggregate extends AbstractAggregate { ...@@ -248,7 +255,8 @@ public class Aggregate extends AbstractAggregate {
/** /**
* Set the separator for the GROUP_CONCAT() aggregate. * Set the separator for the GROUP_CONCAT() aggregate.
* *
* @param separator the separator expression * @param separator
* the separator expression
*/ */
public void setGroupConcatSeparator(Expression separator) { public void setGroupConcatSeparator(Expression separator) {
this.groupConcatSeparator = separator; this.groupConcatSeparator = separator;
...@@ -286,7 +294,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -286,7 +294,7 @@ public class Aggregate extends AbstractAggregate {
// if (on != null) { // if (on != null) {
// on.updateAggregate(); // on.updateAggregate();
// } // }
SelectGroups groupData = select.getGroupDataIfCurrent(true); SelectGroups groupData = select.getGroupDataIfCurrent(over != null);
if (groupData == null) { if (groupData == null) {
// this is a different level (the enclosing query) // this is a different level (the enclosing query)
return; return;
...@@ -299,6 +307,9 @@ public class Aggregate extends AbstractAggregate { ...@@ -299,6 +307,9 @@ public class Aggregate extends AbstractAggregate {
} }
lastGroupRowId = groupRowId; lastGroupRowId = groupRowId;
if (over != null) {
over.updateAggregate(session);
}
if (filterCondition != null) { if (filterCondition != null) {
if (!filterCondition.getBooleanValue(session)) { if (!filterCondition.getBooleanValue(session)) {
return; return;
...@@ -366,7 +377,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -366,7 +377,7 @@ public class Aggregate extends AbstractAggregate {
DbException.throwInternalError("type=" + type); DbException.throwInternalError("type=" + type);
} }
} }
SelectGroups groupData = select.getGroupDataIfCurrent(true); SelectGroups groupData = select.getGroupDataIfCurrent(over != null);
if (groupData == null) { if (groupData == null) {
throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL()); throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL());
} }
...@@ -381,8 +392,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -381,8 +392,7 @@ public class Aggregate extends AbstractAggregate {
sortWithOrderBy(array); sortWithOrderBy(array);
} }
StatementBuilder buff = new StatementBuilder(); StatementBuilder buff = new StatementBuilder();
String sep = groupConcatSeparator == null ? String sep = groupConcatSeparator == null ? "," : groupConcatSeparator.getValue(session).getString();
"," : groupConcatSeparator.getValue(session).getString();
for (Value val : array) { for (Value val : array) {
String s; String s;
if (val.getType() == Value.ARRAY) { if (val.getType() == Value.ARRAY) {
...@@ -431,10 +441,11 @@ public class Aggregate extends AbstractAggregate { ...@@ -431,10 +441,11 @@ public class Aggregate extends AbstractAggregate {
ValueArray key; ValueArray key;
if (over != null && (key = over.getCurrentKey(session)) != null) { if (over != null && (key = over.getCurrentKey(session)) != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ValueHashMap<AggregateData> map = (ValueHashMap<AggregateData>) groupData.getCurrentGroupExprData(this); ValueHashMap<AggregateData> map = (ValueHashMap<AggregateData>) groupData.getCurrentGroupExprData(this,
true);
if (map == null) { if (map == null) {
map = new ValueHashMap<>(); map = new ValueHashMap<>();
groupData.setCurrentGroupExprData(this, map); groupData.setCurrentGroupExprData(this, map, true);
} }
data = map.get(key); data = map.get(key);
if (data == null) { if (data == null) {
...@@ -442,10 +453,10 @@ public class Aggregate extends AbstractAggregate { ...@@ -442,10 +453,10 @@ public class Aggregate extends AbstractAggregate {
map.put(key, data); map.put(key, data);
} }
} else { } else {
data = (AggregateData) groupData.getCurrentGroupExprData(this); data = (AggregateData) groupData.getCurrentGroupExprData(this, over != null);
if (data == null) { if (data == null) {
data = AggregateData.create(type); data = AggregateData.create(type);
groupData.setCurrentGroupExprData(this, data); groupData.setCurrentGroupExprData(this, data, over != null);
} }
} }
return data; return data;
...@@ -766,8 +777,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -766,8 +777,7 @@ public class Aggregate extends AbstractAggregate {
if (on != null && !on.isEverything(visitor)) { if (on != null && !on.isEverything(visitor)) {
return false; return false;
} }
if (groupConcatSeparator != null && if (groupConcatSeparator != null && !groupConcatSeparator.isEverything(visitor)) {
!groupConcatSeparator.isEverything(visitor)) {
return false; return false;
} }
if (orderByList != null) { if (orderByList != null) {
......
...@@ -160,7 +160,7 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -160,7 +160,7 @@ public class JavaAggregate extends AbstractAggregate {
@Override @Override
public Value getValue(Session session) { public Value getValue(Session session) {
SelectGroups groupData = select.getGroupDataIfCurrent(true); SelectGroups groupData = select.getGroupDataIfCurrent(over != null);
if (groupData == null) { if (groupData == null) {
throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL()); throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL());
} }
...@@ -201,7 +201,7 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -201,7 +201,7 @@ public class JavaAggregate extends AbstractAggregate {
@Override @Override
public void updateAggregate(Session session) { public void updateAggregate(Session session) {
SelectGroups groupData = select.getGroupDataIfCurrent(true); SelectGroups groupData = select.getGroupDataIfCurrent(over != null);
if (groupData == null) { if (groupData == null) {
// this is a different level (the enclosing query) // this is a different level (the enclosing query)
return; return;
...@@ -214,6 +214,9 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -214,6 +214,9 @@ public class JavaAggregate extends AbstractAggregate {
} }
lastGroupRowId = groupRowId; lastGroupRowId = groupRowId;
if (over != null) {
over.updateAggregate(session);
}
if (filterCondition != null) { if (filterCondition != null) {
if (!filterCondition.getBooleanValue(session)) { if (!filterCondition.getBooleanValue(session)) {
return; return;
...@@ -253,13 +256,13 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -253,13 +256,13 @@ public class JavaAggregate extends AbstractAggregate {
ValueArray key; ValueArray key;
if (over != null && (key = over.getCurrentKey(session)) != null) { if (over != null && (key = over.getCurrentKey(session)) != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ValueHashMap<Aggregate> map = (ValueHashMap<Aggregate>) groupData.getCurrentGroupExprData(this); ValueHashMap<Aggregate> map = (ValueHashMap<Aggregate>) groupData.getCurrentGroupExprData(this, true);
if (map == null) { if (map == null) {
if (ifExists) { if (ifExists) {
return null; return null;
} }
map = new ValueHashMap<>(); map = new ValueHashMap<>();
groupData.setCurrentGroupExprData(this, map); groupData.setCurrentGroupExprData(this, map, true);
} }
data = map.get(key); data = map.get(key);
if (data == null) { if (data == null) {
...@@ -270,13 +273,13 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -270,13 +273,13 @@ public class JavaAggregate extends AbstractAggregate {
map.put(key, data); map.put(key, data);
} }
} else { } else {
data = (Aggregate) groupData.getCurrentGroupExprData(this); data = (Aggregate) groupData.getCurrentGroupExprData(this, over != null);
if (data == null) { if (data == null) {
if (ifExists) { if (ifExists) {
return null; return null;
} }
data = getInstance(); data = getInstance();
groupData.setCurrentGroupExprData(this, data); groupData.setCurrentGroupExprData(this, data, over != null);
} }
} }
return data; return data;
...@@ -287,14 +290,14 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -287,14 +290,14 @@ public class JavaAggregate extends AbstractAggregate {
ValueArray key; ValueArray key;
if (over != null && (key = over.getCurrentKey(session)) != null) { if (over != null && (key = over.getCurrentKey(session)) != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ValueHashMap<AggregateDataCollecting> map = ValueHashMap<AggregateDataCollecting> map = (ValueHashMap<AggregateDataCollecting>) groupData
(ValueHashMap<AggregateDataCollecting>) groupData.getCurrentGroupExprData(this); .getCurrentGroupExprData(this, true);
if (map == null) { if (map == null) {
if (ifExists) { if (ifExists) {
return null; return null;
} }
map = new ValueHashMap<>(); map = new ValueHashMap<>();
groupData.setCurrentGroupExprData(this, map); groupData.setCurrentGroupExprData(this, map, true);
} }
data = map.get(key); data = map.get(key);
if (data == null) { if (data == null) {
...@@ -305,13 +308,13 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -305,13 +308,13 @@ public class JavaAggregate extends AbstractAggregate {
map.put(key, data); map.put(key, data);
} }
} else { } else {
data = (AggregateDataCollecting) groupData.getCurrentGroupExprData(this); data = (AggregateDataCollecting) groupData.getCurrentGroupExprData(this, over != null);
if (data == null) { if (data == null) {
if (ifExists) { if (ifExists) {
return null; return null;
} }
data = new AggregateDataCollecting(); data = new AggregateDataCollecting();
groupData.setCurrentGroupExprData(this, data); groupData.setCurrentGroupExprData(this, data, over != null);
} }
} }
return data; return data;
......
...@@ -39,6 +39,7 @@ public final class Window { ...@@ -39,6 +39,7 @@ public final class Window {
* the column resolver * the column resolver
* @param level * @param level
* the subquery nesting level * the subquery nesting level
* @see Expression#mapColumns(ColumnResolver, int)
*/ */
public void mapColumns(ColumnResolver resolver, int level) { public void mapColumns(ColumnResolver resolver, int level) {
if (partitionBy != null) { if (partitionBy != null) {
...@@ -56,6 +57,7 @@ public final class Window { ...@@ -56,6 +57,7 @@ public final class Window {
* the table filter * the table filter
* @param value * @param value
* true if the table filter can return value * true if the table filter can return value
* @see Expression#setEvaluatable(TableFilter, boolean)
*/ */
public void setEvaluatable(TableFilter tableFilter, boolean value) { public void setEvaluatable(TableFilter tableFilter, boolean value) {
if (partitionBy != null) { if (partitionBy != null) {
...@@ -90,6 +92,7 @@ public final class Window { ...@@ -90,6 +92,7 @@ public final class Window {
* Returns SQL representation. * Returns SQL representation.
* *
* @return SQL representation. * @return SQL representation.
* @see Expression#getSQL()
*/ */
public String getSQL() { public String getSQL() {
if (partitionBy == null) { if (partitionBy == null) {
...@@ -105,6 +108,21 @@ public final class Window { ...@@ -105,6 +108,21 @@ public final class Window {
return builder.append(')').toString(); return builder.append(')').toString();
} }
/**
* Update an aggregate value.
*
* @param session
* the session
* @see Expression#updateAggregate(Session)
*/
public void updateAggregate(Session session) {
if (partitionBy != null) {
for (Expression expr : partitionBy) {
expr.updateAggregate(session);
}
}
}
@Override @Override
public String toString() { public String toString() {
return getSQL(); return getSQL();
......
...@@ -107,6 +107,17 @@ SELECT ARRAY_AGG(ID) OVER (PARTITION BY NAME), NAME FROM TEST; ...@@ -107,6 +107,17 @@ SELECT ARRAY_AGG(ID) OVER (PARTITION BY NAME), NAME FROM TEST;
> (4, 5, 6) c > (4, 5, 6) c
> rows: 6 > rows: 6
SELECT ARRAY_AGG(ID) FILTER (WHERE ID < 3 OR ID > 4) OVER (PARTITION BY NAME), NAME FROM TEST ORDER BY NAME;
> ARRAY_AGG(ID) FILTER (WHERE ((ID < 3) OR (ID > 4))) OVER (PARTITION BY NAME) NAME
> ---------------------------------------------------------------------------- ----
> (1, 2) a
> (1, 2) a
> null b
> (5, 6) c
> (5, 6) c
> (5, 6) c
> rows (ordered): 6
SELECT ARRAY_AGG(SUM(ID)) OVER () FROM TEST; SELECT ARRAY_AGG(SUM(ID)) OVER () FROM TEST;
> exception FEATURE_NOT_SUPPORTED_1 > exception FEATURE_NOT_SUPPORTED_1
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论