|
27 | 27 | import org.apache.calcite.rel.RelFieldCollation.Direction; |
28 | 28 | import org.apache.calcite.rel.RelFieldCollation.NullDirection; |
29 | 29 | import org.apache.calcite.rel.RelNode; |
| 30 | +import org.apache.calcite.rel.RelRoot; |
30 | 31 | import org.apache.calcite.rel.core.JoinRelType; |
31 | 32 | import org.apache.calcite.rel.hint.HintPredicates; |
32 | 33 | import org.apache.calcite.rel.hint.HintStrategyTable; |
33 | 34 | import org.apache.calcite.rel.hint.RelHint; |
34 | 35 | import org.apache.calcite.rel.logical.LogicalAggregate; |
35 | 36 | import org.apache.calcite.rel.logical.LogicalFilter; |
| 37 | +import org.apache.calcite.rel.logical.LogicalProject; |
36 | 38 | import org.apache.calcite.rel.rules.AggregateJoinTransposeRule; |
37 | 39 | import org.apache.calcite.rel.rules.AggregateProjectMergeRule; |
38 | 40 | import org.apache.calcite.rel.rules.CoreRules; |
|
42 | 44 | import org.apache.calcite.rel.rules.PruneEmptyRules; |
43 | 45 | import org.apache.calcite.rel.type.RelDataType; |
44 | 46 | import org.apache.calcite.rel.type.RelDataTypeFactory; |
| 47 | +import org.apache.calcite.rel.type.RelDataTypeField; |
| 48 | +import org.apache.calcite.rel.type.RelDataTypeFieldImpl; |
45 | 49 | import org.apache.calcite.rel.type.RelDataTypeSystem; |
46 | 50 | import org.apache.calcite.rel.type.RelDataTypeSystemImpl; |
| 51 | +import org.apache.calcite.rel.type.RelRecordType; |
47 | 52 | import org.apache.calcite.runtime.FlatLists; |
48 | 53 | import org.apache.calcite.runtime.Hook; |
49 | 54 | import org.apache.calcite.schema.SchemaPlus; |
50 | 55 | import org.apache.calcite.sql.SqlCall; |
51 | 56 | import org.apache.calcite.sql.SqlDialect; |
52 | 57 | import org.apache.calcite.sql.SqlDialect.DatabaseProduct; |
| 58 | +import org.apache.calcite.sql.SqlKind; |
53 | 59 | import org.apache.calcite.sql.SqlNode; |
54 | 60 | import org.apache.calcite.sql.SqlSelect; |
55 | 61 | import org.apache.calcite.sql.SqlWriter; |
|
99 | 105 |
|
100 | 106 | import java.math.BigDecimal; |
101 | 107 | import java.util.Collection; |
| 108 | +import java.util.Collections; |
102 | 109 | import java.util.List; |
103 | 110 | import java.util.Map; |
104 | 111 | import java.util.Set; |
|
114 | 121 | import static org.hamcrest.CoreMatchers.notNullValue; |
115 | 122 | import static org.hamcrest.MatcherAssert.assertThat; |
116 | 123 | import static org.hamcrest.Matchers.hasToString; |
| 124 | +import static org.junit.jupiter.api.Assertions.assertEquals; |
117 | 125 | import static org.junit.jupiter.api.Assertions.assertFalse; |
| 126 | +import static org.junit.jupiter.api.Assertions.assertInstanceOf; |
| 127 | +import static org.junit.jupiter.api.Assertions.assertNotEquals; |
118 | 128 | import static org.junit.jupiter.api.Assertions.assertTrue; |
119 | 129 |
|
120 | 130 | /** |
@@ -9315,6 +9325,83 @@ private void checkLiteral2(String expression, String expected) { |
9315 | 9325 | } |
9316 | 9326 |
|
9317 | 9327 |
|
| 9328 | + /** Test case for |
| 9329 | + * <a href="https://issues.apache.org/jira/browse/CALCITE-6877">[CALCITE-6877] |
| 9330 | + * Generate LogicalProject in RelRoot.project() when mapping is not name trivial</a>. */ |
| 9331 | + @Test void testRelRootProjectForceNonNameTrivial() { |
| 9332 | + final SchemaPlus rootSchema = Frameworks.createRootSchema(true); |
| 9333 | + final SchemaPlus defaultSchema = |
| 9334 | + CalciteAssert.addSchema(rootSchema, CalciteAssert.SchemaSpec.HR); |
| 9335 | + final FrameworkConfig frameworkConfig = RelBuilderTest.config() |
| 9336 | + .defaultSchema(defaultSchema) |
| 9337 | + .build(); |
| 9338 | + final RelBuilder relBuilder = RelBuilder.create(frameworkConfig); |
| 9339 | + final RelNode inputRel = relBuilder.scan("emps") |
| 9340 | + .project(relBuilder.fields(Collections.singletonList("empid"))).build(); |
| 9341 | + |
| 9342 | + final List<RelDataTypeField> fields = |
| 9343 | + Collections.singletonList( |
| 9344 | + // rename empid to empno via RelRoot |
| 9345 | + new RelDataTypeFieldImpl("empno", |
| 9346 | + inputRel.getRowType().getFieldList().get(0).getIndex(), |
| 9347 | + inputRel.getRowType().getFieldList().get(0).getType())); |
| 9348 | + |
| 9349 | + final RelRoot root = RelRoot.of(inputRel, new RelRecordType(fields), SqlKind.SELECT); |
| 9350 | + |
| 9351 | + // inner LogicalProject selects one field and RelRoot only has one field |
| 9352 | + assertTrue(root.isRefTrivial()); |
| 9353 | + |
| 9354 | + // inner LogicalProject has different field name than RelRoot |
| 9355 | + assertFalse(root.isNameTrivial()); |
| 9356 | + |
| 9357 | + final RelNode project = root.project(); |
| 9358 | + assertEquals(inputRel, project); |
| 9359 | + |
| 9360 | + // regular project() and force project() are different |
| 9361 | + final RelNode forceProject = root.project(true); |
| 9362 | + assertNotEquals(project, forceProject); |
| 9363 | + |
| 9364 | + // new LogicalProject on top of inputRel |
| 9365 | + assertInstanceOf(LogicalProject.class, forceProject); |
| 9366 | + assertEquals(inputRel, forceProject.getInput(0)); |
| 9367 | + |
| 9368 | + // new LogicalProject renames field |
| 9369 | + if (forceProject instanceof LogicalProject) { |
| 9370 | + assertEquals("empno", |
| 9371 | + ((LogicalProject) forceProject).getNamedProjects().get(0).getValue()); |
| 9372 | + } |
| 9373 | + } |
| 9374 | + |
| 9375 | + /** Test case for |
| 9376 | + * <a href="https://issues.apache.org/jira/browse/CALCITE-6877">[CALCITE-6877] |
| 9377 | + * Generate LogicalProject in RelRoot.project() when mapping is not name trivial</a>. */ |
| 9378 | + @Test void testRelRootProjectForceNameTrivial() { |
| 9379 | + final SchemaPlus rootSchema = Frameworks.createRootSchema(true); |
| 9380 | + final SchemaPlus defaultSchema = |
| 9381 | + CalciteAssert.addSchema(rootSchema, CalciteAssert.SchemaSpec.HR); |
| 9382 | + final FrameworkConfig frameworkConfig = RelBuilderTest.config() |
| 9383 | + .defaultSchema(defaultSchema) |
| 9384 | + .build(); |
| 9385 | + final RelBuilder relBuilder = RelBuilder.create(frameworkConfig); |
| 9386 | + final RelNode inputRel = relBuilder.scan("emps") |
| 9387 | + .project(relBuilder.fields(Collections.singletonList("empid"))).build(); |
| 9388 | + |
| 9389 | + final RelRoot root = RelRoot.of(inputRel, SqlKind.SELECT); |
| 9390 | + |
| 9391 | + // inner LogicalProject selects one field and RelRoot only has one field |
| 9392 | + assertTrue(root.isRefTrivial()); |
| 9393 | + |
| 9394 | + // inner LogicalProject has same field name as RelRoot |
| 9395 | + assertTrue(root.isNameTrivial()); |
| 9396 | + |
| 9397 | + final RelNode project = root.project(); |
| 9398 | + assertEquals(inputRel, project); |
| 9399 | + |
| 9400 | + // regular project() and force project() are the same |
| 9401 | + final RelNode forceProject = root.project(true); |
| 9402 | + assertEquals(project, forceProject); |
| 9403 | + } |
| 9404 | + |
9318 | 9405 | /** Fluid interface to run tests. */ |
9319 | 9406 | static class Sql { |
9320 | 9407 | private final CalciteAssert.SchemaSpec schemaSpec; |
|
0 commit comments