提交 dcc0ecbc authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Use separate maps for partitioned and not partitioned window functions

上级 73f31b32
...@@ -15,6 +15,8 @@ import java.util.Map.Entry; ...@@ -15,6 +15,8 @@ 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.expression.aggregate.DataAnalysisOperation;
import org.h2.expression.aggregate.PartitionData;
import org.h2.util.ValueHashMap;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -209,9 +211,14 @@ public abstract class SelectGroups { ...@@ -209,9 +211,14 @@ public abstract class SelectGroups {
final HashMap<Expression, Integer> exprToIndexInGroupByData = new HashMap<>(); final HashMap<Expression, Integer> exprToIndexInGroupByData = new HashMap<>();
/** /**
* Maps an expression object to its data. * Maps an window expression object to its data.
*/ */
private final HashMap<DataAnalysisOperation, Object> windowData = new HashMap<>(); private final HashMap<DataAnalysisOperation, PartitionData> windowData = new HashMap<>();
/**
* Maps an partitioned window expression object to its data.
*/
private final HashMap<DataAnalysisOperation, ValueHashMap<PartitionData>> windowPartitionData = new HashMap<>();
/** /**
* The id of the current group. * The id of the current group.
...@@ -291,10 +298,17 @@ public abstract class SelectGroups { ...@@ -291,10 +298,17 @@ public abstract class SelectGroups {
* *
* @param expr * @param expr
* expression * expression
* @param partitionKey
* a key of partition
* @return expression data or null * @return expression data or null
*/ */
public final Object getWindowExprData(DataAnalysisOperation expr) { public final PartitionData getWindowExprData(DataAnalysisOperation expr, ValueArray partitionKey) {
if (partitionKey == null) {
return windowData.get(expr); return windowData.get(expr);
} else {
ValueHashMap<PartitionData> map = windowPartitionData.get(expr);
return map != null ? map.get(partitionKey) : null;
}
} }
/** /**
...@@ -302,12 +316,23 @@ public abstract class SelectGroups { ...@@ -302,12 +316,23 @@ public abstract class SelectGroups {
* *
* @param expr * @param expr
* expression * expression
* @param partitionKey
* a key of partition
* @param object * @param object
* expression data to set * window expression data to set
*/ */
public final void setWindowExprData(DataAnalysisOperation expr, Object obj) { public final void setWindowExprData(DataAnalysisOperation expr, ValueArray partitionKey, PartitionData obj) {
if (partitionKey == null) {
Object old = windowData.put(expr, obj); Object old = windowData.put(expr, obj);
assert old == null; assert old == null;
} else {
ValueHashMap<PartitionData> map = windowPartitionData.get(expr);
if (map == null) {
map = new ValueHashMap<>();
windowPartitionData.put(expr, map);
}
map.put(partitionKey, obj);
}
} }
abstract void updateCurrentGroupExprData(); abstract void updateCurrentGroupExprData();
...@@ -329,6 +354,7 @@ public abstract class SelectGroups { ...@@ -329,6 +354,7 @@ public abstract class SelectGroups {
currentGroupByExprData = null; currentGroupByExprData = null;
exprToIndexInGroupByData.clear(); exprToIndexInGroupByData.clear();
windowData.clear(); windowData.clear();
windowPartitionData.clear();
currentGroupRowId = 0; currentGroupRowId = 0;
} }
......
...@@ -20,7 +20,6 @@ import org.h2.message.DbException; ...@@ -20,7 +20,6 @@ import org.h2.message.DbException;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.ValueHashMap;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
...@@ -187,38 +186,16 @@ public abstract class DataAnalysisOperation extends Expression { ...@@ -187,38 +186,16 @@ public abstract class DataAnalysisOperation extends Expression {
Object data; Object data;
if (over != null) { if (over != null) {
ValueArray key = over.getCurrentKey(session); ValueArray key = over.getCurrentKey(session);
if (key != null) { PartitionData partition = groupData.getWindowExprData(this, key);
@SuppressWarnings("unchecked")
ValueHashMap<Object> map = (ValueHashMap<Object>) groupData.getWindowExprData(this);
if (map == null) {
if (ifExists) {
return null;
}
map = new ValueHashMap<>();
groupData.setWindowExprData(this, map);
}
PartitionData partition = (PartitionData) map.get(key);
if (partition == null) { if (partition == null) {
if (ifExists) { if (ifExists) {
return null; return null;
} }
data = forOrderBy ? new ArrayList<>() : createAggregateData(); data = forOrderBy ? new ArrayList<>() : createAggregateData();
map.put(key, new PartitionData(data)); groupData.setWindowExprData(this, key, new PartitionData(data));
} else { } else {
data = partition.getData(); data = partition.getData();
} }
} else {
PartitionData partition = (PartitionData) groupData.getWindowExprData(this);
if (partition == null) {
if (ifExists) {
return null;
}
data = forOrderBy ? new ArrayList<>() : createAggregateData();
groupData.setWindowExprData(this, new PartitionData(data));
} else {
data = partition.getData();
}
}
} else { } else {
data = groupData.getCurrentGroupExprData(this); data = groupData.getCurrentGroupExprData(this);
if (data == null) { if (data == null) {
...@@ -273,31 +250,14 @@ public abstract class DataAnalysisOperation extends Expression { ...@@ -273,31 +250,14 @@ public abstract class DataAnalysisOperation extends Expression {
Object data; Object data;
boolean forOrderBy = over.getOrderBy() != null; boolean forOrderBy = over.getOrderBy() != null;
ValueArray key = over.getCurrentKey(session); ValueArray key = over.getCurrentKey(session);
if (key != null) { partition = groupData.getWindowExprData(this, key);
@SuppressWarnings("unchecked")
ValueHashMap<Object> map = (ValueHashMap<Object>) groupData.getWindowExprData(this);
if (map == null) {
map = new ValueHashMap<>();
groupData.setWindowExprData(this, map);
}
partition = (PartitionData) map.get(key);
if (partition == null) {
data = forOrderBy ? new ArrayList<>() : createAggregateData();
partition = new PartitionData(data);
map.put(key, partition);
} else {
data = partition.getData();
}
} else {
partition = (PartitionData) groupData.getWindowExprData(this);
if (partition == null) { if (partition == null) {
data = forOrderBy ? new ArrayList<>() : createAggregateData(); data = forOrderBy ? new ArrayList<>() : createAggregateData();
partition = new PartitionData(data); partition = new PartitionData(data);
groupData.setWindowExprData(this, partition); groupData.setWindowExprData(this, key, partition);
} else { } else {
data = partition.getData(); data = partition.getData();
} }
}
if (over.getOrderBy() != null || !isAggregate()) { if (over.getOrderBy() != null || !isAggregate()) {
return getOrderedResult(session, groupData, partition, data); return getOrderedResult(session, groupData, partition, data);
} }
......
...@@ -12,7 +12,7 @@ import org.h2.value.Value; ...@@ -12,7 +12,7 @@ import org.h2.value.Value;
/** /**
* Partition data of a window aggregate. * Partition data of a window aggregate.
*/ */
final class PartitionData { public final class PartitionData {
/** /**
* Aggregate data. * Aggregate data.
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论