[英]Calcite does not return correct SqlKind
我正在嘗試使用 Apache Calcite 來解析 SQL 語句,我發現它沒有為“avg”、“sum”等函數提供正確的 SqlKind。
這是代碼片段,
public void test() throws SqlParseException {
String sql = "select avg(age) from foobar";
SqlParser parser = SqlParser.create(sql);
SqlNode root = parser.parseQuery();
SqlSelect ss = (SqlSelect) root;
SqlNodeList snl = ss.getSelectList();
SqlBasicCall sbc = (SqlBasicCall) snl.get(0);
System.out.println(sbc.getOperator().kind); // OTHER_FUNCTION
}
我期待它會返回“SqlKind.AVG”,不幸的是,它給出了“SqlKind.OTHER_FUNCTION”。
我在這里做錯了嗎?
如果您評估sbc.getOperator()
結果將是SqlUnresolvedFunction
。 這是因為您有一個未解決的 AST。 要解決它,您需要通過驗證器運行它。 驗證器派生類型並在運算符表中查找運算符。
將解析和驗證拆分為單獨的步驟是一項功能,而不是錯誤。 當我們構建 Calcite 時,我們做出了一個有意的設計選擇,即解析器只會解析,而不是嘗試任何語義分析。 這使得解析器更簡單、更快、更可預測。
我擴展了您的示例以創建驗證器並驗證 AST:
public static void test() throws SqlParseException {
String sql = "select avg(age) from foobar";
SqlParser parser = SqlParser.create(sql);
SqlNode root = parser.parseQuery();
SqlSelect ss = (SqlSelect) root;
SqlNodeList snl = ss.getSelectList();
SqlBasicCall sbc = (SqlBasicCall) snl.get(0);
System.out.println(sbc.getOperator().kind); // prints "OTHER_FUNCTION"
SqlTypeFactoryImpl typeFactory =
new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
RelDataType rowType = typeFactory.builder()
.add("age", SqlTypeName.INTEGER)
.build();
CalciteCatalogReader catalogReader =
SqlValidatorUtil.createSingleTableCatalogReader(false,
"foobar", typeFactory, rowType);
SqlOperatorTable operatorTable =
SqlStdOperatorTable.instance();
SqlValidator.Config config = SqlValidator.Config.DEFAULT;
SqlValidator validator =
SqlValidatorUtil.newValidator(operatorTable,
catalogReader, typeFactory, config);
SqlNode validatedRoot = validator.validate(root);
ss = (SqlSelect) validatedRoot;
snl = ss.getSelectList();
sbc = (SqlBasicCall) snl.get(0);
System.out.println(sbc.getOperator().kind); // prints "AVG"
System.out.println(validator.getValidatedNodeType(ss)); // prints "RecordType(INTEGER EXPR$0)"
}
如您所見,驗證器 ( validatedRoot
) 的輸出也是SqlNode
對象樹,但sbc
內的運算符已重新分配,現在是SqlAvgAggFunction
的一個實例。
最后一行顯示了如何通過調用validator.getValidatedNodeType
來獲取SqlNode
的類型。 驗證器只保留稍后需要的表達式類型,因此它適用於某些 AST 節點,但不是全部。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.