背景

一个最简单的select语句包含select子句、from子句、where子句等,这些子句都不包含子查询(subselect),也没有union操作。而复杂的select语句包含select子句、from子句、where子句(这些子查询可以y是最简单的select语句也可以y是复杂的select语句),同时select语句中可能包含union,即将数个select子句联合在一起
MySQL解析器(lex+yacc)是如何解析上述复杂的SQL的呢?又是使用什么样的数据结构来完整的维护一个大的select中包含的subselect、union的d关系呢?本文希望通过介绍MySQL解析器中相关的数据结构及处理过程,解答上述两个问题。

  


主要数据结构及其之间关系

MySQL解析器中负责分析和存储一个select语句信息的数据结构是st_select_lex类(MySQL中同时将该类宏定义为SELECT_LEX),同时负责分析和存储union关系的数据结构是st_select_lex_unit(MySQL中同时将该类宏定义为SELECT_LEX_UNIT),而这两个类都继承于st_select_lex_node类。

对于SELECT_LEX类,它主要是存储一个select语句中select子句的返回列信息,from子句中的表信息,order by,group by子句的列信息等。对于本文所关心的问题,SELECT_LEX类使用继承于st_select_lex_node类的next指针存储和该select语句进行union操作的其他select语句对应的SELECT_LEX的地址,通过这个指针串成union链表。

 

例如:SQL1:select * from test1 where id=5 union select * from test1 where id=6;

 

MySQL解析器源码分析--对select语句中子查询处理逻辑的分析(一)_第1张图片


对于SELECT_LEX_UNIT负责管理处于同一级的进行union操作的数个select子句对应的SELECT_LEX。SELECT_LEX_UNIT通过继承于st_select_lex_node类的slave指针存储属于这一级的进行union操作的第一个SELECT_LEX,而这一级别其他参与union操作的SELECT_LEX,可以通过next指针串成的链表依次找到。同时SELECT_LEX_UNIT类中还有一个成员变量fake_select_lex,它来保存整个union操作的order by,limit条件。

例如:

 

MySQL解析器源码分析--对select语句中子查询处理逻辑的分析(一)_第2张图片


对于select子句,from子句,where子句中出现子查询(subselect)的情况,MySQL解析器会先建一个SELECT_LEX_UNIT,将此SELECT_LEX_UNIT挂在该子查询上一级select对应的SELECT_LEX下(即该SELECT_LEX的slave指针赋值为此SELECT_LEX_UNIT对应的地址),同时新建一个SELECT_LEX和这个子查询对应,将这个新建的SELECT_LEX挂在刚建的SELECT_LEX_UNIT下。


(未完待续)

 

【本文首发于: 百度运维空间http://hi.baidu.com/ops_bd/blog/item/28f61b1c82902fceac6e750b.html
关注百度技术沙龙