gpt4 book ai didi

java - apache calcite 区分列名和表名

转载 作者:行者123 更新时间:2023-11-30 07:22:43 28 4
gpt4 key购买 nike

我正在实现一个简单的应用程序,它可以更改 SQL 语句中的列名称(并保留表名称)。该语句作为 String 传递,修改后的语句也作为 String 返回,不涉及数据库连接。

为了实现这一点,我使用 Apache Calcite 的 SQL 解析器。我将 SQL 字符串解析到 SqlNode,接受创建重命名的 SqlNodeSqlVisitor,然后将所有内容写回 String(使用SqlNode.toSqlString())。

问题是我不知道在接受 SqlVisitor 时如何区分解析的 SqlNode 对象中的列和表之间的区别。两者都表示为 SqlIdentifier,具有相同的 SqlKind。因此,当SqlVisitor访问SqlIdentifier时,它会重命名它,无论它是列还是表。

private String changeNames(String str) throws SqlParseException {
SqlShuttle visitor = new SqlShuttle() {
private String rename(String str) {
return str + "-test";
}

@Override
public SqlNode visit(SqlIdentifier identifier) {
SqlIdentifier output = new SqlIdentifier(rename(identifier.getSimple()), identifier.getCollation(), identifier.getParserPosition());
return output;
}
};

SqlParser.ConfigBuilder configBuilder = SqlParser.configBuilder();
configBuilder.setLex(Lex.MYSQL);
SqlParser.Config config = configBuilder.build();

SqlParser parser = SqlParser.create(str, config);
SqlNode parsedStatement = parser.parseQuery(str);
SqlNode outputNode = parsedStatement.accept(visitor);

return outputNode.toSqlString(SqlDialect.DUMMY).getSql();
}

例如

SELECT name, address, age FROM mytablename WHERE age = 23 AND name = 'John'

将修改为

SELECT `name-test`, `address-test`, `age-test` FROM `mytablename-test` WHERE `age-test` = 23 AND `name-test` = 'John'

如何判断给定的 SqlIdentifier 是列还是表?

最佳答案

要解析表和列的标识符并确定它们的类型,您需要使用 Calcite 的 validator (SqlValidator)。 validator 理解 SQL 名称解析规则(例如,FROM 子句中的别名是否可以在子查询中看到),而我们故意不让解析器及其生成的 SqlNode 数据结构了解诸如此类的事情。

validator 中的两个关键概念是范围 (SqlValidatorScope) 和命名空间 (SqlValidatorNamespace)。

范围是您所处的位置并尝试解析标识符。例如,您可能位于查询的 SELECT 子句中。或者在特定子查询的 WHERE 子句中。您将能够在不同范围内看到不同的表和列集合。即使 GROUP BY 子句和 ORDER BY 子句也有不同的范围。

命名空间看起来像一个表,并且有一个列列表。它可能是一个表,或者 FROM 子句中的子查询。如果您在某个范围内,则可以查找表别名,获取命名空间,然后查看它有哪些列。

出于您的目的,如果有一个 SqlShuttle 的变体能够准确地知道您所在的范围,以及您可以在哪里要求将标识符扩展到表和列引用,那么将会很有用。不幸的是还没有人 build 出这样的东西。

关于java - apache calcite 区分列名和表名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37288184/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com