簡體   English   中英

Calcite 不返回正確的 SqlKind

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM