diff --git a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvTableScan.java b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvTableScan.java index a667a4499d07..b47d002be284 100644 --- a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvTableScan.java +++ b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvTableScan.java @@ -25,12 +25,14 @@ import org.apache.calcite.linq4j.tree.Expressions; import org.apache.calcite.linq4j.tree.Primitive; import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelOptCost; import org.apache.calcite.plan.RelOptPlanner; import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelWriter; import org.apache.calcite.rel.core.TableScan; +import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeField; @@ -79,6 +81,11 @@ protected CsvTableScan(RelOptCluster cluster, RelOptTable table, planner.addRule(CsvProjectTableScanRule.INSTANCE); } + @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) { + return super.computeSelfCost(planner, mq) + .multiplyBy(fields.length / table.getRowType().getFieldCount()); + } + public Result implement(EnumerableRelImplementor implementor, Prefer pref) { PhysType physType = PhysTypeImpl.of( diff --git a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java index 785688b7c3b1..9fb63865cd52 100644 --- a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java +++ b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java @@ -241,6 +241,30 @@ public Void apply(ResultSet resultSet) { .ok(); } + @Test public void testPushDownProjectAggregate() throws SQLException { + sql("smart", "explain plan for select gender, count(*) from EMPS group by gender") + .returns("PLAN=EnumerableAggregate(group=[{0}], EXPR$1=[COUNT()])\n" + + " CsvTableScan(table=[[SALES, EMPS]], fields=[[3]])\n") + .ok(); + } + + @Test public void testPushDownProjectAggregateWithFilter() throws SQLException { + sql("smart", "explain plan for select max(empno) from EMPS where gender='F'") + .returns("PLAN=EnumerableAggregate(group=[{}], EXPR$0=[MAX($0)])\n" + + " EnumerableCalc(expr#0..1=[{inputs}], expr#2=['F'], expr#3=[=($t1, $t2)], proj#0..1=[{exprs}], $condition=[$t3])\n" + + " CsvTableScan(table=[[SALES, EMPS]], fields=[[0, 3]])\n") + .ok(); + } + + @Test public void testPushDownProjectAggregateNested() throws SQLException { + sql("smart", "explain plan for select gender, max(qty) from\n" + + "(select name, gender, count(*) qty from EMPS group by name, gender) t group by gender") + .returns("PLAN=EnumerableAggregate(group=[{1}], EXPR$1=[MAX($2)])\n" + + " EnumerableAggregate(group=[{0, 1}], QTY=[COUNT()])\n" + + " CsvTableScan(table=[[SALES, EMPS]], fields=[[1, 3]])\n") + .ok(); + } + @Test public void testFilterableSelect() throws SQLException { sql("filterable-model", "select name from EMPS").ok(); }