如何在没有架构信息的情况下从 RelBuild 构建 sql?
how to build sql from RelBuild without schema info?
我想生成 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();
但如果我不设置架构,将抛出 table 未找到的异常。
有什么方法可以在没有架构信息的情况下生成 sql。
目标是生成 sql。只生成 sql.
回复第一个答案。因为评论字符长度限制。
我的场景是商业智能。 DataSource可以有很多,比如Hive、ClickHouse等等。而且还有很多table。我还需要动态删除或添加数据源。所以我认为让 Calcite 了解所有数据源是不合适的。我还有两个问题:
- 如何创建 'free-standing' table 对象
- 检查是否可以使用 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());
RelBuilder
中只有一种方法使用 RelOptSchema
:scan(String...)
(及其变体 Scan(Iterable<String>)
)。当您认为 RelOptSchema
的目的是作为目录服务,转换 table 名称(或 table 路径,由符合目录的 table 名称组成时,这是有道理的and/or 模式名称)转换为 RelOptTable
对象。
如果您有 'free-standing' table 对象无法通过命名空间访问,那么您可以直接创建 TableScan
关系表达式,然后调用 RelBuilder.push(RelNode)
将它们添加到堆栈。由于您从不调用 RelBuilder.scan
,因此您可以使用 null RelOptSchema
.
创建 RelBuilder
但在您的情况下,您似乎没有独立的 table 对象。这对 Calcite 来说是个问题,因为它需要知道您的“EMP”table 有一个名为“DEPTNO”的字段并且它的类型为 INTEGER
.
所以我建议您创建一个 'virtual' 模式,其中包含类型信息但不一定由真实的 table 支持。 MockCatalogReader
class,在 Calcite 的几个测试中使用,是一个很好的例子。
我想生成 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();
但如果我不设置架构,将抛出 table 未找到的异常。 有什么方法可以在没有架构信息的情况下生成 sql。
目标是生成 sql。只生成 sql.
回复第一个答案。因为评论字符长度限制。
我的场景是商业智能。 DataSource可以有很多,比如Hive、ClickHouse等等。而且还有很多table。我还需要动态删除或添加数据源。所以我认为让 Calcite 了解所有数据源是不合适的。我还有两个问题:
- 如何创建 'free-standing' table 对象
- 检查是否可以使用 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());
RelBuilder
中只有一种方法使用 RelOptSchema
:scan(String...)
(及其变体 Scan(Iterable<String>)
)。当您认为 RelOptSchema
的目的是作为目录服务,转换 table 名称(或 table 路径,由符合目录的 table 名称组成时,这是有道理的and/or 模式名称)转换为 RelOptTable
对象。
如果您有 'free-standing' table 对象无法通过命名空间访问,那么您可以直接创建 TableScan
关系表达式,然后调用 RelBuilder.push(RelNode)
将它们添加到堆栈。由于您从不调用 RelBuilder.scan
,因此您可以使用 null RelOptSchema
.
RelBuilder
但在您的情况下,您似乎没有独立的 table 对象。这对 Calcite 来说是个问题,因为它需要知道您的“EMP”table 有一个名为“DEPTNO”的字段并且它的类型为 INTEGER
.
所以我建议您创建一个 'virtual' 模式,其中包含类型信息但不一定由真实的 table 支持。 MockCatalogReader
class,在 Calcite 的几个测试中使用,是一个很好的例子。