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

Merge pull request #1462 from katzyn/window

Separate aggregate and window code in some places
...@@ -256,7 +256,12 @@ ${item.example}</p> ...@@ -256,7 +256,12 @@ ${item.example}</p>
<c:forEach var="item" items="otherGrammar"> <c:forEach var="item" items="otherGrammar">
<h3 id="${item.link}" class="notranslate" onclick="switchBnf(this)">${item.topic}</h3> <h3 id="${item.link}" class="notranslate" onclick="switchBnf(this)">${item.topic}</h3>
<!-- railroad-start --> <!-- railroad-start -->
<pre name="bnf" style="display: none">
${item.syntax}
</pre>
<div name="railroad">
${item.railroad} ${item.railroad}
</div>
<!-- railroad-end --> <!-- railroad-end -->
<!-- syntax-start <!-- syntax-start
<pre> <pre>
......
...@@ -171,6 +171,7 @@ import org.h2.expression.UnaryOperation; ...@@ -171,6 +171,7 @@ import org.h2.expression.UnaryOperation;
import org.h2.expression.ValueExpression; import org.h2.expression.ValueExpression;
import org.h2.expression.Variable; import org.h2.expression.Variable;
import org.h2.expression.Wildcard; import org.h2.expression.Wildcard;
import org.h2.expression.aggregate.DataAnalysisOperation;
import org.h2.expression.aggregate.AbstractAggregate; import org.h2.expression.aggregate.AbstractAggregate;
import org.h2.expression.aggregate.Aggregate; import org.h2.expression.aggregate.Aggregate;
import org.h2.expression.aggregate.Aggregate.AggregateType; import org.h2.expression.aggregate.Aggregate.AggregateType;
...@@ -3053,23 +3054,24 @@ public class Parser { ...@@ -3053,23 +3054,24 @@ public class Parser {
} }
private void readFilterAndOver(AbstractAggregate aggregate) { private void readFilterAndOver(AbstractAggregate aggregate) {
boolean isAggregate = aggregate.isAggregate(); if (readIf("FILTER")) {
if (isAggregate && readIf("FILTER")) {
read(OPEN_PAREN); read(OPEN_PAREN);
read(WHERE); read(WHERE);
Expression filterCondition = readExpression(); Expression filterCondition = readExpression();
read(CLOSE_PAREN); read(CLOSE_PAREN);
aggregate.setFilterCondition(filterCondition); aggregate.setFilterCondition(filterCondition);
} }
Window over = null; readOver(aggregate);
}
private void readOver(DataAnalysisOperation operation) {
if (readIf("OVER")) { if (readIf("OVER")) {
over = readWindowNameOrSpecification(); operation.setOverCondition(readWindowNameOrSpecification());
aggregate.setOverCondition(over);
currentSelect.setWindowQuery(); currentSelect.setWindowQuery();
} else if (!isAggregate) { } else if (operation.isAggregate()) {
throw getSyntaxError();
} else {
currentSelect.setGroupQuery(); currentSelect.setGroupQuery();
} else {
throw getSyntaxError();
} }
} }
...@@ -3440,7 +3442,7 @@ public class Parser { ...@@ -3440,7 +3442,7 @@ public class Parser {
default: default:
// Avoid warning // Avoid warning
} }
readFilterAndOver(function); readOver(function);
return function; return function;
} }
......
...@@ -14,6 +14,7 @@ import java.util.Map.Entry; ...@@ -14,6 +14,7 @@ import java.util.Map.Entry;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.expression.aggregate.DataAnalysisOperation;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -210,7 +211,7 @@ public abstract class SelectGroups { ...@@ -210,7 +211,7 @@ public abstract class SelectGroups {
/** /**
* Maps an expression object to its data. * Maps an expression object to its data.
*/ */
private final HashMap<Expression, Object> windowData = new HashMap<>(); private final HashMap<DataAnalysisOperation, Object> windowData = new HashMap<>();
/** /**
* The id of the current group. * The id of the current group.
...@@ -251,14 +252,9 @@ public abstract class SelectGroups { ...@@ -251,14 +252,9 @@ public abstract class SelectGroups {
* *
* @param expr * @param expr
* expression * expression
* @param window
* true if expression is a window expression
* @return expression data or null * @return expression data or null
*/ */
public Object getCurrentGroupExprData(Expression expr, boolean window) { public final Object getCurrentGroupExprData(Expression expr) {
if (window) {
return windowData.get(expr);
}
Integer index = exprToIndexInGroupByData.get(expr); Integer index = exprToIndexInGroupByData.get(expr);
if (index == null) { if (index == null) {
return null; return null;
...@@ -273,15 +269,8 @@ public abstract class SelectGroups { ...@@ -273,15 +269,8 @@ public abstract class SelectGroups {
* expression * expression
* @param object * @param object
* expression data to set * expression data to set
* @param window
* true if expression is a window expression
*/ */
public void setCurrentGroupExprData(Expression expr, Object obj, boolean window) { public final void setCurrentGroupExprData(Expression expr, Object obj) {
if (window) {
Object old = windowData.put(expr, obj);
assert old == null;
return;
}
Integer index = exprToIndexInGroupByData.get(expr); Integer index = exprToIndexInGroupByData.get(expr);
if (index != null) { if (index != null) {
assert currentGroupByExprData[index] == null; assert currentGroupByExprData[index] == null;
...@@ -297,6 +286,30 @@ public abstract class SelectGroups { ...@@ -297,6 +286,30 @@ public abstract class SelectGroups {
currentGroupByExprData[index] = obj; currentGroupByExprData[index] = obj;
} }
/**
* Get the window data for the specified expression.
*
* @param expr
* expression
* @return expression data or null
*/
public final Object getWindowExprData(DataAnalysisOperation expr) {
return windowData.get(expr);
}
/**
* Set the window data for the specified expression.
*
* @param expr
* expression
* @param object
* expression data to set
*/
public final void setWindowExprData(DataAnalysisOperation expr, Object obj) {
Object old = windowData.put(expr, obj);
assert old == null;
}
abstract void updateCurrentGroupExprData(); abstract void updateCurrentGroupExprData();
/** /**
......
...@@ -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, false); Value v = (Value) groupData.getCurrentGroupExprData(this);
if (v == null) { if (v == null) {
groupData.setCurrentGroupExprData(this, now, false); groupData.setCurrentGroupExprData(this, now);
} 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, false); Value v = (Value) groupData.getCurrentGroupExprData(this);
if (v != null) { if (v != null) {
return v; return v;
} }
......
...@@ -251,11 +251,6 @@ public class Aggregate extends AbstractAggregate { ...@@ -251,11 +251,6 @@ public class Aggregate extends AbstractAggregate {
return AGGREGATES.get(name); return AGGREGATES.get(name);
} }
@Override
public boolean isAggregate() {
return true;
}
/** /**
* Set the order for ARRAY_AGG() or GROUP_CONCAT() aggregate. * Set the order for ARRAY_AGG() or GROUP_CONCAT() aggregate.
* *
...@@ -312,6 +307,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -312,6 +307,7 @@ 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);
if (on != null) { if (on != null) {
on.updateAggregate(session, stage); on.updateAggregate(session, stage);
} }
...@@ -514,9 +510,6 @@ public class Aggregate extends AbstractAggregate { ...@@ -514,9 +510,6 @@ public class Aggregate extends AbstractAggregate {
if (groupConcatSeparator != null) { if (groupConcatSeparator != null) {
groupConcatSeparator = groupConcatSeparator.optimize(session); groupConcatSeparator = groupConcatSeparator.optimize(session);
} }
if (filterCondition != null) {
filterCondition = filterCondition.optimize(session);
}
switch (type) { switch (type) {
case GROUP_CONCAT: case GROUP_CONCAT:
dataType = Value.STRING; dataType = Value.STRING;
......
...@@ -40,11 +40,6 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -40,11 +40,6 @@ public class JavaAggregate extends AbstractAggregate {
this.args = args; this.args = args;
} }
@Override
public boolean isAggregate() {
return true;
}
@Override @Override
public int getCost() { public int getCost() {
int cost = 5; int cost = 5;
...@@ -140,9 +135,6 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -140,9 +135,6 @@ public class JavaAggregate extends AbstractAggregate {
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} }
if (filterCondition != null) {
filterCondition = filterCondition.optimize(session);
}
return this; return this;
} }
...@@ -237,6 +229,7 @@ public class JavaAggregate extends AbstractAggregate { ...@@ -237,6 +229,7 @@ public class JavaAggregate extends AbstractAggregate {
@Override @Override
protected void updateGroupAggregates(Session session, int stage) { protected void updateGroupAggregates(Session session, int stage) {
super.updateGroupAggregates(session, stage);
for (Expression expr : args) { for (Expression expr : args) {
expr.updateAggregate(session, stage); expr.updateAggregate(session, stage);
} }
......
...@@ -10,6 +10,7 @@ import java.util.HashMap; ...@@ -10,6 +10,7 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import org.h2.command.dml.Select; import org.h2.command.dml.Select;
import org.h2.command.dml.SelectGroups;
import org.h2.command.dml.SelectOrderBy; import org.h2.command.dml.SelectOrderBy;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
...@@ -24,7 +25,7 @@ import org.h2.value.ValueNull; ...@@ -24,7 +25,7 @@ import org.h2.value.ValueNull;
/** /**
* A window function. * A window function.
*/ */
public class WindowFunction extends AbstractAggregate { public class WindowFunction extends DataAnalysisOperation {
private final WindowFunctionType type; private final WindowFunctionType type;
...@@ -105,7 +106,7 @@ public class WindowFunction extends AbstractAggregate { ...@@ -105,7 +106,7 @@ public class WindowFunction extends AbstractAggregate {
* arguments, or null * arguments, or null
*/ */
public WindowFunction(WindowFunctionType type, Select select, Expression[] args) { public WindowFunction(WindowFunctionType type, Select select, Expression[] args) {
super(select, false); super(select);
this.type = type; this.type = type;
this.args = args; this.args = args;
} }
...@@ -145,12 +146,13 @@ public class WindowFunction extends AbstractAggregate { ...@@ -145,12 +146,13 @@ public class WindowFunction extends AbstractAggregate {
} }
@Override @Override
protected void updateAggregate(Session session, Object aggregateData) { protected void updateAggregate(Session session, SelectGroups groupData, int groupRowId) {
throw DbException.getUnsupportedException("Window function"); updateOrderedAggregate(session, groupData, groupRowId, over.getOrderBy());
} }
@Override @Override
protected void updateGroupAggregates(Session session, int stage) { protected void updateGroupAggregates(Session session, int stage) {
super.updateGroupAggregates(session, stage);
if (args != null) { if (args != null) {
for (Expression expr : args) { for (Expression expr : args) {
expr.updateAggregate(session, stage); expr.updateAggregate(session, stage);
......
...@@ -449,9 +449,10 @@ public class TransactionStore { ...@@ -449,9 +449,10 @@ public class TransactionStore {
if (map != null) { // might be null if map was removed later if (map != null) { // might be null if map was removed later
Object key = op[1]; Object key = op[1];
commitDecisionMaker.setUndoKey(undoKey); commitDecisionMaker.setUndoKey(undoKey);
// although second parameter (value) is not really used // although second parameter (value) is not really
// by CommitDecisionMaker, MVRTreeMap has weird traversal logic based on it, // used by CommitDecisionMaker, MVRTreeMap has weird
// and any non-null value will do, to signify update, not removal // traversal logic based on it, and any non-null
// value will do, to signify update, not removal
map.operate(key, VersionedValue.DUMMY, commitDecisionMaker); map.operate(key, VersionedValue.DUMMY, commitDecisionMaker);
} }
} }
......
...@@ -796,4 +796,4 @@ interior envelopes multilinestring multipoint packed exterior normalization awkw ...@@ -796,4 +796,4 @@ interior envelopes multilinestring multipoint packed exterior normalization awkw
xym normalizes coord setz xyzm geometrycollection multipolygon mixup rings polygons rejection finite xym normalizes coord setz xyzm geometrycollection multipolygon mixup rings polygons rejection finite
pointzm pointz pointm dimensionality redefine forum measures pointzm pointz pointm dimensionality redefine forum measures
mpg casted pzm mls constrained subtypes complains mpg casted pzm mls constrained subtypes complains
ranks rno dro rko precede cume reopens preceding unbounded rightly itr lag maximal tiles tile ntile ranks rno dro rko precede cume reopens preceding unbounded rightly itr lag maximal tiles tile ntile signify
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论