【问题标题】:how to build sql from RelBuild without schema info?如何在没有架构信息的情况下从 RelBuild 构建 sql?
【发布时间】:2022-01-24 09:05:25
【问题描述】:

我想使用方解石生成 sql。像这样

org.apache.calcite.rel.rel2sql.RelToSqlConverterTest#testAntiJoin

final FrameworkConfig frameworkConfig = Frameworks.newConfigBuilder()
       .parserConfig(SqlParser.Config.DEFAULT)
//       .defaultSchema(schema)
       .build();

final RelBuilder builder = RelBuilder.create(frameworkConfig);

final RelBuilder builder = relBuilder();
final RelNode root = builder
       .scan("DEPT")
        .scan("EMP")
        .join(
            JoinRelType.ANTI, builder.equals(
              builder.field(2, 1, "DEPTNO"),
              builder.field(2, 0, "DEPTNO")))
        .project(builder.field("DEPTNO"))
        .build();

但如果我不设置架构,则会抛出未找到的异常表。 有没有办法在没有架构信息的情况下生成 sql。

目的是生成sql。只生成sql。



回复第一个答案。因为评论字符长度限制。

我的场景是商业智能。 DataSource可以有很多,比如Hive、ClickHouse等。而且有很多桌子。我还需要动态删除或添加数据源。所以我认为 Calcite 不适合了解所有数据源。我还有两个问题:

  1. 如您所说,如何创建“独立式”表格对象
  2. 检查是否可以使用 SqlNode 来执行此操作。例如:
        SqlIdentifier from = new SqlIdentifier("testTable", SqlParserPos.QUOTED_ZERO);
        SqlNode[] nodes = new SqlNode[2];
        nodes[0] = new SqlIdentifier("a", SqlParserPos.QUOTED_ZERO);
        nodes[1] = SqlLiteral.createExactNumeric("1", SqlParserPos.QUOTED_ZERO);
        SqlNode where = new SqlBasicCall(SqlStdOperatorTable.EQUALS, nodes, SqlParserPos.QUOTED_ZERO);
        SqlIdentifier selectNode = new SqlIdentifier("a", SqlParserPos.QUOTED_ZERO);
        SqlSelect select = new SqlSelect(SqlParserPos.QUOTED_ZERO, SqlNodeList.EMPTY,
                new SqlNodeList(Arrays.asList(selectNode), SqlParserPos.QUOTED_ZERO),
                from,
                where,
                null,
                null,
                null,
                null,
                null,
                null,
                null);
        SqlString sqlString = select.toSqlString(CalciteSqlDialect.DEFAULT);
        System.out.println(sqlString.getSql());

【问题讨论】:

    标签: apache-calcite sqlbuilder


    【解决方案1】:

    RelBuilder 中只有一种方法使用RelOptSchemascan(String...)(及其变体Scan(Iterable<String>))。当您考虑 RelOptSchema 的目的是作为目录服务时,这是有道理的,将表名(或表路径,由具有目录和/或模式名称限定的表名组成)转换为 RelOptTable 对象。

    如果您有不通过命名空间访问的“独立”表对象,那么您可以直接创建TableScan 关系表达式,然后调用RelBuilder.push(RelNode) 将它们添加到堆栈中。由于您从不调用 RelBuilder.scan,因此您可以使用 null RelOptSchema 创建 RelBuilder

    但在您的情况下,您似乎没有独立的表格对象。这对 Calcite 来说是个问题,因为它需要知道您的“EMP”表有一个名为“DEPTNO”的字段,并且它的类型为 INTEGER

    所以我建议您创建一个包含类型信息但不一定由真实表支持的“虚拟”模式。在 Calcite 的几个测试中使用的 MockCatalogReader 类是一个很好的例子。

    【讨论】:

    • 请看问题。评论字符长度限制。所以我编辑了这个问题。非常感谢
    猜你喜欢
    • 2012-10-15
    • 2021-07-10
    • 1970-01-01
    • 2010-12-29
    • 2018-09-04
    • 2015-09-22
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多