提交 85f6c774 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix GROUP BY with two identical columns in selected expressions

上级 44d2f6cd
......@@ -108,6 +108,9 @@ public class Select extends Query {
SelectGroups groupData;
private int havingIndex;
private int[] groupByCopies;
boolean isGroupQuery;
private boolean isGroupSortedQuery;
private boolean isWindowQuery;
......@@ -462,7 +465,8 @@ public class Select extends Query {
void updateAgg(int columnCount, int stage) {
for (int i = 0; i < columnCount; i++) {
if (groupByExpression == null || !groupByExpression[i]) {
if ((groupByExpression == null || !groupByExpression[i])
&& (groupByCopies == null || groupByCopies[i] < 0)) {
Expression expr = expressions.get(i);
expr.updateAggregate(session, stage);
}
......@@ -480,6 +484,13 @@ public class Select extends Query {
if (groupByExpression != null && groupByExpression[j]) {
continue;
}
if (groupByCopies != null) {
int original = groupByCopies[j];
if (original >= 0) {
row[j] = row[original];
continue;
}
}
Expression expr = expressions.get(j);
row[j] = expr.getValue(session);
}
......@@ -1047,7 +1058,7 @@ public class Select extends Query {
for (int j = 0; j < expSize; j++) {
String s2 = expressionSQL.get(j);
if (db.equalsIdentifiers(s2, sql)) {
found = j;
found = mergeGroupByExpressions(db, j, expressionSQL, false);
break;
}
}
......@@ -1056,12 +1067,12 @@ public class Select extends Query {
for (int j = 0; j < expSize; j++) {
Expression e = expressions.get(j);
if (db.equalsIdentifiers(sql, e.getAlias())) {
found = j;
found = mergeGroupByExpressions(db, j, expressionSQL, true);
break;
}
sql = expr.getAlias();
if (db.equalsIdentifiers(sql, e.getAlias())) {
found = j;
found = mergeGroupByExpressions(db, j, expressionSQL, true);
break;
}
}
......@@ -1074,6 +1085,14 @@ public class Select extends Query {
groupIndex[i] = found;
}
}
checkUsed: if (groupByCopies != null) {
for (int i : groupByCopies) {
if (i >= 0) {
break checkUsed;
}
}
groupByCopies = null;
}
groupByExpression = new boolean[expressions.size()];
for (int gi : groupIndex) {
groupByExpression[gi] = true;
......@@ -1092,6 +1111,50 @@ public class Select extends Query {
checkInit = true;
}
private int mergeGroupByExpressions(Database db, int index, ArrayList<String> expressionSQL, boolean scanPrevious)
{
/*
* -1: uniqueness of expression is not known yet
*
* -2: expression that is used as a source for a copy or does not have
* copies
*
* >=0: expression is a copy of expression at this index
*/
if (groupByCopies != null) {
int c = groupByCopies[index];
if (c >= 0) {
return c;
} else if (c == -2) {
return index;
}
} else {
groupByCopies = new int[expressionSQL.size()];
Arrays.fill(groupByCopies, -1);
}
String sql = expressionSQL.get(index);
if (scanPrevious) {
/*
* If expression was matched using an alias previous expressions may
* be identical.
*/
for (int i = 0; i < index; i++) {
if (db.equalsIdentifiers(sql, expressionSQL.get(i))) {
index = i;
break;
}
}
}
int l = expressionSQL.size();
for (int i = index + 1; i < l; i++) {
if (db.equalsIdentifiers(sql, expressionSQL.get(i))) {
groupByCopies[i] = index;
}
}
groupByCopies[index] = -2;
return index;
}
@Override
public void prepare() {
if (isPrepared) {
......
......@@ -466,3 +466,46 @@ DROP TABLE TEST;
SELECT 1 = ALL (SELECT * FROM VALUES (NULL), (1), (2), (NULL) ORDER BY 1);
>> FALSE
CREATE TABLE TEST(G INT, V INT);
> ok
INSERT INTO TEST VALUES (10, 1), (11, 2), (20, 4);
> update count: 3
SELECT G / 10 G1, G / 10 G2, SUM(T.V) S FROM TEST T GROUP BY G / 10, G / 10;
> G1 G2 S
> -- -- -
> 1 1 3
> 2 2 4
> rows: 2
SELECT G / 10 G1, G / 10 G2, SUM(T.V) S FROM TEST T GROUP BY G2;
> G1 G2 S
> -- -- -
> 1 1 3
> 2 2 4
> rows: 2
DROP TABLE TEST;
> ok
@reconnect off
CALL RAND(0);
>> 0.730967787376657
SELECT RAND(), RAND() + 1, RAND() + 1, RAND() GROUP BY RAND() + 1;
> RAND() RAND() + 1 RAND() + 1 RAND()
> ------------------ ------------------ ------------------ ------------------
> 0.6374174253501083 1.2405364156714858 1.2405364156714858 0.5504370051176339
> rows: 1
SELECT RAND() A, RAND() + 1 B, RAND() + 1 C, RAND() D, RAND() + 2 E, RAND() + 3 F GROUP BY B, C, E, F;
> A B C D E F
> ------------------ ------------------ ------------------ ------------------ ------------------ ------------------
> 0.8791825178724801 1.3332183994766498 1.3332183994766498 0.9412491794821144 2.3851891847407183 3.9848415401998087
> rows: 1
@reconnect on
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论