Hi,
I am playing with the planner but I can't get it work for a very simple
query.
Th table is
MYTABLE(id integer, name varchar) definition is given in code
snippet
the query is "SELECT * FROM MYTABLE"
The error is:
org.apache.calcite.plan.RelOptPlanner$CannotPlanException: Node
[rel#7:Subset#0.NONE.[0, 1].any] could not be implemented; planner state:
Root: rel#7:Subset#0.NONE.[0, 1].any
Original rel:
LogicalProject(subset=[rel#6:Subset#1.NONE.[0, 1].any], id=[$0],
name=[$1]): rowcount = 15.0, cumulative cost = {15.0 rows, 30.0 cpu, 0.0
io}, id = 5
EnumerableTableScan(subset=[rel#4:Subset#0.ENUMERABLE.[0, 1].any],
table=[[default, MYTABLE]]): rowcount = 15.0, cumulative cost = {15.0 rows,
16.0 cpu, 0.0 io}, id = 2
Sets:
Set#0, type: RecordType(INTEGER id, VARCHAR name)
rel#4:Subset#0.ENUMERABLE.[0, 1].any, best=rel#2, importance=0.9
rel#2:EnumerableTableScan.ENUMERABLE.[[0, 1]].any(table=[default,
MYTABLE]), rowcount=15.0, cumulative cost={15.0 rows, 16.0 cpu, 0.0 io}
rel#9:EnumerableProject.ENUMERABLE.[[0,
1]].any(input=rel#4:Subset#0.ENUMERABLE.[0, 1].any,id=$0,name=$1),
rowcount=15.0, cumulative cost={30.0 rows, 46.0 cpu, 0.0 io}
rel#7:Subset#0.NONE.[0, 1].any, best=null, importance=1.0
rel#5:LogicalProject.NONE.[[0,
1]].any(input=rel#4:Subset#0.ENUMERABLE.[0, 1].any,id=$0,name=$1),
rowcount=15.0, cumulative cost={inf}
rel#8:AbstractConverter.NONE.[0,
1].any(input=rel#4:Subset#0.ENUMERABLE.[0, 1].any,convention=NONE,sort=[0,
1],dist=any), rowcount=15.0, cumulative cost={inf}
Does anybody has an hint for me ?
I am using currert master of Calcite (1.15-SNAPSHOT)
Thank you
Enrico
My code is:
@Test
public void test() throws Exception {
Table table = new TableImpl();
CalciteSchema schema = CalciteSchema.createRootSchema(true, true,
"default");
schema.add("MYTABLE", table);
SchemaPlus rootSchema = schema.plus();
SqlRexConvertletTable convertletTable =
StandardConvertletTable.INSTANCE;
SqlToRelConverter.Config config = SqlToRelConverter.Config.DEFAULT;
FrameworkConfig frameworkConfig = new FrameworkConfigImpl(config,
rootSchema, convertletTable);
Planner imp = Frameworks.getPlanner(frameworkConfig);
SqlNode sqlNode = imp.parse("SELECT * FROM MYTABLE");
sqlNode = imp.validate(sqlNode);
RelRoot relRoot = imp.rel(sqlNode);
RelNode project = relRoot.project();
RelOptPlanner planner = project.getCluster().getPlanner();
planner.setRoot(project);
RelNode findBestExp = planner.findBestExp();
System.out.println("best:" + findBestExp);
}
private class FrameworkConfigImpl implements FrameworkConfig {
private final SqlToRelConverter.Config config;
private final SchemaPlus rootSchema;
private final SqlRexConvertletTable convertletTable;
public FrameworkConfigImpl(SqlToRelConverter.Config config,
SchemaPlus rootSchema, SqlRexConvertletTable convertletTable) {
this.config = config;
this.rootSchema = rootSchema;
this.convertletTable = convertletTable;
}
@Override
public SqlParser.Config getParserConfig() {
return SqlParser.Config.DEFAULT;
}
@Override
public SqlToRelConverter.Config getSqlToRelConverterConfig() {
return config;
}
@Override
public SchemaPlus getDefaultSchema() {
return rootSchema;
}
@Override
public RexExecutor getExecutor() {
return new RexExecutorImpl(new DataContextImpl());
}
@Override
public ImmutableList<Program> getPrograms() {
return ImmutableList.of(Programs.standard());
}
@Override
public SqlOperatorTable getOperatorTable() {
return new SqlStdOperatorTable();
}
@Override
public RelOptCostFactory getCostFactory() {
return null;
}
@Override
public ImmutableList<RelTraitDef> getTraitDefs() {
return ImmutableList.of(ConventionTraitDef.INSTANCE,
RelCollationTraitDef.INSTANCE,
RelDistributionTraitDef.INSTANCE
);
}
@Override
public SqlRexConvertletTable getConvertletTable() {
return convertletTable;
}
@Override
public Context getContext() {
return new ContextImpl();
}
@Override
public RelDataTypeSystem getTypeSystem() {
return RelDataTypeSystem.DEFAULT;
}
class DataContextImpl implements DataContext {
public DataContextImpl() {
}
@Override
public SchemaPlus getRootSchema() {
return rootSchema;
}
@Override
public JavaTypeFactory getTypeFactory() {
throw new UnsupportedOperationException("Not supported
yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public QueryProvider getQueryProvider() {
throw new UnsupportedOperationException("Not supported
yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Object get(String name) {
throw new UnsupportedOperationException("Not supported
yet."); //To change body of generated methods, choose Tools | Templates.
}
}
private class ContextImpl implements Context {
public ContextImpl() {
}
@Override
public <C> C unwrap(Class<C> aClass) {
return null;
}
}
}
private static class TableImpl implements Table {
public TableImpl() {
}
@Override
public RelDataType getRowType(RelDataTypeFactory typeFactory) {
return typeFactory
.builder()
.add("id",
typeFactory.createSqlType(SqlTypeName.INTEGER))
.add("name",
typeFactory.createSqlType(SqlTypeName.VARCHAR))
.build();
}
@Override
public Statistic getStatistic() {
return new StatisticImpl();
}
@Override
public Schema.TableType getJdbcTableType() {
throw new UnsupportedOperationException("Not supported yet.");
//To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean isRolledUp(String column) {
return true;
}
@Override
public boolean rolledUpColumnValidInsideAgg(String column, SqlCall
call, SqlNode parent, CalciteConnectionConfig config) {
return false;
}
class StatisticImpl implements Statistic {
public StatisticImpl() {
}
@Override
public Double getRowCount() {
return 15d;
}
@Override
public boolean isKey(ImmutableBitSet columns) {
return false;
}
@Override
public List<RelReferentialConstraint>
getReferentialConstraints() {
return Collections.emptyList();
}
@Override
public List<RelCollation> getCollations() {
RelCollation c = new RelCollationImpl(
ImmutableList.of(
new RelFieldCollation(0,
RelFieldCollation.Direction.ASCENDING),
new RelFieldCollation(1,
RelFieldCollation.Direction.ASCENDING)
)) {
};
return Arrays.asList(c);
}
@Override
public RelDistribution getDistribution() {
return RelDistributions.ANY;
}
}
}
2017-11-06 19:48 GMT+01:00 Julian Hyde <[email protected]>:
> Yes that is definitely possible. I am too busy to write a code snippet but
> you should take a look at PlannerTest.
>
> > On Nov 6, 2017, at 3:05 AM, Stéphane Campinas <
> [email protected]> wrote:
> >
> > Hi,
> >
> > I am trying to use the Volcano planner in order to optimise queries based
> > on statistics but I am having some issues understanding how to achieve
> > this, even after looking at the Github repository for tests.
> > A first goal I would like to achieve would be to choose a join
> > implementation based on its cost.
> >
> > For example, a query tree can have several joins, and depending on the
> > position of the join in the tree, an certain implementation would be more
> > efficient than another.
> > Would that be possible ? If so, could you share a code snippet ?
> >
> > Thanks
> >
> > --
> > Campinas Stéphane
>
>