本节摘要:语法分析是 Driver 编译流水线的第一关:把 HQL 字符串切成 token 流,再按文法规则归约成一棵抽象语法树(AST)。本节展示 AST 的形状、子查询与表达式在树上的嵌套方式、语法错误的报错特征,以及为什么 SQL 审计与血缘工具都从 AST 下手。
你在 Beeline 里敲下的查询,在 Driver 眼里只是一段带换行的字符序列:
SELECT region, SUM(amount) FROM orders WHERE dt = '2026-01-15' AND amount > 50 GROUP BY region HAVING SUM(amount) > 100;
第一步是词法分析:扫描字符流,把有意义的最小单元切成 token。SELECT 是关键字,region 是标识符,逗号是分隔符,'2026-01-15' 是字符串字面量,50 是数字字面量。大小写在这一步被归一(HQL 关键字不区分大小写),注释被剥掉,多余空白被压缩。
第二步是语法分析:解析器按 HQL 文法把 token 流归约成树。ANTLR 生成的解析器逐条尝试归约规则,遇到无法归约的情况立即报语法错误,报错信息会给出出错 token 的位置——这是"括号不配对""关键字拼错"类问题的拦截点。
归约出的 AST 大致是这个形状(简化示意):

看懂这棵树有三个实用结论:
第一,AST 不含任何事实信息。TOK_TABREF 节点只记了一个名字 orders,不知道这张表存不存在、有几列。所以语法分析通过的查询完全可能下一秒就报"表不存在"——那是语义分析的事。
第二,表达式的嵌套就是树的嵌套。amount 大于 50 与 dt 等值条件构成 AND 节点的两个子树;SUM(amount) 是一个函数节点包着一个列引用节点。后面优化器改写谓词、下推过滤,操作的都是这些子树。
第三,子查询是树上的 TOK_SUBQUERY 节点,里面又包一棵完整的 TOK_QUERY。这就是为什么子查询可以任意嵌套但别太深——每层嵌套都是一棵要独立走完后续编译流程的树。
Hive 提供了一个不算广为人知的开关,可以把解析结果打出来:
SET hive.parse.expr.string.literal=true;
更直接的方式是用 EXPLAIN 的扩展形态观察解析产物,或者使用带 ANTLR 工具链的客户端插件。对学习而言,理解结构比拿到原始输出更重要;对工程而言,AST 的主要消费者不是人,是工具。
SQL 审计系统、血缘分析、自动改写(比如把 SELECT * 替换为显式列清单)这类工具,第一件事都是解析出 AST:只有树化之后,"这个查询引用了哪些表哪些列"才能用遍历算法精确回答,正则匹配在稍复杂的嵌套面前不堪一击。你以后看到数据平台能自动生成血缘图,底层就是 AST 遍历加规则提取。
制造一个错误体验一下:
SELECT region, SUM(amount FROM orders;
报错大意是 cannot recognize input near 'FROM' 'orders' '<EOF>' in expression specification,并带出错位置。特征是:报错发生在任何表名核对之前——把 orders 换成不存在的表名,报错一模一样。这说明拦截发生在语法关,还没到语义关。反过来,如果报错是 Invalid table name 或 Column 'region1' cannot be resolved,则说明语法已通过、死在语义关。区分这两类报错,是排错的第一刀。
常见的语法关错误还有:中文字符混入(全角逗号、中文引号),报错位置往往指向"看起来没错"的地方,因为解析器把不可见的多字节字符当成了意外 token;字符串字面量里的引号未转义;以及 HiveQL 与 MySQL 方言差异,比如不支持 UPDATE 的 SET 列表写法、不支持某些窗口函数外的 ORDER BY 位置。
语法关的交付物是 AST,但它还不能直接变成执行计划——中间隔着一个"查询块"(Query Block)的转换。Driver 遍历 AST,把每个 TOK_QUERY 与 TOK_SUBQUERY 节点转成一个 QB 对象,外层查询是主 QB,子查询与视图展开后各自成块。QB 是带槽位的名册:FROM 槽记数据源、SELECT 槽记投影、WHERE 槽记过滤、GROUP 槽记分组。下一节的语义分析就是逐个槽位核对事实,把"名字"换成"真实对象"。
这个分层也解释了一个常见困惑:为什么有些错误报的是语法、有些报的是语义,而有些(比如类型不兼容的隐式转换失败)报错位置离出错写法很远——因为遍历 QB 槽位的顺序与你书写 SQL 的视觉顺序并不一致。
语法关只审"话通顺"。下一节看 Driver 如何拿着这份通顺的稿件去 Metastore 核对"事属实"。