提交 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 { ...@@ -356,29 +356,34 @@ 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 (isGroupQuery) {
queryGroupWindow(columnCount, result, offset, quickOffset);
return;
}
if (groupData == null) { if (groupData == null) {
groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex); groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex);
} }
groupData.reset(); groupData.reset();
try { try {
int rowNumber = 0; gatherGroup(columnCount, true);
setCurrentRowNumber(0); processGroupResult(columnCount, result, offset, quickOffset);
int sampleSize = getSampleSizeValue(session); } finally {
while (topTableFilter.next()) { groupData.reset();
setCurrentRowNumber(rowNumber + 1); }
if (isConditionMet()) { }
rowNumber++;
groupData.nextSource(); private void queryGroupWindow(int columnCount, LocalResult result, long offset, boolean quickOffset) {
updateAgg(columnCount, true); if (groupData == null) {
if (sampleSize > 0 && rowNumber >= sampleSize) { groupData = SelectGroups.getInstance(session, expressions, isGroupQuery, groupIndex);
break; }
} groupData.reset();
} try {
gatherGroup(columnCount, false);
while (groupData.next() != null) {
updateAgg(columnCount, true);
} }
groupData.done(); groupData.done();
for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) { processGroupResult(columnCount, result, offset, quickOffset);
offset = processGroupedRow(columnCount, result, offset, quickOffset, currentGroupsKey);
}
} finally { } finally {
groupData.reset(); groupData.reset();
} }
...@@ -390,29 +395,31 @@ public class Select extends Query { ...@@ -390,29 +395,31 @@ public class Select extends Query {
} }
groupData.reset(); groupData.reset();
try { try {
int rowNumber = 0; gatherGroup(columnCount, false);
setCurrentRowNumber(0); processGroupResult(columnCount, result, offset, quickOffset);
int sampleSize = getSampleSizeValue(session);
while (topTableFilter.next()) {
setCurrentRowNumber(rowNumber + 1);
if (isConditionMet()) {
rowNumber++;
groupData.nextSource();
updateAgg(columnCount, false);
if (sampleSize > 0 && rowNumber >= sampleSize) {
break;
}
}
}
groupData.done();
for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) {
offset = processGroupedRow(columnCount, result, offset, quickOffset, currentGroupsKey);
}
} finally { } finally {
groupData.reset(); groupData.reset();
} }
} }
private void gatherGroup(int columnCount, boolean window) {
int rowNumber = 0;
setCurrentRowNumber(0);
int sampleSize = getSampleSizeValue(session);
while (topTableFilter.next()) {
setCurrentRowNumber(rowNumber + 1);
if (isConditionMet()) {
rowNumber++;
groupData.nextSource();
updateAgg(columnCount, window);
if (sampleSize > 0 && rowNumber >= sampleSize) {
break;
}
}
}
groupData.done();
}
private void updateAgg(int columnCount, boolean window) { private void updateAgg(int columnCount, boolean window) {
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
if (groupByExpression == null || !groupByExpression[i]) { if (groupByExpression == null || !groupByExpression[i]) {
...@@ -422,30 +429,30 @@ public class Select extends Query { ...@@ -422,30 +429,30 @@ public class Select extends Query {
} }
} }
private long processGroupedRow(int columnCount, LocalResult result, long offset, boolean quickOffset, private void processGroupResult(int columnCount, LocalResult result, long offset, boolean quickOffset) {
ValueArray currentGroupsKey) { for (ValueArray currentGroupsKey; (currentGroupsKey = groupData.next()) != null;) {
Value[] keyValues = currentGroupsKey.getList(); Value[] keyValues = currentGroupsKey.getList();
Value[] row = new Value[columnCount]; Value[] row = new Value[columnCount];
for (int j = 0; groupIndex != null && j < groupIndex.length; j++) { for (int j = 0; groupIndex != null && j < groupIndex.length; j++) {
row[groupIndex[j]] = keyValues[j]; row[groupIndex[j]] = keyValues[j];
} }
for (int j = 0; j < columnCount; j++) { for (int j = 0; j < columnCount; j++) {
if (groupByExpression != null && groupByExpression[j]) { if (groupByExpression != null && groupByExpression[j]) {
continue;
}
Expression expr = expressions.get(j);
row[j] = expr.getValue(session);
}
if (isHavingNullOrFalse(row)) {
continue; continue;
} }
Expression expr = expressions.get(j); if (quickOffset && offset > 0) {
row[j] = expr.getValue(session); offset--;
} continue;
if (isHavingNullOrFalse(row)) { }
return offset; row = keepOnlyDistinct(row, columnCount);
} result.addRow(row);
if (quickOffset && offset > 0) {
offset--;
return offset;
} }
row = keepOnlyDistinct(row, columnCount);
result.addRow(row);
return offset;
} }
/** /**
...@@ -746,7 +753,11 @@ public class Select extends Query { ...@@ -746,7 +753,11 @@ public class Select extends Query {
if (isQuickAggregateQuery) { if (isQuickAggregateQuery) {
queryQuick(columnCount, to, quickOffset && offset > 0); queryQuick(columnCount, to, quickOffset && offset > 0);
} else if (isWindowQuery) { } else if (isWindowQuery) {
queryWindow(columnCount, result, offset, quickOffset); if (isGroupQuery) {
queryGroupWindow(columnCount, result, offset, quickOffset);
} else {
queryWindow(columnCount, result, offset, quickOffset);
}
} else if (isGroupQuery) { } else if (isGroupQuery) {
if (isGroupSortedQuery) { if (isGroupSortedQuery) {
lazyResult = queryGroupSorted(columnCount, to, offset, quickOffset); lazyResult = queryGroupSorted(columnCount, to, offset, quickOffset);
...@@ -943,10 +954,6 @@ public class Select extends Query { ...@@ -943,10 +954,6 @@ public class Select extends Query {
throw DbException.get(ErrorCode.WITH_TIES_WITHOUT_ORDER_BY); 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(); Database db = session.getDatabase();
// first the select list (visible columns), // first the select list (visible columns),
...@@ -1437,6 +1444,24 @@ public class Select extends Query { ...@@ -1437,6 +1444,24 @@ public class Select extends Query {
return isQuickAggregateQuery; 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 @Override
public void addGlobalCondition(Parameter param, int columnId, public void addGlobalCondition(Parameter param, int columnId,
int comparisonType) { int comparisonType) {
......
...@@ -127,6 +127,7 @@ public abstract class SelectGroups { ...@@ -127,6 +127,7 @@ public abstract class SelectGroups {
if (cursor.hasNext()) { if (cursor.hasNext()) {
Map.Entry<ValueArray, Object[]> entry = cursor.next(); Map.Entry<ValueArray, Object[]> entry = cursor.next();
currentGroupByExprData = entry.getValue(); currentGroupByExprData = entry.getValue();
currentGroupRowId++;
return entry.getKey(); return entry.getKey();
} }
return null; return null;
......
...@@ -291,6 +291,15 @@ public class Aggregate extends AbstractAggregate { ...@@ -291,6 +291,15 @@ public class Aggregate extends AbstractAggregate {
@Override @Override
public void updateAggregate(Session session, boolean window) { public void updateAggregate(Session session, boolean window) {
if (window != (over != null)) { 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; return;
} }
// TODO aggregates: check nested MIN(MAX(ID)) and so on // TODO aggregates: check nested MIN(MAX(ID)) and so on
...@@ -311,7 +320,9 @@ public class Aggregate extends AbstractAggregate { ...@@ -311,7 +320,9 @@ public class Aggregate extends AbstractAggregate {
lastGroupRowId = groupRowId; lastGroupRowId = groupRowId;
if (over != null) { if (over != null) {
over.updateAggregate(session, true); if (!select.isGroupQuery()) {
over.updateAggregate(session, true);
}
} }
if (filterCondition != null) { if (filterCondition != null) {
if (!filterCondition.getBooleanValue(session)) { if (!filterCondition.getBooleanValue(session)) {
......
...@@ -119,10 +119,44 @@ SELECT ARRAY_AGG(ID) FILTER (WHERE ID < 3 OR ID > 4) OVER (PARTITION BY NAME), N ...@@ -119,10 +119,44 @@ SELECT ARRAY_AGG(ID) FILTER (WHERE ID < 3 OR ID > 4) OVER (PARTITION BY NAME), N
> rows (ordered): 6 > rows (ordered): 6
SELECT ARRAY_AGG(SUM(ID)) OVER () FROM TEST; 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; 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; DROP TABLE TEST;
> ok > ok
...@@ -40,3 +40,11 @@ select sum(v) from test; ...@@ -40,3 +40,11 @@ select sum(v) from test;
drop table test; drop table test;
> ok > 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论