我正在實現一個簡單的應用程序,它可以在SQL語句中更改列名稱(並且只保留表名)。該語句作爲String
傳遞,修改後的語句也作爲String
返回,不涉及數據庫連接。apache方解石區分表名稱的列名稱
爲了達到這個目的,我使用了Apache Calcite的SQL解析器。我將SQL字符串解析爲SqlNode
,接受SqlVisitor
創建重命名爲SqlNode
,然後將所有內容寫回到String
(使用SqlNode.toSqlString()
)。
問題是我不知道如何區分解析的SqlNode
對象中的列和表之間的區別,同時接受SqlVisitor
。兩者都表示爲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
是一列或表?
SqlScopedShuttle呢? –
SqlScopedShuttle聽起來很有用,但它不會像你想要的那麼多。當你遞歸到樹中時,它只保留一堆AST節點(SqlNode)。它並不知道SQL範圍規則的任何內容。 –