You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Calcite SqlParser解析Spark SQL并按需扩展语法?

使用Calcite解析Spark SQL的问题与解决方案

1. 如何使用Calcite解析Spark SQL?

你尝试的代码:

Config config = SqlParser.config()
//        .withLex(Lex.MYSQL)
//        .withConformance(SqlConformanceEnum.BABEL)
        .withParserFactory(SqlDdlParserImpl.FACTORY);

SqlParser sqlParser = SqlParser.create("create temporary table test1 as select * from test",config);
SqlNode sqlNode = sqlParser.parseQuery();

执行后报错:

Caused by: org.apache.calcite.sql.parser.ddl.ParseException: Encountered "temporary" at line 1, column 8.
Was expecting one of:
"FOREIGN" ...
"OR" ...
"MATERIALIZED" ...
"SCHEMA" ...
"TABLE" ...
"TYPE" ...
"VIEW" ...
"FUNCTION" ...

at org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl.generateParseException(SqlDdlParserImpl.java:45760)
at org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl.jj_consume_token(SqlDdlParserImpl.java:45571)
at org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl.SqlCreate(SqlDdlParserImpl.java:22975)
at org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl.SqlStmt(SqlDdlParserImpl.java:3653)
at org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl.SqlStmtEof(SqlDdlParserImpl.java:4194)
at org.apache.calcite.sql.parser.ddl.SqlDdlParserImpl.parseSqlStmtEof(SqlDdlParserImpl.java:213)
at org.apache.calcite.sql.parser.SqlParser.parseQuery(SqlParser.java:172)
... 28 more

解决方案

Calcite没有官方原生的Spark SQL解析器,但可以通过以下方式适配:

  • 优先使用SqlConformanceEnum.BABEL配置,它兼容更多SQL方言特性,比默认ANSI规则更灵活。
  • 自定义Lex:基于现有Lex(如Lex.MYSQL)扩展,添加Spark SQL特有关键词,移除与Spark冲突的MySQL专属关键字。
  • 复用社区扩展:部分大数据项目(如Flink、Hive相关的Calcite扩展)已经实现了Spark方言适配,可以直接参考或复用其解析器配置。
  • 临时适配:如果仅需支持CREATE TEMPORARY TABLE这类简单语法,可以先启用Lex.MYSQL+SqlConformanceEnum.BABEL组合,后续针对Spark特有语法再单独扩展。

2. 如何按需扩展语法(比如解析create temporary table)?

你尝试的步骤:

  1. 复制Calcite中的Parser.jj文件
  2. 在parserImpls.ftl中添加SqlNode SqlCreateTempTable() :...
  3. 创建继承自SqlCall的CreateTempTable类,定义getOperator、getOperandList、unparse方法
  4. 在config.fmpp中添加相关配置
  5. 执行mvn generate-sources生成TestSqlParserImpl

执行步骤5时报错:

FMPP processing session failed.
[ERROR] Caused by: freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:
[ERROR] ==> default [in template "Parser.jj" at line 1124, column 43]
[ERROR]
[ERROR] ----
[ERROR] Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
[ERROR] ----
[ERROR]
[ERROR] ----
[ERROR] FTL stack trace ("~" means nesting-related):
[ERROR] - Failed at: #if (parser.createStatementParserMeth... [in template "Parser.jj" at line 1124, column 1]

问题分析与正确步骤

你的步骤存在关键错误:直接复制生成后的Parser.jj文件是错误的,该文件是FMPP模板生成的静态文件,包含未替换的FreeMarker变量,导致模板解析时变量缺失。正确的扩展流程如下:

  1. 基于模板文件扩展,而非复制生成后的Parser.jj
    Parser.jj是FMPP的输出产物,不能直接修改。应通过修改Calcite的模板文件(parserImpls.ftl、config.fmpp)来扩展语法。

  2. 修改parserImpls.ftl添加解析规则
    在SqlCreate方法中添加TEMPORARY分支,示例:

    SqlNode SqlCreate() :
    {
        SqlNode node;
    }
    {
        <#if parser.createStatementParserMethods??>
            <#list parser.createStatementParserMethods as m>
                ( <m.name>() )
                { node = $1; }
            </#list>
        </#if>
        | ( "CREATE"
            ( "TEMPORARY" )?
            "TABLE"
            <#-- 原有表创建的解析逻辑 -->
        )
        { node = new CreateTempTable(...); }
    }
    
  3. 完善config.fmpp配置
    确保在配置中声明新增的解析方法,同时补全所有模板变量的默认值:

    parser.createStatementParserMethods = [
      {name: "SqlCreateTempTable"}
    ]
    
  4. 实现对应的SqlCall与Operator
    CreateTempTable类需正确关联SqlOperator,并实现getOperandList、unparse等方法,保证语法解析与输出的一致性。

  5. 重新生成解析器
    执行mvn generate-sources前,确认FMPP配置路径正确,所有模板变量均已定义,避免变量缺失问题。

错误原因

直接复制Parser.jj后,文件中的FreeMarker模板变量(如${default})未被FMPP替换,导致模板解析时无法找到变量值,从而抛出InvalidReferenceException。


内容的提问来源于stack exchange,提问作者user25300193

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:43:17