提交 356414ab authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add experimental implementation of grouped window queries

上级 8949f340
......@@ -356,29 +356,34 @@ public class Select extends Query {
}
private void queryWindow(int columnCount, LocalResult result, long offset, boolean quickOffset) {
if (isGroupQuery) {
queryGroupWindow(columnCount, result, offset, quickOffset);
return;
}
if (groupData == null) {
groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex);
}
groupData.reset();
try {
int rowNumber = 0;
setCurrentRowNumber(0);
int sampleSize = getSampleSizeValue(session);
while (topTableFilter.next()) {
setCurrentRowNumber(rowNumber + 1);
if (isConditionMet()) {
rowNumber++;
groupData.nextSource();
updateAgg(columnCount, true);
if (sampleSize > 0 && rowNumber >= sampleSize) {
break;
gatherGroup(columnCount, true);
processGroupResult(columnCount, result, offset, quickOffset);
} finally {
groupData.reset();
}
}
private void queryGroupWindow(int columnCount, LocalResult result, long offset, boolean quickOffset) {
if (groupData == null) {
groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex);
}
groupData.done();
for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) {
offset = processGroupedRow(columnCount, result, offset, quickOffset, currentGroupsKey);
groupData.reset();
try {
gatherGroup(columnCount, false);
while (groupData.next() != null) {
updateAgg(columnCount, true);
}
groupData.done();
processGroupResult(columnCount, result, offset, quickOffset);
} finally {
groupData.reset();
}
......@@ -390,6 +395,14 @@ public class Select extends Query {
}
groupData.reset();
try {
gatherGroup(columnCount, false);
processGroupResult(columnCount, result, offset, quickOffset);
} finally {
groupData.reset();
}
}
private void gatherGroup(int columnCount, boolean window) {
int rowNumber = 0;
setCurrentRowNumber(0);
int sampleSize = getSampleSizeValue(session);
......@@ -398,19 +411,13 @@ public class Select extends Query {
if (isConditionMet()) {
rowNumber++;
groupData.nextSource();
updateAgg(columnCount, false);
updateAgg(columnCount, window);
if (sampleSize > 0 && rowNumber >= sampleSize) {
break;
}
}
}
groupData.done();
for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) {
offset = processGroupedRow(columnCount, result, offset, quickOffset, currentGroupsKey);
}
} finally {
groupData.reset();
}
}
private void updateAgg(int columnCount, boolean window) {
......@@ -422,8 +429,8 @@ public class Select extends Query {
}
}
private long processGroupedRow(int columnCount, LocalResult result, long offset, boolean quickOffset,
ValueArray currentGroupsKey) {
private void processGroupResult(int columnCount, LocalResult result, long offset, boolean quickOffset) {
for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) {
Value[] keyValues = currentGroupsKey.getList();
Value[] row = new Value[columnCount];
for (int j = 0; groupIndex != null && j < groupIndex.length; j++) {
......@@ -437,15 +444,15 @@ public class Select extends Query {
row[j] = expr.getValue(session);
}
if (isHavingNullOrFalse(row)) {
return offset;
continue;
}
if (quickOffset && offset > 0) {
offset--;
return offset;
continue;
}
row = keepOnlyDistinct(row, columnCount);
result.addRow(row);
return offset;
}
}
/**
......@@ -746,7 +753,11 @@ public class Select extends Query {
if (isQuickAggregateQuery) {
queryQuick(columnCount, to, quickOffset && offset > 0);
} else if (isWindowQuery) {
if (isGroupQuery) {
queryGroupWindow(columnCount, result, offset, quickOffset);
} else {
queryWindow(columnCount, result, offset, quickOffset);
}
} else if (isGroupQuery) {
if (isGroupSortedQuery) {
lazyResult = queryGroupSorted(columnCount, to, offset, quickOffset);
......@@ -943,10 +954,6 @@ public class Select extends Query {
throw DbException.get(ErrorCode.WITH_TIES_WITHOUT_ORDER_BY);
}
if (isWindowQuery && isGroupQuery) {
throw DbException.getUnsupportedException("Window functions in group query are not currently supported.");
}
Database db = session.getDatabase();
// first the select list (visible columns),
......@@ -1437,6 +1444,24 @@ public class Select extends Query {
return isQuickAggregateQuery;
}
/**
* Checks if this query is a group query.
*
* @return whether this query is a group query.
*/
public boolean isGroupQuery() {
return isGroupQuery;
}
/**
* Checks if this query contains window functions.
*
* @return whether this query contains window functions
*/
public boolean isWindowQuery() {
return isWindowQuery;
}
@Override
public void addGlobalCondition(Parameter param, int columnId,
int comparisonType) {
......
......@@ -127,6 +127,7 @@ public abstract class SelectGroups {
if (cursor.hasNext()) {
Map.Entry<ValueArray, Object[]> entry = cursor.next();
currentGroupByExprData = entry.getValue();
currentGroupRowId++;
return entry.getKey();
}
return null;
......
......@@ -291,6 +291,15 @@ public class Aggregate extends AbstractAggregate {
@Override
public void updateAggregate(Session session, boolean window) {
if (window != (over != null)) {
if (!window && select.isWindowQuery()) {
if (on != null) {
on.updateAggregate(session, false);
}
if (filterCondition != null) {
filterCondition.updateAggregate(session, false);
}
over.updateAggregate(session, false);
}
return;
}
// TODO aggregates: check nested MIN(MAX(ID)) and so on
......@@ -311,8 +320,10 @@ public class Aggregate extends AbstractAggregate {
lastGroupRowId = groupRowId;
if (over != null) {
if (!select.isGroupQuery()) {
over.updateAggregate(session, true);
}
}
if (filterCondition != null) {
if (!filterCondition.getBooleanValue(session)) {
return;
......
......@@ -119,10 +119,44 @@ SELECT ARRAY_AGG(ID) FILTER (WHERE ID < 3 OR ID > 4) OVER (PARTITION BY NAME), N
> rows (ordered): 6
SELECT ARRAY_AGG(SUM(ID)) OVER () FROM TEST;
> exception FEATURE_NOT_SUPPORTED_1
> ARRAY_AGG(SUM(ID)) OVER ()
> --------------------------
> (21)
> rows: 1
SELECT ARRAY_AGG(ID) OVER() FROM TEST GROUP BY ID;
> exception FEATURE_NOT_SUPPORTED_1
> ARRAY_AGG(ID) OVER ()
> ---------------------
> (1, 2, 3, 4, 5, 6)
> (1, 2, 3, 4, 5, 6)
> (1, 2, 3, 4, 5, 6)
> (1, 2, 3, 4, 5, 6)
> (1, 2, 3, 4, 5, 6)
> (1, 2, 3, 4, 5, 6)
> rows: 6
SELECT ARRAY_AGG(NAME) OVER(PARTITION BY NAME) FROM TEST GROUP BY NAME;
> ARRAY_AGG(NAME) OVER (PARTITION BY NAME)
> ----------------------------------------
> (a)
> (b)
> (c)
> rows: 3
SELECT ARRAY_AGG(ARRAY_AGG(ID)) OVER (PARTITION BY NAME), NAME FROM TEST GROUP BY NAME;
> ARRAY_AGG(ARRAY_AGG(ID)) OVER (PARTITION BY NAME) NAME
> ------------------------------------------------- ----
> ((1, 2)) a
> ((3)) b
> ((4, 5, 6)) c
> rows: 3
SELECT ARRAY_AGG(ARRAY_AGG(ID)) OVER (PARTITION BY NAME), NAME FROM TEST GROUP BY NAME OFFSET 1 ROW;
> ARRAY_AGG(ARRAY_AGG(ID)) OVER (PARTITION BY NAME) NAME
> ------------------------------------------------- ----
> ((3)) b
> ((4, 5, 6)) c
> rows: 2
DROP TABLE TEST;
> ok
......@@ -40,3 +40,11 @@ select sum(v) from test;
drop table test;
> ok
SELECT X, COUNT(*), SUM(COUNT(*)) OVER() FROM VALUES (1), (1), (1), (1), (2), (2), (3) T(X) GROUP BY X;
> X COUNT(*) SUM(COUNT(*)) OVER ()
> - -------- ---------------------
> 1 4 7
> 2 2 7
> 3 1 7
> rows: 3
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论