Apache Кальцит: оптимизация и выполнение по представлению на JDB C Source - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь оптимизировать запрос из схемы JDB C (PostgreSQL), следуя этой записной книжке: https://github.com/michaelmior/calcite-notebooks/blob/master/query-optimization.ipynb

По сути, я пытаюсь оптимизировать запрос, который обращается к представлению, определенному в схеме JDB C. Однако, когда я пытаюсь выполнить оптимизированный план, я получаю исключение (подробнее см. Ниже).

У меня есть следующий файл модели:

{
  "version": "1.0",
  "defaultSchema": "tpch-view",
  "schemas": [
    {
      "type": "jdbc",
      "name": "tpch-jdbc",
      "jdbcUser": "user",
      "jdbcPassword": "pass",
      "jdbcUrl": "jdbc:postgresql://localhost/db"
    },
    {
      "name": "tpch-view",
      "tables": [
        {
          "name": "nationview",
          "type": "view",
          "sql": "SELECT * from \"tpch-jdbc\".\"nation\""
        }
        ]
    }

  ]
}

Мой кальцитовый код выглядит так:

Connection connection = DriverManager.getConnection("jdbc:calcite:model=src/main/resources/model-jdbc.json");

CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);

SchemaPlus mySchema = calciteConnection.getRootSchema().getSubSchema(connection.getSchema());

FrameworkConfig config = Frameworks.newConfigBuilder()
                .defaultSchema(mySchema)
                .build();

String query = "select * from \"nationview\"";
Planner planner = getPlanner(config);
SqlNode parse = planner.parse(query);

SqlNode validate = planner.validate(parse);
RelNode rel = planner.rel(validate).project();

HepProgram program = HepProgram.builder().build();

HepPlanner hepPlanner = new HepPlanner(program);


hepPlanner.setRoot(rel);
RelNode optimized = hepPlanner.findBestExp();
optimized.explain(rw);

RelOptCluster cluster = rel.getCluster();
VolcanoPlanner vplanner = (VolcanoPlanner) cluster.getPlanner();

RelTraitSet desiredTraits = cluster.traitSet().replace(EnumerableConvention.INSTANCE);
RelNode newRoot = vplanner.changeTraits(rel, desiredTraits);
vplanner.setRoot(newRoot);

RelNode optimized2 = vplanner.findBestExp();
optimized2.explain(rw);

ResultSet result = RelRunners.run(optimized2).executeQuery();

Я получаю следующее (соответственно, для планировщиков Hep и Volcano):

14:LogicalProject(n_nationkey=[$0], n_name=[$1], n_regionkey=[$2], n_comment=[$3])
  10:JdbcTableScan(table=[[tpch-jdbc, nation]])

31:JdbcToEnumerableConverter
  10:JdbcTableScan(table=[[tpch-jdbc, nation]])

Однако во время выполнения инструкции я получаю следующее исключение:

Exception in thread "main" java.sql.SQLException: exception while executing query: null
    at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
    at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
    at org.apache.calcite.avatica.AvaticaConnection.executeQueryInternal(AvaticaConnection.java:577)
    at org.apache.calcite.avatica.AvaticaPreparedStatement.executeQuery(AvaticaPreparedStatement.java:137)
    at JDBCTest.main(JDBCTest.java:89)
Caused by: java.lang.NullPointerException
    at Baz.bind(Unknown Source)
    at org.apache.calcite.jdbc.CalcitePrepare$CalciteSignature.enumerable(CalcitePrepare.java:355)
    at org.apache.calcite.jdbc.CalciteConnectionImpl.enumerable(CalciteConnectionImpl.java:316)
    at org.apache.calcite.jdbc.CalciteMetaImpl._createIterable(CalciteMetaImpl.java:506)
    at org.apache.calcite.jdbc.CalciteMetaImpl.createIterable(CalciteMetaImpl.java:497)
    at org.apache.calcite.avatica.AvaticaResultSet.execute(AvaticaResultSet.java:182)
    at org.apache.calcite.jdbc.CalciteResultSet.execute(CalciteResultSet.java:64)
    at org.apache.calcite.jdbc.CalciteResultSet.execute(CalciteResultSet.java:43)
    at org.apache.calcite.avatica.AvaticaConnection.executeQueryInternal(AvaticaConnection.java:573)
    ... 2 more

Почему сбой при выполнении, несмотря на то, что процедура оптимизации прошла нормально? Когда я пытаюсь сделать то же самое с видом на схему CSV, выполнение работает нормально. Кроме того, когда я пытаюсь выполнить его таким образом (без оптимизации), он также работает нормально:

Statement stmt = calciteConnection.createStatement();
String query = "select * from \"nationview\"";

SqlParser parser = SqlParser.create(query);

ResultSet resultSet = stmt.executeQuery(query);

Я забыл включить что-то? Или мне нужны дополнительные параметры конфигурации для выполнения через JDB C?

...