Skip to content

Commit 6ba1b53

Browse files
committed
[CALCITE-7274] RexFieldAccess has wrong index when use trim unused fields
1 parent c274aac commit 6ba1b53

File tree

6 files changed

+230
-9
lines changed

6 files changed

+230
-9
lines changed

core/src/main/java/org/apache/calcite/sql/validate/SelectScope.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,15 @@ public boolean existingWindowName(String winName) {
222222
public void setExpandedSelectList(@Nullable List<SqlNode> selectList) {
223223
expandedSelectList = selectList;
224224
}
225+
226+
@Override public boolean isWithin(SqlValidatorScope scope2) {
227+
if (this == scope2) {
228+
return true;
229+
}
230+
// go from the JOIN to the enclosing SELECT
231+
if (scope2 instanceof JoinScope) {
232+
return isWithin(requireNonNull(((JoinScope) scope2).getUsingScope(), "usingScope"));
233+
}
234+
return false;
235+
}
225236
}

core/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,58 @@ protected TrimResult trimChild(
233233
return dispatchTrimFields(input, fieldsUsedBuilder.build(), extraFields);
234234
}
235235

236+
/**
237+
* Trims the fields of an input relational expression for RelNode with multiple inputs.
238+
*
239+
* @param rel Relational expression
240+
* @param input Input relational expression, whose fields to trim
241+
* @param startIndex Start index of the field range to process
242+
* @param endIndex End index of the field range to process (exclusive)
243+
* @param fieldsUsed Bitmap of fields needed by the consumer
244+
* @return New relational expression and its field mapping
245+
*/
246+
protected TrimResult trimChild(
247+
RelNode rel,
248+
RelNode input,
249+
int startIndex,
250+
int endIndex,
251+
final ImmutableBitSet fieldsUsed,
252+
Set<RelDataTypeField> extraFields) {
253+
final ImmutableBitSet.Builder fieldsUsedBuilder = fieldsUsed.rebuild();
254+
255+
// Fields that define the collation cannot be discarded.
256+
final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
257+
final ImmutableList<RelCollation> collations = mq.collations(input);
258+
if (collations != null) {
259+
for (RelCollation collation : collations) {
260+
for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
261+
fieldsUsedBuilder.set(fieldCollation.getFieldIndex());
262+
}
263+
}
264+
}
265+
266+
// Correlating variables are a means for other relational expressions to use
267+
// fields.
268+
for (final CorrelationId correlation : rel.getVariablesSet()) {
269+
rel.accept(
270+
new CorrelationReferenceFinder() {
271+
@Override protected RexNode handle(RexFieldAccess fieldAccess) {
272+
final RexCorrelVariable v =
273+
(RexCorrelVariable) fieldAccess.getReferenceExpr();
274+
if (v.id.equals(correlation)) {
275+
if (fieldAccess.getField().getIndex() >= startIndex
276+
&& fieldAccess.getField().getIndex() < endIndex) {
277+
fieldsUsedBuilder.set(fieldAccess.getField().getIndex() - startIndex);
278+
}
279+
}
280+
return fieldAccess;
281+
}
282+
});
283+
}
284+
285+
return dispatchTrimFields(input, fieldsUsedBuilder.build(), extraFields);
286+
}
287+
236288
/**
237289
* Trims a child relational expression, then adds back a dummy project to
238290
* restore the fields that were removed.
@@ -865,7 +917,8 @@ public TrimResult trimFields(
865917
: combinedInputExtraFields;
866918
inputExtraFieldCounts.add(inputExtraFields.size());
867919
TrimResult trimResult =
868-
trimChild(join, input, inputFieldsUsed.build(), inputExtraFields);
920+
trimChild(join, input, offset, offset + inputFieldCount,
921+
inputFieldsUsed.build(), inputExtraFields);
869922
newInputs.add(trimResult.left);
870923
if (trimResult.left != input) {
871924
++changeCount;
@@ -946,7 +999,7 @@ public TrimResult trimFields(
946999
requireNonNull(newMatchConditionExpr, "newMatchConditionExpr"));
9471000
break;
9481001
default:
949-
relBuilder.join(join.getJoinType(), newConditionExpr);
1002+
relBuilder.join(join.getJoinType(), newConditionExpr, join.getVariablesSet());
9501003
break;
9511004
}
9521005
return result(relBuilder.build(), mapping, join);

core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3103,12 +3103,25 @@ protected RelNode createJoin(
31033103
p.id, requiredCols, joinType);
31043104
}
31053105

3106-
final RelNode node =
3106+
RelNode node =
31073107
relBuilder.push(leftRel)
31083108
.push(rightRel)
31093109
.join(joinType, joinCond)
31103110
.build();
31113111

3112+
final CorrelationUse correlationUseInJoin = getCorrelationUse(bb, node);
3113+
if (correlationUseInJoin != null) {
3114+
assert correlationUseInJoin.r instanceof Join;
3115+
Join joinRelTemp = (Join) correlationUseInJoin.r;
3116+
node =
3117+
LogicalJoin.create(joinRelTemp.getLeft(),
3118+
joinRelTemp.getRight(),
3119+
joinRelTemp.getHints(),
3120+
joinRelTemp.getCondition(),
3121+
ImmutableSet.of(correlationUseInJoin.id),
3122+
joinRelTemp.getJoinType());
3123+
}
3124+
31123125
// If join conditions are pushed down, update the leaves.
31133126
if (node instanceof Project) {
31143127
final Join newJoin = (Join) node.getInputs().get(0);

core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8502,7 +8502,7 @@ LogicalProject(ID=[$0], ID0=[$1])
85028502
LogicalJoin(condition=[AND(=($0, $1), NOT(EXISTS({
85038503
LogicalFilter(condition=[=($0, $cor0.ID)])
85048504
LogicalValues(tuples=[[{ 3 }]])
8505-
})))], joinType=[left])
8505+
})))], joinType=[left], variablesSet=[[$cor0]])
85068506
LogicalValues(tuples=[[{ 1 }, { 2 }]])
85078507
LogicalValues(tuples=[[{ 2 }]])
85088508
]]>
@@ -8536,7 +8536,7 @@ LogicalProject(ID=[$0], ID0=[$1])
85368536
LogicalJoin(condition=[NOT(EXISTS({
85378537
LogicalFilter(condition=[=($0, $cor0.ID0)])
85388538
LogicalValues(tuples=[[{ 3 }]])
8539-
}))], joinType=[left])
8539+
}))], joinType=[left], variablesSet=[[$cor0]])
85408540
LogicalValues(tuples=[[{ 1 }]])
85418541
LogicalValues(tuples=[[{ 2 }]])
85428542
]]>
@@ -8598,7 +8598,7 @@ LogicalProject(ID=[$0], ID0=[$1])
85988598
LogicalJoin(condition=[OR(=($0, $1), EXISTS({
85998599
LogicalFilter(condition=[=($0, $cor0.ID0)])
86008600
LogicalValues(tuples=[[{ 3 }]])
8601-
}))], joinType=[left])
8601+
}))], joinType=[left], variablesSet=[[$cor0]])
86028602
LogicalValues(tuples=[[{ 1 }]])
86038603
LogicalValues(tuples=[[{ 2 }]])
86048604
]]>
@@ -8632,7 +8632,7 @@ LogicalProject(ID=[$0], ID0=[$1])
86328632
LogicalJoin(condition=[OR(=($0, $1), NOT(EXISTS({
86338633
LogicalFilter(condition=[=($0, $cor0.ID0)])
86348634
LogicalValues(tuples=[[{ 3 }]])
8635-
})))], joinType=[left])
8635+
})))], joinType=[left], variablesSet=[[$cor0]])
86368636
LogicalValues(tuples=[[{ 1 }]])
86378637
LogicalValues(tuples=[[{ 2 }]])
86388638
]]>

core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3765,7 +3765,7 @@ LogicalAggregate(group=[{}], EXPR$0=[AVG($0)])
37653765
LogicalProject(SAL=[$5])
37663766
LogicalFilter(condition=[=($7, $cor0.DEPTNO)])
37673767
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
3768-
})))], joinType=[inner])
3768+
})))], joinType=[inner], variablesSet=[[$cor0]])
37693769
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
37703770
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
37713771
]]>
@@ -3986,7 +3986,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$
39863986
LogicalJoin(condition=[OR(=($0, 1), EXISTS({
39873987
LogicalFilter(condition=[>($0, +($cor0.DEPTNO0, 5))])
39883988
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
3989-
}))], joinType=[left])
3989+
}))], joinType=[left], variablesSet=[[$cor0]])
39903990
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
39913991
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
39923992
]]>

core/src/test/resources/sql/sub-query.iq

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7505,4 +7505,148 @@ SELECT deptno FROM dept WHERE 1000.00 >
75057505

75067506
!ok
75077507

7508+
# [CALCITE-7274] RexFieldAccess has wrong index when use trim unused fields
7509+
!set trimfields true
7510+
7511+
SELECT empno
7512+
FROM emp AS e
7513+
LEFT JOIN dept AS d
7514+
ON d.deptno = e.deptno
7515+
AND (EXISTS (
7516+
SELECT e2.deptno FROM emp AS e2
7517+
WHERE e2.deptno = d.deptno
7518+
GROUP BY e2.deptno
7519+
HAVING SUM(e2.sal) > 1000000));
7520+
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0])
7521+
EnumerableTableScan(table=[[scott, EMP]])
7522+
!plan
7523+
+-------+
7524+
| EMPNO |
7525+
+-------+
7526+
| 7369 |
7527+
| 7499 |
7528+
| 7521 |
7529+
| 7566 |
7530+
| 7654 |
7531+
| 7698 |
7532+
| 7782 |
7533+
| 7788 |
7534+
| 7839 |
7535+
| 7844 |
7536+
| 7876 |
7537+
| 7900 |
7538+
| 7902 |
7539+
| 7934 |
7540+
+-------+
7541+
(14 rows)
7542+
7543+
!ok
7544+
7545+
SELECT empno
7546+
FROM emp AS e
7547+
LEFT JOIN dept AS d
7548+
ON d.dname = e.ename
7549+
AND (EXISTS (
7550+
SELECT e2.deptno FROM emp AS e2
7551+
WHERE e2.deptno = e.deptno
7552+
GROUP BY e2.deptno
7553+
HAVING SUM(e2.sal) > 1000000));
7554+
7555+
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0])
7556+
EnumerableTableScan(table=[[scott, EMP]])
7557+
!plan
7558+
+-------+
7559+
| EMPNO |
7560+
+-------+
7561+
| 7369 |
7562+
| 7499 |
7563+
| 7521 |
7564+
| 7566 |
7565+
| 7654 |
7566+
| 7698 |
7567+
| 7782 |
7568+
| 7788 |
7569+
| 7839 |
7570+
| 7844 |
7571+
| 7876 |
7572+
| 7900 |
7573+
| 7902 |
7574+
| 7934 |
7575+
+-------+
7576+
(14 rows)
7577+
7578+
!ok
7579+
7580+
# Same as previous; but don't trim fields
7581+
!set trimfields false
7582+
7583+
SELECT empno
7584+
FROM emp AS e
7585+
LEFT JOIN dept AS d
7586+
ON d.deptno = e.deptno
7587+
AND (EXISTS (
7588+
SELECT e2.deptno FROM emp AS e2
7589+
WHERE e2.deptno = d.deptno
7590+
GROUP BY e2.deptno
7591+
HAVING SUM(e2.sal) > 1000000));
7592+
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0])
7593+
EnumerableTableScan(table=[[scott, EMP]])
7594+
!plan
7595+
+-------+
7596+
| EMPNO |
7597+
+-------+
7598+
| 7369 |
7599+
| 7499 |
7600+
| 7521 |
7601+
| 7566 |
7602+
| 7654 |
7603+
| 7698 |
7604+
| 7782 |
7605+
| 7788 |
7606+
| 7839 |
7607+
| 7844 |
7608+
| 7876 |
7609+
| 7900 |
7610+
| 7902 |
7611+
| 7934 |
7612+
+-------+
7613+
(14 rows)
7614+
7615+
!ok
7616+
7617+
SELECT empno
7618+
FROM emp AS e
7619+
LEFT JOIN dept AS d
7620+
ON d.dname = e.ename
7621+
AND (EXISTS (
7622+
SELECT e2.deptno FROM emp AS e2
7623+
WHERE e2.deptno = e.deptno
7624+
GROUP BY e2.deptno
7625+
HAVING SUM(e2.sal) > 1000000));
7626+
7627+
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0])
7628+
EnumerableTableScan(table=[[scott, EMP]])
7629+
!plan
7630+
+-------+
7631+
| EMPNO |
7632+
+-------+
7633+
| 7369 |
7634+
| 7499 |
7635+
| 7521 |
7636+
| 7566 |
7637+
| 7654 |
7638+
| 7698 |
7639+
| 7782 |
7640+
| 7788 |
7641+
| 7839 |
7642+
| 7844 |
7643+
| 7876 |
7644+
| 7900 |
7645+
| 7902 |
7646+
| 7934 |
7647+
+-------+
7648+
(14 rows)
7649+
7650+
!ok
7651+
75087652
# End sub-query.iq

0 commit comments

Comments
 (0)