Skip to content

Latest commit

 

History

History
55 lines (28 loc) · 5.16 KB

3.parser-resolver.md

File metadata and controls

55 lines (28 loc) · 5.16 KB

4.2 Parser 和 Resolver 模块

Parser 模块

当一条 SQL 请求到达 Server 端后,首先经过的是 Parser 模块。Parser 模块主要作用是根据定义的语法规则判断一条 SQL 语句的格式是否符合对应的语法结构,这个语法结构无论是在 MySQL 还是 OceanBase 中,都是使用 Yacc 和 Flex 工具自动生成的。需要重点理解 Parser 模块是如何将一条用户写的 SQL 请求转换成可以在数据库内核中所使用的数据结构。

如下图所示,SQL 语句 SELECT c1+c2 FROM t1 WHERE exists 再接着一个子查询,然后子查询是由 union all 连接的另外两个子查询。Parser 模块最终解析出来的是一个逻辑结构图,就像示例图中这样一个树状结构。

img

接下来介绍一下具体是如何实现的,无论是 SELECT、FROM 还是 WHERE,都会有自己所附带的一些成分。

  • select list 是一个表达式操作,即 c1+c2。再递归解析,它的根节点是 +,两个子节点分别是参与运算的两个常量 c1 和 c2。

  • from list 的参数其实是一个 relation,也就是一个表名,即 t1。

  • where 代表的是 condition 条件,这里的 condition 操作符是 exists,exists 后面是一个 sub query。这个 sub query 可以递归地向下去分解,它是由 union all 所连接起来的两个 sub query。同理这两个 sub query 也可以再递归地向下展开。

一条 SQL 语句,无论写得多么复杂,本质上就是一层一层嵌套的树状结构。Parser 模块这一个部分主要做的就是根据用户所写的语法规则正确的识别,并将一条 SQL 语句转化为一个语法树的结构。但一条符合语法树规则的 SQL 不一定是一条“合格”的 SQL,数据库中还存在着许多约束,一条 SQL 还必须满足语义的约束,许多语法的约束以及虚视图的展开都是在 Resolver 模块中完成的。

Resolver 模块

Resolver 模块主要作用是对 Parser 模块所生成的符合语法规则的树状结构进行进一步的约束检查,还可能会提取表达式的属性。为便于大家理解接下来介绍几个示例。

  • 关系或属性的检查

    关系或属性的检查主要是看表名、列名和别名是否有歧义、是否合法。比如当查询某张表中的一些列属性,FROM 子句出现的关系必须存在。也就是说当一张表都不存在,那查询肯定是没有意义的,或者当查询的属性没有出现在所查询的表中,当然也不满足数据库约束的要求。

  • 类型的检查

    • LIKE 操作符:要求匹配的属性必须是一个字符串,或可以转化成一个字符串结构。

    • PARTITION BY 操作符:该操作符后不能跟正则操作。当创建了一张表,PARTITION BY HASH 带的是一个 RLIKE 的正则操作符,这张表创建成功后查询时却报错了。

      img

      4016 是 OceanBase 中处理错误的一种表示。这张表本就不应该创建成功,虽然这个语法符合 Parser 的语法要求,但实际不符合数据库中的语义要求,也就是说 PARTITION BY HASH 后不应该带 RLIKE 的正则操作符。

  • 类型推演

    类型推演主要是提取表达式的属性用于后续分析,比如共享一些表达式,或者优化一些表达式计算之类的,对之后查询计划的优化有很大的作用。

  • 虚视图的展开

    在 OceanBase 和 MySQL 中都支持语法 SHOW FULL COLUMNS FROM t1(查看表的属性)。实际上在 OceanBase 中是转化成查询内部租户下的一张虚拟表。table_id 对应的是 t1,在 OceanBase 内部表名会被转换成一个唯一的 table_id,这些都是在 Resolver 模块完成的。

    img

除此之外,Resolver 模块虽然是将 Parser 模块的语法树结构进行一个检查转换,但在这一层会转化成一个自己的数据结构。不同的数据库可能有不同的实现,在 OceanBase 中用的是 STMT(Statement)。

如下图所示,这里将 SQL 语句 SELECT c1+c2 FROM t1 WHERE exists (select c1 from t1 union all select c1 from t2) 转换成了 Statement Tree,大家可以观察一下,在 OceanBase 中 Resolver 这层是怎么去表示 Statement 结构,这个结构是多个 OceanBase Statement 和表达式对象的集合,多个 Statement 对象在 OceanBase 中可以表达一些查询中的子查询。

img

理论上可以通过 Statement 结构去还原原始的 SQL,每个数据库都有不同的做法,它既不是一个关系运算符的表示,也不是一个树状结构,而是一个实际的工程实现,在逻辑上与树状结构相似,大家也可以继续把它当成一种树状的层次结构来理解。