Skip to content

Commit a63524b

Browse files
emasabmatriv
authored andcommitted
SQL: Fix issue with duplicate columns in SELECT (#42122)
Previously, if a column (field, scalar, alias) appeared more than once in the SELECT list, the value was returned only once (1st appearance) in each row. Fixes: #41811 (cherry picked from commit 097ea36)
1 parent 84fe287 commit a63524b

File tree

5 files changed

+117
-2
lines changed

5 files changed

+117
-2
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
aggSumWithColumnRepeatedWithOrderAsc
2+
SELECT gender AS g, gender, SUM(salary) AS s3, SUM(salary), SUM(salary) AS s5 FROM test_emp GROUP BY gender ORDER BY SUM(salary);
3+
4+
g:s | gender:s | s3:i | SUM(salary):i | s5:i
5+
null |null |487605 |487605 |487605
6+
F |F |1666196|1666196 |1666196
7+
M |M |2671054|2671054 |2671054
8+
;
9+
10+
aggSumWithAliasWithColumnRepeatedWithOrderDesc
11+
SELECT gender AS g, gender, SUM(salary) AS s3, SUM(salary), SUM(salary) AS s5 FROM test_emp GROUP BY g ORDER BY s5 DESC;
12+
13+
g:s | gender:s | s3:i | SUM(salary):i | s5:i
14+
M |M |2671054|2671054 |2671054
15+
F |F |1666196|1666196 |1666196
16+
null |null |487605 |487605 |487605
17+
;
18+
19+
aggSumWithNumericRefWithColumnRepeatedWithOrderDesc
20+
SELECT gender AS g, gender, SUM(salary) AS s3, SUM(salary), SUM(salary) AS s5 FROM test_emp GROUP BY 2 ORDER BY 3 DESC;
21+
22+
g:s | gender:s | s3:i | SUM(salary):i | s5:i
23+
M |M |2671054|2671054 |2671054
24+
F |F |1666196|1666196 |1666196
25+
null |null |487605 |487605 |487605
26+
;

x-pack/plugin/sql/qa/src/main/resources/agg.csv-spec

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,33 @@ null |null |null |null |null |n
146146
4 |4 |72 |4 |4.0 |0.0 |NaN |NaN
147147
;
148148

149+
aggSumWithColumnRepeated
150+
SELECT gender AS g, gender, SUM(salary) AS s3, SUM(salary), SUM(salary) AS s5 FROM test_emp GROUP BY gender;
151+
152+
g:s | gender:s | s3:i | SUM(salary):i | s5:i
153+
null |null |487605 |487605 |487605
154+
F |F |1666196|1666196 |1666196
155+
M |M |2671054|2671054 |2671054
156+
;
157+
158+
aggSumWithAliasWithColumnRepeated
159+
SELECT gender AS g, gender, SUM(salary) AS s3, SUM(salary), SUM(salary) AS s5 FROM test_emp GROUP BY g;
160+
161+
g:s | gender:s | s3:i | SUM(salary):i | s5:i
162+
null |null |487605 |487605 |487605
163+
F |F |1666196|1666196 |1666196
164+
M |M |2671054|2671054 |2671054
165+
;
166+
167+
aggSumWithNumericRefWithColumnRepeated
168+
SELECT gender AS g, gender, SUM(salary) AS s3, SUM(salary), SUM(salary) AS s5 FROM test_emp GROUP BY 2;
169+
170+
g:s | gender:s | s3:i | SUM(salary):i | s5:i
171+
null |null |487605 |487605 |487605
172+
F |F |1666196|1666196 |1666196
173+
M |M |2671054|2671054 |2671054
174+
;
175+
149176
aggByComplexCastedValue
150177
SELECT CONVERT(CONCAT(LTRIM(CONVERT("emp_no", SQL_VARCHAR)), LTRIM(CONVERT("languages", SQL_VARCHAR))), SQL_BIGINT) AS "TEMP"
151178
FROM "test_emp" GROUP BY "TEMP" ORDER BY "TEMP" LIMIT 20;

x-pack/plugin/sql/qa/src/main/resources/select.sql-spec

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ multipleColumnsNoAliasWithLimit
3333
SELECT first_name, last_name FROM "test_emp" ORDER BY emp_no LIMIT 5;
3434
multipleColumnWithAliasWithAndWithoutAsWithLimit
3535
SELECT first_name f, last_name AS l FROM "test_emp" ORDER BY emp_no LIMIT 5;
36+
multipleColumnNoAliasWithColumnRepeatedWithLimit
37+
SELECT salary, first_name, salary FROM test_emp ORDER BY salary LIMIT 3;
38+
multipleColumnWithAliasWithAsWithColumnRepeatedWithLimit
39+
SELECT salary, first_name, salary AS x FROM test_emp ORDER BY x LIMIT 3;
40+
multipleColumnWithAliasWithAndWithoutAsWithColumnRepeatedWithLimit
41+
SELECT salary, first_name, salary AS x, salary y FROM test_emp ORDER BY y LIMIT 3;
3642

3743
//
3844
// SELECT constant literals with FROM

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,9 @@ public BitSet columnMask(List<Attribute> columns) {
182182
.innerId() : alias.id()) : null;
183183
for (int i = 0; i < fields.size(); i++) {
184184
Tuple<FieldExtraction, ExpressionId> tuple = fields.get(i);
185-
if (tuple.v2().equals(id) || (aliasId != null && tuple.v2().equals(aliasId))) {
185+
// if the index is already set there is a collision,
186+
// so continue searching for the other tuple with the same id
187+
if (mask.get(i)==false && (tuple.v2().equals(id) || (aliasId != null && tuple.v2().equals(aliasId)))) {
186188
index = i;
187189
break;
188190
}
@@ -479,4 +481,4 @@ public String toString() {
479481
throw new RuntimeException("error rendering", e);
480482
}
481483
}
482-
}
484+
}

x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainerTests.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,25 @@
66
package org.elasticsearch.xpack.sql.querydsl.container;
77

88
import org.elasticsearch.test.ESTestCase;
9+
import org.elasticsearch.xpack.sql.expression.Alias;
10+
import org.elasticsearch.xpack.sql.expression.Attribute;
11+
import org.elasticsearch.xpack.sql.expression.AttributeMap;
12+
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
913
import org.elasticsearch.xpack.sql.querydsl.query.BoolQuery;
1014
import org.elasticsearch.xpack.sql.querydsl.query.MatchAll;
1115
import org.elasticsearch.xpack.sql.querydsl.query.NestedQuery;
1216
import org.elasticsearch.xpack.sql.querydsl.query.Query;
1317
import org.elasticsearch.xpack.sql.querydsl.query.RangeQuery;
1418
import org.elasticsearch.xpack.sql.tree.Source;
1519
import org.elasticsearch.xpack.sql.tree.SourceTests;
20+
import org.elasticsearch.xpack.sql.type.DataType;
21+
import org.elasticsearch.xpack.sql.type.EsField;
1622

1723
import java.util.AbstractMap.SimpleImmutableEntry;
24+
import java.util.Arrays;
25+
import java.util.BitSet;
26+
import java.util.LinkedHashMap;
27+
import java.util.Map;
1828

1929
import static java.util.Collections.emptyMap;
2030
import static java.util.Collections.singletonMap;
@@ -60,4 +70,48 @@ public void testRewriteToContainsNestedFieldWhenDoesNotContainNestedFieldAndCant
6070
new MatchAll(source)));
6171
assertEquals(expected, QueryContainer.rewriteToContainNestedField(original, source, path, name, format, hasDocValues));
6272
}
73+
74+
public void testColumnMaskShouldDuplicateSameAttributes() {
75+
76+
EsField esField = new EsField("str", DataType.TEXT, emptyMap(), true);
77+
78+
Attribute first = new FieldAttribute(Source.EMPTY, "first", esField);
79+
Attribute second = new FieldAttribute(Source.EMPTY, "second", esField);
80+
Attribute third = new FieldAttribute(Source.EMPTY, "third", esField);
81+
Attribute fourth = new FieldAttribute(Source.EMPTY, "fourth", esField);
82+
Alias firstAliased = new Alias(Source.EMPTY, "firstAliased", first);
83+
84+
Map<Attribute,Attribute> aliasesMap = new LinkedHashMap<>();
85+
aliasesMap.put(firstAliased.toAttribute(), first);
86+
87+
QueryContainer queryContainer = new QueryContainer()
88+
.withAliases(new AttributeMap<>(aliasesMap))
89+
.addColumn(third)
90+
.addColumn(first)
91+
.addColumn(fourth)
92+
.addColumn(firstAliased.toAttribute())
93+
.addColumn(second)
94+
.addColumn(first)
95+
.addColumn(fourth);
96+
97+
BitSet result = queryContainer.columnMask(Arrays.asList(
98+
first,
99+
first,
100+
second,
101+
third,
102+
firstAliased.toAttribute()
103+
));
104+
105+
BitSet expected = new BitSet();
106+
expected.set(0, true);
107+
expected.set(1, true);
108+
expected.set(2, false);
109+
expected.set(3, true);
110+
expected.set(4, true);
111+
expected.set(5, true);
112+
expected.set(6, false);
113+
114+
115+
assertEquals(expected, result);
116+
}
63117
}

0 commit comments

Comments
 (0)