Skip to content

Commit d8d2fec

Browse files
[CALCITE-7324] NullPointerException from RelDecorrelator with multiple subqueries where one has a complex correlated condition
1 parent e7e3925 commit d8d2fec

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

plus/src/test/java/org/apache/calcite/adapter/tpch/TpchTest.java

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,116 @@ private CalciteAssert.AssertThat with() {
12131213
assertThat(after, hasTree(planAfter));
12141214
}
12151215

1216+
/** Test case for <a href="https://issues.apache.org/jira/browse/CALCITE-7324">[CALCITE-7324]
1217+
* NullPointerException from RelDecorrelator with multiple subqueries
1218+
* where one has a complex correlated condition</a>. */
1219+
@Test public void test7324()
1220+
throws SqlParseException, ValidationException, RelConversionException {
1221+
SchemaPlus rootSchema = Frameworks.createRootSchema(true);
1222+
TpchSchema tpchSchema = new TpchSchema(1.0, 0, 1, false);
1223+
rootSchema.add("TPCH", tpchSchema);
1224+
FrameworkConfig config = Frameworks.newConfigBuilder()
1225+
.defaultSchema(rootSchema)
1226+
.build();
1227+
final RelBuilder builder = RelBuilder.create(config);
1228+
final RelOptCluster cluster = builder.getCluster();
1229+
1230+
Planner planner = Frameworks.getPlanner(config);
1231+
1232+
String sql = ""
1233+
+ "select\n" +
1234+
" (select count(*) from tpch.PART where p_partkey = PARTSUPP.ps_partkey),\n" +
1235+
" (select count(*) from tpch.SUPPLIER\n" +
1236+
"where s_suppkey = case when s_acctbal > 0 then PARTSUPP.ps_partkey + 1 else 1234 end)\n" +
1237+
"from tpch.PARTSUPP";
1238+
1239+
SqlNode parsed = planner.parse(sql);
1240+
SqlNode validated = planner.validate(parsed);
1241+
RelRoot root = planner.rel(validated);
1242+
final RelNode originalRel = root.rel;
1243+
1244+
final HepProgram hepProgram = HepProgram.builder()
1245+
.addRuleCollection(
1246+
ImmutableList.of(
1247+
// SubQuery program rules
1248+
CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
1249+
CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE,
1250+
CoreRules.JOIN_SUB_QUERY_TO_CORRELATE))
1251+
.build();
1252+
final Program program =
1253+
Programs.of(hepProgram, true,
1254+
requireNonNull(cluster.getMetadataProvider()));
1255+
final RelNode before =
1256+
program.run(cluster.getPlanner(), originalRel, cluster.traitSet(),
1257+
Collections.emptyList(), Collections.emptyList());
1258+
final String planBefore = ""
1259+
+ "LogicalProject(EXPR$0=[$5], EXPR$1=[$6])\n"
1260+
+ " LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])\n"
1261+
+ " LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])\n"
1262+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1263+
+ " LogicalAggregate(group=[{}], EXPR$0=[COUNT()])\n"
1264+
+ " LogicalFilter(condition=[=($0, $cor0.PS_PARTKEY)])\n"
1265+
+ " LogicalTableScan(table=[[TPCH, PART]])\n"
1266+
+ " LogicalAggregate(group=[{}], EXPR$0=[COUNT()])\n"
1267+
+ " LogicalFilter(condition=[=(CAST($0):BIGINT, CASE(>(CAST($5):DOUBLE, CAST(0):DOUBLE NOT NULL), +($cor0.PS_PARTKEY, 1), 1234:BIGINT))])\n"
1268+
+ " LogicalTableScan(table=[[TPCH, SUPPLIER]])\n";
1269+
assertThat(before, hasTree(planBefore));
1270+
1271+
// Decorrelate without any rules, just "purely" decorrelation algorithm on RelDecorrelator
1272+
final RelNode after =
1273+
RelDecorrelator.decorrelateQuery(before, builder,
1274+
RuleSets.ofList(Collections.emptyList()),
1275+
RuleSets.ofList(Collections.emptyList()));
1276+
final String planAfter = ""
1277+
+ "LogicalProject(EXPR$0=[$5], EXPR$1=[$8])\n"
1278+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($6, $7)], joinType=[left])\n"
1279+
+ " LogicalProject(PS_PARTKEY=[$0], PS_SUPPKEY=[$1], PS_AVAILQTY=[$2], PS_SUPPLYCOST=[$3], PS_COMMENT=[$4], EXPR$0=[$6], $f6=[+($0, 1)])\n"
1280+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $5)], joinType=[left])\n"
1281+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1282+
+ " LogicalProject(P_PARTKEY=[$0], EXPR$0=[CASE(IS NOT NULL($2), $2, 0)])\n"
1283+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])\n"
1284+
+ " LogicalAggregate(group=[{0}])\n"
1285+
+ " LogicalProject(PS_PARTKEY=[$0])\n"
1286+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1287+
+ " LogicalAggregate(group=[{0}], EXPR$0=[COUNT()])\n"
1288+
+ " LogicalProject(P_PARTKEY=[$0])\n"
1289+
+ " LogicalFilter(condition=[IS NOT NULL($0)])\n"
1290+
+ " LogicalTableScan(table=[[TPCH, PART]])\n"
1291+
+ " LogicalProject($f6=[$0], EXPR$0=[CASE(IS NOT NULL($2), $2, 0)])\n"
1292+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])\n"
1293+
+ " LogicalAggregate(group=[{0}])\n"
1294+
+ " LogicalProject($f6=[+($0, 1)])\n"
1295+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $5)], joinType=[left])\n"
1296+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1297+
+ " LogicalProject(P_PARTKEY=[$0], EXPR$0=[CASE(IS NOT NULL($2), $2, 0)])\n"
1298+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])\n"
1299+
+ " LogicalAggregate(group=[{0}])\n"
1300+
+ " LogicalProject(PS_PARTKEY=[$0])\n"
1301+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1302+
+ " LogicalAggregate(group=[{0}], EXPR$0=[COUNT()])\n"
1303+
+ " LogicalProject(P_PARTKEY=[$0])\n"
1304+
+ " LogicalFilter(condition=[IS NOT NULL($0)])\n"
1305+
+ " LogicalTableScan(table=[[TPCH, PART]])\n"
1306+
+ " LogicalAggregate(group=[{0}], EXPR$0=[COUNT()])\n"
1307+
+ " LogicalProject($f6=[$7])\n"
1308+
+ " LogicalJoin(condition=[=(CAST($0):BIGINT, CASE(>(CAST($5):DOUBLE, 0.0E0), $7, 1234:BIGINT))], joinType=[inner])\n"
1309+
+ " LogicalTableScan(table=[[TPCH, SUPPLIER]])\n"
1310+
+ " LogicalAggregate(group=[{0}])\n"
1311+
+ " LogicalProject($f6=[+($0, 1)])\n"
1312+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $5)], joinType=[left])\n"
1313+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1314+
+ " LogicalProject(P_PARTKEY=[$0], EXPR$0=[CASE(IS NOT NULL($2), $2, 0)])\n"
1315+
+ " LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])\n"
1316+
+ " LogicalAggregate(group=[{0}])\n"
1317+
+ " LogicalProject(PS_PARTKEY=[$0])\n"
1318+
+ " LogicalTableScan(table=[[TPCH, PARTSUPP]])\n"
1319+
+ " LogicalAggregate(group=[{0}], EXPR$0=[COUNT()])\n"
1320+
+ " LogicalProject(P_PARTKEY=[$0])\n"
1321+
+ " LogicalFilter(condition=[IS NOT NULL($0)])\n"
1322+
+ " LogicalTableScan(table=[[TPCH, PART]])\n";
1323+
assertThat(after, hasTree(planAfter));
1324+
}
1325+
12161326
private void checkQuery(int i) {
12171327
query(i).runs();
12181328
}

0 commit comments

Comments
 (0)