初步剖析Calcite执行链路(源码入手)

coverImg

介绍

calcite是使用javcc+FreeMarker集成的,借助FreeMarker支持用户自定义自己的语义、语法分析及处理,扩展性极强。

calcite基于javacc扩展的解析SQL的实现在core包中:

前置知识学习:03、编译原理实践 - JavaCC解析表达式并生成抽象语法树、自定义Calcite的SQL语法后再来尝试阅读源码

关于Parser.jj中的${xxx}来源

变量参数均来自:

例如:${parser.class}指的就是自定义类名

入口是什么?

我们在使用calcite解析的时候是如下代码操作的:

public static void main(String[] args) throws SqlParseException {
    // 解析配置 - mysql设置
    SqlParser.Config mysqlConfig = SqlParser.configBuilder()
            // 定义解析工厂
            .setParserFactory(SqlParserImpl.FACTORY)
            .setLex(Lex.MYSQL)
            .build();
    // 创建解析器
    SqlParser parser = SqlParser.create("", mysqlConfig);
    // Sql语句
    String sql = "xxx";
    // 解析sql
    SqlNode sqlNode = parser.parseQuery(sql);
    System.out.println(sqlNode.toSqlString(OracleSqlDialect.DEFAULT));
}

核心代码:parseQuery(sql)方法

public SqlNode parseQuery(String sql) throws SqlParseException {
    this.parser.ReInit(new StringReader(sql));
    //1
    return this.parseQuery();
}

public SqlNode parseQuery() throws SqlParseException {
    try {
        //2、自定义parseSqlStmtEof
        return this.parser.parseSqlStmtEof();
    } catch (Throwable var2) {
        Throwable ex = var2;
        throw this.handleException(ex);
    }
}

这个parseSqlStmtEof()从何而来?Parser.jj中定义好的

看下下面解析实现:可以看到优先匹配的是我们自定义部分

parser.statementParserMethods

对应的就是config.fmpp中配置的:

自定义模板替换

模板替换:

评论区请在客户端页面查看