xiedeyantu commented on code in PR #4544:
URL: https://github.com/apache/calcite/pull/4544#discussion_r2358676334
##########
core/src/test/java/org/apache/calcite/test/RelBuilderTest.java:
##########
@@ -5585,6 +5590,284 @@ private static RelNode
buildCorrelateWithJoin(JoinRelType type, RelBuilder build
assertThat(root, hasTree(expected));
}
+
+ @Test void testCombine() {
+ // Create two separate queries
+ final RelBuilder builder = RelBuilder.create(config().build());
+ RelNode scan1 = builder.scan("EMP")
+ .filter(builder.equals(builder.field("DEPTNO"), builder.literal(10)))
+ .project(builder.field("ENAME"))
+ .build();
+ RelNode scan2 = builder.scan("EMP")
+ .filter(builder.equals(builder.field("DEPTNO"), builder.literal(20)))
+ .project(builder.field("SAL"))
+ .build();
+
+ // Test combine with varargs
+ RelNode combine1 = builder.combine(scan1, scan2).build();
+ assertThat(combine1, instanceOf(Combine.class));
+ assertThat(combine1.getInputs(), hasSize(2));
+
+ // Test combine with Iterable
+ RelNode combine2 = builder.combine(Arrays.asList(scan1, scan2)).build();
+ assertThat(combine2, instanceOf(Combine.class));
+ assertThat(combine2.getInputs(), hasSize(2));
+
+ // Test combine with stack
+ builder.push(scan1)
+ .push(scan2);
+ RelNode combine3 = builder.combine(2).build();
+ assertThat(combine3, instanceOf(Combine.class));
+ assertThat(((Combine) combine3).getInputs(), hasSize(2));
+
+ // Test combine with all stack
+ builder.clear();
+ builder.push(scan1)
+ .push(scan2);
+ RelNode combine4 = builder.combine().build();
+ assertThat(combine4, instanceOf(Combine.class));
+ assertThat(combine4.getInputs(), hasSize(2));
+ }
+
+ @Test void testCombineWithSharedSubexpression() {
+ // Test that demonstrates how Combine can optimize queries with shared
subexpressions
+ final RelBuilder builder = RelBuilder.create(config().build());
+
+ // Create a common subexpression - employees with salary > 1000
+ builder.scan("EMP")
+ .filter(
+ builder.call(SqlStdOperatorTable.GREATER_THAN,
+ builder.field("SAL"), builder.literal(1000)));
+ RelNode commonSubexpr = builder.build();
+
+ // Query 1: Count high earners by department
+ RelNode query1 = builder.push(commonSubexpr)
+ .aggregate(builder.groupKey("DEPTNO"), builder.count())
+ .build();
+
+ // Query 2: Get names of high earners
+ RelNode query2 = builder.push(commonSubexpr)
+ .project(builder.field("ENAME"), builder.field("SAL"))
+ .build();
+
+ // Combine both queries - planner can recognize shared subexpression
+ RelNode combined = builder.combine(query1, query2).build();
+
+ assertThat(combined, instanceOf(Combine.class));
+ assertThat(combined.getInputs(), hasSize(2));
+ // Both queries share the same filter as their base
Review Comment:
@asolimando 's question is also what I want to know, but I still have some
additional questions.
I found that currently we need to explicitly create Combine operators to
form shared operators. If I have multiple plans, how can I send multiple plans
into the volcano planner simultaneously? Should I wrap multiple RelRoots with
Combine?
Because I understand this capability is only available in the volcano
planner and not really necessary in the Hep planner. If we're in the volcano
planner, can we automatically add Combine operators using passThrough and
derive capabilities? Similar to how we add Exchange or Sort operators.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]