Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@
import org.apache.calcite.plan.hep.HepProgram;
import org.apache.calcite.plan.hep.HepProgramBuilder;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.logical.LogicalCalc;
import org.apache.calcite.rel.rules.CoreRules;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexInputRef;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexProgramBuilder;
import org.apache.calcite.rex.RexSimplify;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
Expand Down Expand Up @@ -80,9 +83,20 @@ public class MaterializedViewSubstitutionVisitorTest {
@Override protected List<RelNode> optimize(RelNode queryRel,
List<RelOptMaterialization> materializationList) {
RelOptMaterialization materialization = materializationList.get(0);
RelNode materializedRel = canonicalize(materialization.queryRel);
RelNode normalQueryRel = canonicalize(queryRel);
if (!(normalQueryRel instanceof LogicalCalc) && materializedRel instanceof LogicalCalc) {
final RelDataType rowType = normalQueryRel.getRowType();
final RexProgramBuilder programBuilder =
new RexProgramBuilder(rowType, normalQueryRel.getCluster().getRexBuilder());
final List<RelDataTypeField> queryFields = rowType.getFieldList();
for (int i = 0; i < queryFields.size(); i++) {
programBuilder.addProject(RexInputRef.of(i, rowType), queryFields.get(i).getName());
}
normalQueryRel = LogicalCalc.create(normalQueryRel, programBuilder.getProgram());
}
SubstitutionVisitor substitutionVisitor =
new SubstitutionVisitor(canonicalize(materialization.queryRel),
canonicalize(queryRel));
new SubstitutionVisitor(materializedRel, normalQueryRel);
return substitutionVisitor
.go(materialization.tableRel);
}
Expand Down Expand Up @@ -449,6 +463,66 @@ protected final MaterializedViewFixture sql(String materialize,
sql(mv, query).noMat();
}

/**
* Need matching because query could be expressed by mv, using trim mv's unused field,
* which is the top of Aggregate.
*/
@Test void testAggregateWithCalcTopInMv() {
String mv = ""
+ "select \"deptno\", sum(\"salary\"), sum(\"commission\") + 1, sum(\"k\")\n"
+ "from\n"
+ " (select \"deptno\", \"salary\", \"commission\", 100 as \"k\"\n"
+ " from \"emps\")\n"
+ "group by \"deptno\"";
String query = ""
+ "select \"deptno\", sum(\"salary\"), sum(\"k\")\n"
+ "from\n"
+ " (select \"deptno\", \"salary\", 100 as \"k\"\n"
+ " from \"emps\")\n"
+ "group by \"deptno\"";
sql(mv, query).ok();
}

/** Similar with {@link #testAggregateWithCalcTopInMv()},
* but target's fields have no-equal sequence. */
@Test void testAggregateWithCalcTopInMv2() {
String mv = ""
+ "select \"deptno\", sum(\"commission\") + 1, sum(\"k\"), sum(\"salary\")\n"
+ "from\n"
+ " (select \"deptno\", \"salary\", \"commission\", 100 as \"k\"\n"
+ " from \"emps\")\n"
+ "group by \"deptno\"";
String query = ""
+ "select \"deptno\", sum(\"salary\"), sum(\"k\")\n"
+ "from\n"
+ " (select \"deptno\", \"salary\", 100 as \"k\"\n"
+ " from \"emps\")\n"
+ "group by \"deptno\"";
sql(mv, query).ok();
}

/**
* Need matching because query could be expressed by mv, using trim mv's unused field,
* which is the top of Union.
*/
@Test void testUnionWithCalcTopInMv() {
String mv = ""
+ "select \"deptno\", \"salary\", 'hello' as \"k\"\n"
+ "from ("
+ "select \"deptno\", \"salary\"\n"
+ "from \"emps\"\n"
+ "union\n"
+ "select \"deptno\", \"salary\"\n"
+ "from \"emps\")";
String query = ""
+ "select \"deptno\", \"salary\"\n"
+ "from \"emps\"\n"
+ "union\n"
+ "select \"deptno\", \"salary\"\n"
+ "from \"emps\"";
sql(mv, query).ok();
}

/**
* There will be a compensating Project added after matching of the Aggregate.
* This rule targets to test if the Calc can be handled.
Expand Down Expand Up @@ -861,11 +935,14 @@ protected final MaterializedViewFixture sql(String materialize,
String m = "select * from \"emps\" where \"empid\" < 500";
sql(m, q)
.checkingThatResultContains(""
+ "LogicalUnion(all=[true])\n"
+ " LogicalCalc(expr#0..4=[{inputs}], expr#5=[300], expr#6=[>($t0, $t5)], proj#0..4=[{exprs}], $condition=[$t6])\n"
+ " LogicalTableScan(table=[[hr, emps]])\n"
+ " LogicalCalc(expr#0..4=[{inputs}], expr#5=[200], expr#6=[<($t0, $t5)], proj#0..4=[{exprs}], $condition=[$t6])\n"
+ " EnumerableTableScan(table=[[hr, MV0]])")
+ "LogicalCalc(expr#0..4=[{inputs}], proj#0..4=[{exprs}])\n"
+ " LogicalUnion(all=[true])\n"
+ " LogicalCalc(expr#0..4=[{inputs}], expr#5=[300], expr#6=[>($t0, $t5)], proj#0."
+ ".4=[{exprs}], $condition=[$t6])\n"
+ " LogicalTableScan(table=[[hr, emps]])\n"
+ " LogicalCalc(expr#0..4=[{inputs}], expr#5=[200], expr#6=[<($t0, $t5)], proj#0."
+ ".4=[{exprs}], $condition=[$t6])\n"
+ " EnumerableTableScan(table=[[hr, MV0]])")
.ok();
}

Expand Down