Vladimir Dolzhenko created CALCITE-595:
------------------------------------------
Summary: planner doesn't care about cheaper transformation plan
Key: CALCITE-595
URL: https://issues.apache.org/jira/browse/CALCITE-595
Project: Calcite
Issue Type: Bug
Reporter: Vladimir Dolzhenko
Assignee: Julian Hyde
The rule splits the condition - the 1st part to TableScan another keeps to a
LogicalFilter.
Despite of rule execution - another plan (with split condition) even has not
been calculated - computeSelfCost executes only in case of null condition.
{code}
@Test public void testAnotherTableFilter() throws Exception {
final SchemaPlus rootSchema = Frameworks.createRootSchema(true);
rootSchema.add("ANOTHER", new AnotherTable());
final FrameworkConfig config = Frameworks.newConfigBuilder()
.parserConfig(SqlParser.Config.DEFAULT)
.defaultSchema(rootSchema)
.traitDefs((List<RelTraitDef>) null)
.programs(Programs.heuristicJoinOrder(Programs.RULE_SET, true, 2))
.build();
Planner planner = Frameworks.getPlanner(config);
SqlNode parse = planner.parse("select * from ANOTHER where name='a' AND
type='b'");
SqlNode validate = planner.validate(parse);
RelNode convert = planner.convert(validate);
RelTraitSet traitSet = planner.getEmptyTraitSet()
.replace(EnumerableConvention.INSTANCE);
RelNode transform = planner.transform(0, traitSet, convert);
final String actual = toString(transform);
assertThat(actual, containsString("EnumerableProject(NAME=[$0],
TYPE=[$1])\n" +
" EnumerableFilter(condition=[=(CAST($0):VARCHAR(1) CHARACTER SET
\"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'a')])\n" +
" AnotherTableScan(table=[[ANOTHER]])"));
}
public class AnotherTable extends AbstractTable implements TranslatableTable {
public RelNode toRel(RelOptTable.ToRelContext context,
RelOptTable relOptTable) {
return new AnotherTableScan( context.getCluster(),
context.getCluster().traitSetOf( EnumerableConvention.INSTANCE ),
relOptTable );
}
public RelDataType getRowType(RelDataTypeFactory typeFactory) {
RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder();
builder.add("NAME", typeFactory.createJavaType( String.class) );
builder.add("TYPE", typeFactory.createJavaType( String.class) );
return builder.build();
}
}
static class AnotherTableScanRule extends RelOptRule {
private AnotherTableScanRule() {
super(
operand(
LogicalFilter.class,
operand(AnotherTableScan.class, any())));
}
public void onMatch( RelOptRuleCall call ) {
final LogicalFilter filter = call.rel( 0 );
final AnotherTableScan tableScan = call.rel( 1 );
final RexNode newScanCondition = filter.getCondition();
final RelTraitSet restTableScanTraitSet = tableScan.getTraitSet();
final RelNode newTableScan = tableScan.copy( restTableScanTraitSet,
ImmutableList.<RelNode>of(), newScanCondition );
RexNode newFilterCondition =
newScanCondition.getKind() == SqlKind.AND ? RelOptUtil.conjunctions(
newScanCondition ).get( 0 ) : newScanCondition;
System.out.println(newScanCondition + " > " + newScanCondition);
final RelTraitSet filterTraitSet = filter.getTraitSet();
final RelNode wrappedFilter = filter.copy( filterTraitSet, newTableScan,
newFilterCondition );
call.transformTo( wrappedFilter );
}
}
public static class AnotherTableScan extends TableScan implements
EnumerableRel {
private final RexNode condition;
public AnotherTableScan(RelOptCluster cluster, RelTraitSet traits,
RelOptTable table) {
this(cluster, traits, table, null);
}
public AnotherTableScan(RelOptCluster cluster, RelTraitSet traits,
RelOptTable table, RexNode condition) {
super(cluster, traits, table);
this.condition = condition;
}
public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
return null;
}
@Override
public void register(RelOptPlanner planner) {
planner.addRule(new AnotherTableScanRule());
}
public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs, RexNode
condition) {
assert inputs.isEmpty();
final AnotherTableScan tableScan = new AnotherTableScan(getCluster(),
traitSet, getTable(), condition);
return tableScan;
}
@Override
public RelOptCost computeSelfCost(RelOptPlanner planner) {
final RelOptCost relOptCost = super.computeSelfCost(planner);
final RelOptCost cost = relOptCost.multiplyBy(1f /
(RelOptUtil.conjunctions(condition).size() + 1));
System.out.println(condition + " = " + cost);
return cost;
}
}
{code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)