Skip to content

Commit 5f75b0b

Browse files
julianhydeclaude
andcommitted
[CALCITE-7420] Migrate tests to Quidem .iq format (batch)
Migrate 15 tests from RelOptRulesTest.java + XML to Quidem .iq scripts: - reduce-expressions.iq: testReduceNestedCaseWhen, testReduceNot - aggregate.iq: testDigestOfApproximateDistinctAggregateCall, testRemoveDistinctOnAgg - aggregate-within-distinct.iq (new file): testWithinDistinct, testWithinDistinctNoThrow, testWithinDistinctUniformDistinctKeys, testWithinDistinctUniformDistinctKeysNoThrow, testWithinDistinctCountDistinct, testWithinDistinctFilteredAggs, testWithinDistinctPreservesNonDistinctAggFilters, testWithinDistinctPreservesNonDistinctCollation, testWithinDistinctFilteredAggsUniformDistinctKeys, testWithinDistinctFilteredAggsUniformDistinctKeysNoThrow, testWithinDistinctFilteredAggsSameFilter Also adds 'throwIfNotUnique=false' config token to SubPlanCommand in QuidemTest.java, which applies AggregateExpandWithinDistinctRule.config.withThrowIfNotUnique(false) when the token precedes AGGREGATE_EXPAND_WITHIN_DISTINCT in the rule list. Also carries forward earlier-session changes: - filter-into-join.iq: testStrengthenJoinType - filter-project-transpose.iq (new): testFilterProjectTransposePreventedByCorrelation, testProjectCorrelateTransposeRuleLeftCorrelate - filter.iq: testPushFilterPastAggWithGroupingSets1/2 (with correct pre-rules PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE) - project-filter-transpose.iq (new): testPushProjectPastFilter3b/3c Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a1a5a38 commit 5f75b0b

File tree

10 files changed

+635
-989
lines changed

10 files changed

+635
-989
lines changed

core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java

Lines changed: 0 additions & 386 deletions
Large diffs are not rendered by default.

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

Lines changed: 7 additions & 602 deletions
Large diffs are not rendered by default.

core/src/test/resources/sql/rule/aggregate-within-distinct.iq

Lines changed: 277 additions & 0 deletions
Large diffs are not rendered by default.

core/src/test/resources/sql/rule/aggregate.iq

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,33 @@ LogicalAggregate(group=[{0, 1}])
487487
LogicalValues(tuples=[[{ 1, 'a' }, { 2, 'b' }, { 1, 'b' }]])
488488
!sub-plan "AGGREGATE_PROJECT_MERGE, AGGREGATE_VALUES"
489489

490+
# testDigestOfApproximateDistinctAggregateCall ---------------------------------
491+
# AGGREGATE_PROJECT_MERGE merges a Project into an Aggregate, treating
492+
# COUNT(DISTINCT) and APPROX_COUNT_DISTINCT as different aggregate calls.
493+
# Not using !ok: approx_count_distinct is not supported in the scott HSQLDB.
494+
495+
select *
496+
from (
497+
select deptno, count(distinct empno) from emp group by deptno
498+
union all
499+
select deptno, approx_count_distinct(empno) from emp group by deptno);
500+
LogicalProject(DEPTNO=[$0], EXPR$1=[$1])
501+
LogicalUnion(all=[true])
502+
LogicalAggregate(group=[{0}], EXPR$1=[COUNT(DISTINCT $1)])
503+
LogicalProject(DEPTNO=[$7], EMPNO=[$0])
504+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
505+
LogicalAggregate(group=[{0}], EXPR$1=[COUNT(APPROXIMATE DISTINCT $1)])
506+
LogicalProject(DEPTNO=[$7], EMPNO=[$0])
507+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
508+
!sub-plan ""
509+
LogicalProject(DEPTNO=[$0], EXPR$1=[$1])
510+
LogicalUnion(all=[true])
511+
LogicalAggregate(group=[{7}], EXPR$1=[COUNT(DISTINCT $0)])
512+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
513+
LogicalAggregate(group=[{7}], EXPR$1=[COUNT(APPROXIMATE DISTINCT $0)])
514+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
515+
!sub-plan "AGGREGATE_PROJECT_MERGE"
516+
490517
# testGroupByBooleanLiteralSimple ----------------------------------------------
491518
# AggregateProjectConstantToDummyJoinRule replaces a constant group-by key
492519
# (boolean literal true) with a join to a single-row Values.
@@ -770,4 +797,22 @@ LogicalAggregate(group=[{0, 1}])
770797
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
771798
!sub-plan "AGGREGATE_PROJECT_MERGE, AGGREGATE_UNION_AGGREGATE"
772799

800+
# testRemoveDistinctOnAgg ------------------------------------------------------
801+
# AGGREGATE_REMOVE removes the aggregate when the group key contains a primary
802+
# key, since each group has exactly one row. PROJECT_MERGE then merges projects.
803+
# Not using !ok: bit_and, bit_or may not be supported in the scott HSQLDB.
804+
805+
select empno, sum(distinct sal), min(sal),
806+
min(distinct sal), max(distinct sal),
807+
bit_and(distinct sal), bit_or(sal), count(distinct sal)
808+
from sales.emp group by empno, deptno;
809+
LogicalProject(EMPNO=[$0], EXPR$1=[$2], EXPR$2=[$3], EXPR$3=[$3], EXPR$4=[$4], EXPR$5=[$5], EXPR$6=[$6], EXPR$7=[$7])
810+
LogicalAggregate(group=[{0, 1}], EXPR$1=[SUM(DISTINCT $2)], EXPR$2=[MIN($2)], EXPR$4=[MAX($2)], EXPR$5=[BIT_AND($2)], EXPR$6=[BIT_OR($2)], EXPR$7=[COUNT(DISTINCT $2)])
811+
LogicalProject(EMPNO=[$0], DEPTNO=[$7], SAL=[$5])
812+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
813+
!sub-plan ""
814+
LogicalProject(EMPNO=[$0], EXPR$1=[$5], EXPR$2=[$5], EXPR$3=[$5], EXPR$4=[$5], EXPR$5=[$5], EXPR$6=[$5], EXPR$7=[1:BIGINT])
815+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
816+
!sub-plan "AGGREGATE_REMOVE, PROJECT_MERGE"
817+
773818
# End aggregate.iq

core/src/test/resources/sql/rule/filter-into-join.iq

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,4 +624,48 @@ LogicalProject(UNO=[1])
624624
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
625625
!sub-plan "FILTER_INTO_JOIN"
626626

627+
# testStrengthenJoinType -------------------------------------------------------
628+
# FILTER_INTO_JOIN strengthens a left outer join to inner join when the WHERE
629+
# clause has a null-rejecting predicate on the right side.
630+
631+
select dept.*, emp.ename
632+
from dept left join emp on dept.deptno = emp.deptno
633+
where emp.deptno is not null and emp.sal > 100;
634+
+--------+------------+----------+--------+
635+
| DEPTNO | DNAME | LOC | ENAME |
636+
+--------+------------+----------+--------+
637+
| 10 | ACCOUNTING | NEW YORK | CLARK |
638+
| 10 | ACCOUNTING | NEW YORK | KING |
639+
| 10 | ACCOUNTING | NEW YORK | MILLER |
640+
| 20 | RESEARCH | DALLAS | ADAMS |
641+
| 20 | RESEARCH | DALLAS | FORD |
642+
| 20 | RESEARCH | DALLAS | JONES |
643+
| 20 | RESEARCH | DALLAS | SCOTT |
644+
| 20 | RESEARCH | DALLAS | SMITH |
645+
| 30 | SALES | CHICAGO | ALLEN |
646+
| 30 | SALES | CHICAGO | BLAKE |
647+
| 30 | SALES | CHICAGO | JAMES |
648+
| 30 | SALES | CHICAGO | MARTIN |
649+
| 30 | SALES | CHICAGO | TURNER |
650+
| 30 | SALES | CHICAGO | WARD |
651+
+--------+------------+----------+--------+
652+
(14 rows)
653+
654+
!ok
655+
LogicalProject(DEPTNO=[$0], DNAME=[$1], ENAME=[$2])
656+
LogicalFilter(condition=[AND(>($3, 100), IS NOT NULL($4))])
657+
LogicalJoin(condition=[=($0, $4)], joinType=[left])
658+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
659+
LogicalProject(ENAME=[$1], SAL=[$5], DEPTNO=[$7])
660+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
661+
!sub-plan "trim=true, PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE"
662+
LogicalProject(DEPTNO=[$0], DNAME=[$1], ENAME=[$2])
663+
LogicalProject(DEPTNO=[$0], DNAME=[$1], ENAME=[CAST($2):VARCHAR(20)], SAL=[CAST($3):INTEGER], DEPTNO0=[CAST($4):INTEGER])
664+
LogicalJoin(condition=[=($0, $4)], joinType=[inner])
665+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
666+
LogicalFilter(condition=[>($1, 100)])
667+
LogicalProject(ENAME=[$1], SAL=[$5], DEPTNO=[$7])
668+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
669+
!sub-plan "trim=true, PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE, FILTER_INTO_JOIN"
670+
627671
# End filter-into-join.iq

core/src/test/resources/sql/rule/filter-project-transpose.iq

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,30 @@ LogicalProject(EXPR$0=[CASE(>($3, 0), $4, null:INTEGER)], SALARY=[$0], ENROLL_DA
5151
LogicalValues(tuples=[[{ 'x', 10, 5200, 2007-08-01 }, { null, null, null, null }]])
5252
!sub-plan "PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW, PROJECT_WINDOW_TRANSPOSE"
5353

54+
# testFilterProjectTransposePreventedByCorrelation -----------------------------
55+
# FILTER_PROJECT_TRANSPOSE does not push a Filter containing a correlated
56+
# variable past a Project (expand=true, decorrelate=false, checkUnchanged).
57+
# Not using !ok: uses correlated EXISTS subquery not reliably executable in HSQLDB.
58+
59+
SELECT e.empno
60+
FROM emp as e
61+
WHERE exists (
62+
SELECT *
63+
FROM (
64+
SELECT deptno * 2 AS twiceDeptno
65+
FROM dept) AS d
66+
WHERE e.deptno = d.twiceDeptno);
67+
LogicalProject(EMPNO=[$0])
68+
LogicalFilter(condition=[IS NOT NULL($9)])
69+
LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{7}])
70+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
71+
LogicalAggregate(group=[{}], agg#0=[MIN($0)])
72+
LogicalProject($f0=[true])
73+
LogicalFilter(condition=[=($cor0.DEPTNO, $0)])
74+
LogicalProject(TWICEDEPTNO=[*($0, 2)])
75+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
76+
!sub-plan "expand=true, FILTER_PROJECT_TRANSPOSE"
77+
5478
# testFilterTableFunctionScanTranspose -----------------------------------------
5579
# FILTER_TABLE_FUNCTION_TRANSPOSE pushes a Filter past a TableFunctionScan.
5680
# [CALCITE-5985]
@@ -177,6 +201,36 @@ LogicalProject(DNAME=[$1], DEPTNO=[$0], EXPR$2=[$2])
177201
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
178202
!sub-plan "PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW, FILTER_PROJECT_TRANSPOSE, FILTER_WINDOW_TRANSPOSE, PROJECT_REMOVE"
179203

204+
# testProjectCorrelateTransposeRuleLeftCorrelate --------------------------------
205+
# PROJECT_CORRELATE_TRANSPOSE pushes a Project into a left-type Correlate.
206+
# [CALCITE-6878]
207+
# Not using !ok: uses correlated EXISTS subquery not reliably executable in HSQLDB.
208+
209+
SELECT e1.empno
210+
FROM emp e1 where exists (select empno, deptno from dept d2 where e1.deptno = d2.deptno);
211+
LogicalProject(EMPNO=[$0])
212+
LogicalFilter(condition=[IS NOT NULL($9)])
213+
LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{7}])
214+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
215+
LogicalAggregate(group=[{}], agg#0=[MIN($0)])
216+
LogicalProject($f0=[true])
217+
LogicalFilter(condition=[=($cor0.DEPTNO, $0)])
218+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
219+
!sub-plan "expand=true, NONE"
220+
LogicalProject(EMPNO=[$0])
221+
LogicalFilter(condition=[IS NOT NULL($1)])
222+
LogicalProject(EMPNO=[$0], $f0=[$2])
223+
LogicalCorrelate(correlation=[$cor2], joinType=[left], requiredColumns=[{1}])
224+
LogicalProject(EMPNO=[$0], DEPTNO=[$7])
225+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
226+
LogicalProject($f0=[$0])
227+
LogicalAggregate(group=[{}], agg#0=[MIN($0)])
228+
LogicalProject($f0=[true])
229+
LogicalFilter(condition=[=($cor2.DEPTNO, $0)])
230+
LogicalProject(DEPTNO=[$0])
231+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
232+
!sub-plan "expand=true, FILTER_PROJECT_TRANSPOSE, PROJECT_FILTER_TRANSPOSE, PROJECT_CORRELATE_TRANSPOSE"
233+
180234
# testProjectCorrelateTransposeWithOver ----------------------------------------
181235
# PROJECT_CORRELATE_TRANSPOSE should not push a Project with windowed aggregates
182236
# over a Correlate, but can push into the Correlate's inputs.

core/src/test/resources/sql/rule/filter.iq

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,50 @@ LogicalProject(DEPTNO=[$0], ENAME=[$1])
127127
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
128128
!sub-plan "FILTER_PROJECT_TRANSPOSE, FILTER_MERGE, FILTER_INTO_JOIN"
129129

130+
# testPushFilterPastAggWithGroupingSets1 ---------------------------------------
131+
# FILTER_AGGREGATE_TRANSPOSE does not push a filter past an aggregate with
132+
# ROLLUP grouping sets (checkUnchanged).
133+
# Not using !ok: result row order is non-deterministic.
134+
135+
select ddeptno, dname, c from
136+
(select deptno ddeptno, dname dname, count(*) as c
137+
from dept group by rollup(deptno,dname)) t
138+
where dname = 'Charlie';
139+
LogicalProject(DDEPTNO=[$0], DNAME=[$1], C=[$2])
140+
LogicalProject(DDEPTNO=[$0], DNAME=[$1], C=[$2])
141+
LogicalFilter(condition=[=($1, 'Charlie')])
142+
LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]], C=[COUNT()])
143+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
144+
!sub-plan "PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE"
145+
LogicalProject(DDEPTNO=[$0], DNAME=[$1], C=[$2])
146+
LogicalProject(DDEPTNO=[$0], DNAME=[$1], C=[$2])
147+
LogicalFilter(condition=[=($1, 'Charlie')])
148+
LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}, {}]], C=[COUNT()])
149+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
150+
!sub-plan "PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE, FILTER_AGGREGATE_TRANSPOSE"
151+
152+
# testPushFilterPastAggWithGroupingSets2 ---------------------------------------
153+
# FILTER_AGGREGATE_TRANSPOSE pushes a filter past an aggregate with non-ROLLUP
154+
# grouping sets.
155+
# Not using !ok: result row order is non-deterministic.
156+
157+
select dname, ddeptno, c from
158+
(select dname dname, deptno ddeptno, count(*) as c
159+
from dept group by grouping sets ((dname,deptno),(dname))) t
160+
where dname = 'Charlie';
161+
LogicalProject(DNAME=[$0], DDEPTNO=[$1], C=[$2])
162+
LogicalFilter(condition=[=($0, 'Charlie')])
163+
LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}]], C=[COUNT()])
164+
LogicalProject(DNAME=[$1], DDEPTNO=[$0])
165+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
166+
!sub-plan "PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE"
167+
LogicalProject(DNAME=[$0], DDEPTNO=[$1], C=[$2])
168+
LogicalAggregate(group=[{0, 1}], groups=[[{0, 1}, {0}]], C=[COUNT()])
169+
LogicalFilter(condition=[=($0, 'Charlie')])
170+
LogicalProject(DNAME=[$1], DDEPTNO=[$0])
171+
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
172+
!sub-plan "PROJECT_MERGE, FILTER_PROJECT_TRANSPOSE, FILTER_AGGREGATE_TRANSPOSE"
173+
130174
# testReduceValuesUnderFilter --------------------------------------------------
131175
# FILTER_VALUES_MERGE merges a filter with an underlying VALUES node.
132176

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to you under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
# Tests planner rules related to ProjectFilterTransposeRule
17+
# (PROJECT_FILTER_TRANSPOSE and its variants).
18+
#
19+
# Ensure that tests occur in alphabetical order:
20+
# // lint: sort where '^[#] test'
21+
#
22+
23+
!use scott
24+
!set outputformat mysql
25+
26+
# testPushProjectPastFilter3b --------------------------------------------------
27+
# PROJECT_FILTER_TRANSPOSE_WHOLE_EXPRESSIONS pushes a Project past a Filter,
28+
# keeping filter conditions as whole expressions.
29+
# Not using !ok: uses SLACKER column not in the scott EMP table.
30+
31+
select empno + deptno as x, ename, job, mgr,
32+
hiredate, sal, comm, slacker
33+
from emp
34+
where sal = 10 * comm
35+
and upper(ename) = 'FOO';
36+
LogicalProject(X=[+($0, $7)], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], SLACKER=[$8])
37+
LogicalFilter(condition=[AND(=($5, *(10, $6)), =(UPPER($1), 'FOO'))])
38+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
39+
!sub-plan "NONE"
40+
LogicalProject(X=[$8], ENAME=[$0], JOB=[$1], MGR=[$2], HIREDATE=[$3], SAL=[$4], COMM=[$5], SLACKER=[$6])
41+
LogicalFilter(condition=[$7])
42+
LogicalProject(ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], SLACKER=[$8], $f7=[AND(=($5, *(10, $6)), =(UPPER($1), 'FOO'))], $f8=[+($0, $7)])
43+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
44+
!sub-plan "PROJECT_FILTER_TRANSPOSE_WHOLE_EXPRESSIONS"
45+
46+
# testPushProjectPastFilter3c --------------------------------------------------
47+
# PROJECT_FILTER_TRANSPOSE_WHOLE_PROJECT_EXPRESSIONS pushes a Project past a
48+
# Filter, keeping project expressions whole.
49+
# Not using !ok: uses SLACKER column not in the scott EMP table.
50+
51+
select empno + deptno as x, ename, job, mgr,
52+
hiredate, sal, comm, slacker
53+
from emp
54+
where sal = 10 * comm
55+
and upper(ename) = 'FOO';
56+
LogicalProject(X=[+($0, $7)], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], SLACKER=[$8])
57+
LogicalFilter(condition=[AND(=($5, *(10, $6)), =(UPPER($1), 'FOO'))])
58+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
59+
!sub-plan "NONE"
60+
LogicalProject(X=[$7], ENAME=[$0], JOB=[$1], MGR=[$2], HIREDATE=[$3], SAL=[$4], COMM=[$5], SLACKER=[$6])
61+
LogicalFilter(condition=[AND(=($4, *(10, $5)), =(UPPER($0), 'FOO'))])
62+
LogicalProject(ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], SLACKER=[$8], $f7=[+($0, $7)])
63+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
64+
!sub-plan "PROJECT_FILTER_TRANSPOSE_WHOLE_PROJECT_EXPRESSIONS"
65+
66+
# End project-filter-transpose.iq

core/src/test/resources/sql/rule/reduce-expressions.iq

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,94 @@ LogicalProject(COL1=[$0])
12681268
LogicalValues(tuples=[[{ false }, { true }]])
12691269
!sub-plan "FILTER_REDUCE_EXPRESSIONS"
12701270

1271+
# testReduceNestedCaseWhen ----------------------------------------------------
1272+
# FILTER_REDUCE_EXPRESSIONS simplifies a nested CASE when condition.
1273+
# Not using !ok: uses mock catalog only.
1274+
1275+
select sal
1276+
from emp
1277+
where case when (sal = 1000) then
1278+
(case when sal = 1000 then null else 1 end is null) else
1279+
(case when sal = 2000 then null else 1 end is null) end is true;
1280+
LogicalProject(SAL=[$5])
1281+
LogicalFilter(condition=[IS TRUE(CASE(=($5, 1000), IS NULL(CASE(=($5, 1000), null:INTEGER, 1)), IS NULL(CASE(=($5, 2000), null:INTEGER, 1))))])
1282+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1283+
!sub-plan ""
1284+
LogicalProject(SAL=[$5])
1285+
LogicalFilter(condition=[SEARCH($5, Sarg[1000, 2000])])
1286+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1287+
!sub-plan "FILTER_REDUCE_EXPRESSIONS"
1288+
1289+
# testReduceNot ----------------------------------------------------------------
1290+
# FILTER_REDUCE_EXPRESSIONS does not simplify NOT of a nullable CASE (checkUnchanged).
1291+
# Not using !ok: uses mock catalog only.
1292+
1293+
select *
1294+
from (select (case when sal > 1000 then null else false end) as caseCol from emp)
1295+
where NOT(caseCol);
1296+
LogicalProject(CASECOL=[$0])
1297+
LogicalFilter(condition=[NOT($0)])
1298+
LogicalProject(CASECOL=[AND(>($5, 1000), null)])
1299+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1300+
!sub-plan ""
1301+
LogicalProject(CASECOL=[$0])
1302+
LogicalFilter(condition=[NOT($0)])
1303+
LogicalProject(CASECOL=[AND(>($5, 1000), null)])
1304+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1305+
!sub-plan "FILTER_REDUCE_EXPRESSIONS"
1306+
1307+
# testReduceNullableCase -------------------------------------------------------
1308+
# PROJECT_REDUCE_EXPRESSIONS does not simplify CASE WHEN 1=2 when the THEN
1309+
# branch contains a scalar subquery (expand=true, checkUnchanged).
1310+
# Not using !ok: uses scalar subquery not supported in HSQLDB.
1311+
1312+
SELECT CASE WHEN 1=2 THEN cast((values(1)) as integer) ELSE 2 end
1313+
from (values(1));
1314+
LogicalProject(EXPR$0=[CAST(2):INTEGER])
1315+
LogicalJoin(condition=[true], joinType=[left])
1316+
LogicalValues(tuples=[[{ 1 }]])
1317+
LogicalValues(tuples=[[{ 1 }]])
1318+
!sub-plan "expand=true, PROJECT_REDUCE_EXPRESSIONS"
1319+
1320+
# testReduceNullableCase2 -------------------------------------------------------
1321+
# PROJECT_REDUCE_EXPRESSIONS does not simplify CASE WHEN 1=2 when already
1322+
# reduced to null during conversion (expand=true, checkUnchanged).
1323+
# Not using !ok: result row order is non-deterministic.
1324+
1325+
SELECT deptno, ename,
1326+
CASE WHEN 1=2 THEN substring(ename, 1, cast(2 as int)) ELSE NULL end
1327+
from emp
1328+
group by deptno, ename,
1329+
case when 1=2 then substring(ename,1, cast(2 as int)) else null end;
1330+
LogicalAggregate(group=[{0, 1, 2}])
1331+
LogicalProject(DEPTNO=[$7], ENAME=[$1], EXPR$2=[null:VARCHAR(20)])
1332+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1333+
!sub-plan "expand=true, PROJECT_REDUCE_EXPRESSIONS"
1334+
1335+
# testReduceOrCaseWhen -------------------------------------------------------
1336+
# FILTER_REDUCE_EXPRESSIONS should reduce OR(IS NULL(CASE...), IS NULL(CASE...))
1337+
# to SEARCH(sal, Sarg[1000, 2000]).
1338+
1339+
select sal
1340+
from emp
1341+
where case when sal = 1000 then null else 1 end is null
1342+
OR case when sal = 2000 then null else 1 end is null;
1343+
+-----+
1344+
| SAL |
1345+
+-----+
1346+
+-----+
1347+
(0 rows)
1348+
1349+
!ok
1350+
LogicalProject(SAL=[$5])
1351+
LogicalFilter(condition=[OR(IS NULL(CASE(=($5, 1000), null:INTEGER, 1)), IS NULL(CASE(=($5, 2000), null:INTEGER, 1)))])
1352+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1353+
!sub-plan "NONE"
1354+
LogicalProject(SAL=[$5])
1355+
LogicalFilter(condition=[SEARCH($5, Sarg[1000, 2000])])
1356+
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
1357+
!sub-plan "FILTER_REDUCE_EXPRESSIONS"
1358+
12711359
# testSkipReduceConstantsCaseEquals -------------------------------------------
12721360
# FILTER_REDUCE_EXPRESSIONS should not reduce CASE from COALESCE when it
12731361
# compares two non-constant expressions.

0 commit comments

Comments
 (0)