【MySQL·8.0·源码】MySQL 语法树结构

发布时间:2023年12月18日

引文

  • Query_block(查询块)
    查询块也称为查询范式
    即一个由 SELECT 关键词开头,紧跟表列表,可选由 WHERE 子句、GROUP BY 子句等组成的一个基本查询块
  • Query_expression(查询表达式)
    一个查询表达式可能由一个或者多个查询块组成
    多于一个查询块表示查询表达式中包含一个或者多个 UNION、INTERSET 或者 EXCEPT 操作
    如果有子查询,那么也可能含有多个查询块
  • LEX
    LEX 是一条 SQL 语句相关的解析语法树结构对象
    即 MySQL 使用 LEX 对象来保存解析语法树

Query_block(查询块)

一个查询块对应着一条基本的 SELECT 语句的语法结构

  • master
    指向查询块的上层表达式(外部查询表达式)
  • slave
    执行属于该查询块的第一个查询表达式(子查询)
  • neighbors
    link_next、link_prev 分别指向同层同级别的邻居查询块,查询块列表
class Query_block : public Query_term {
  /**
    Intrusive linked list of all query blocks within the same
    query expression.
  */
  Query_block *next{nullptr};

  /// The query expression containing this query block.
  Query_expression *master{nullptr};
  /// The first query expression contained within this query block.
  Query_expression *slave{nullptr};

  /// Intrusive double-linked global list of query blocks.
  Query_block *link_next{nullptr};
  Query_block **link_prev{nullptr};
  
  Query_expression *master_query_expression() const { return master; }
  Query_expression *first_inner_query_expression() const { return slave; }
  Query_block *outer_query_block() const { return master->outer_query_block(); }
  Query_block *next_query_block() const { return next; }
  Query_block *next_select_in_list() const { return link_next; }
}

Query_expression(查询表达式)

查询表达式中的查询块形成一个树形结构,表达了嵌套形式的查询操作
查询表达式由一个或多个查询块组成,多个查询块表示查询表达式有 UNION、INTERSECT、EXCEPT操作,或者利用查询块来描述子查询结构

  • master
    指向查询表达式的上层查询块(外部查询块)
  • slave
    执行属于该查询表达式的第一个查询块
  • neighbors
    next、prev 分别指向同层同级别的邻居查询表达式,查询表达式列表
class Query_expression { 
  /**
    Intrusive double-linked list of all query expressions
    immediately contained within the same query block.
  */
  Query_expression *next;
  Query_expression **prev;
  /**
    The query block wherein this query expression is contained,
    NULL if the query block is the outer-most one.
  */
  Query_block *master;
  /// The first query block in this query expression.
  Query_block *slave;

  /// @return the query block this query expression belongs to as subquery
  Query_block *outer_query_block() const { return master; }
  /// @return the first query block inside this query expression
  Query_block *first_query_block() const { return slave; }
  /// @return the next query expression within same query block (next subquery)
  Query_expression *next_query_expression() const { return next; }
}

LEX

从 LEX 可以定位到语法树中最外层的查询表达式和第一个查询块,也可以直接遍历所有的查询块
然后根据以上查询块和查询表达式的关系,从最外层的查询表达式的第一个查询块进行查询处理

struct LEX : public Query_tables_list {
  Query_expression *unit;  ///< Outer-most query expression
  /// @todo: query_block can be replaced with unit->first-select()
  Query_block *query_block;            ///< First query block
  Query_block *all_query_blocks_list;  ///< List of all query blocks
 private:
  /* current Query_block in parsing */
  Query_block *m_current_query_block;
}

示例

Q1: union + order by查询

select * from t1 union select * from t2 union select * from t3 order by 1;

在这里插入图片描述

Q2: union + intersect + except + order by + limit查询

((
    SELECT * FROM t1
    UNION SELECT * FROM t2
    UNION SELECT * FROM t3
    ORDER BY c1 LIMIT 5
  )
  INTERSECT 
  (((
      SELECT  *
      FROM t3
      ORDER BY c1
      LIMIT 1
    )
   )
   EXCEPT
      SELECT * FROM t4 
  )
  ORDER BY c1
  LIMIT 4
)
ORDER BY c1
LIMIT 3;

在这里插入图片描述

Q3: 带 viewfrom子句子查询的查询

(select * from t1) union (select tmp1.* from (select * from t2) as tmp1, (select * from t3 union select * from v1) as tmp2);

在这里插入图片描述
Q4:where子句带子查询的查询

select * from t1 where c1 in (select c2 from t2 where t2.c1 < 20);

在这里插入图片描述

Query_block 其他重要成员

class Query_block {
  SQL_I_List<Table_ref> m_table_list // FROM 字句中的所有表列表,使用 Table_ref::next_local 进行遍历
  SQL_I_List<ORDER> order_list //ORDER BY 子句字段列表
  QL_I_List<ORDER> group_list //GROUP BY 子句字段列表
  table_map outer_join //outer join 查询中所有 inner tables 的 bitmap
  mem_root_deque<Table_ref *> sj_nests // semi-join 的表 nests 列表
  
  mem_root_deque<Item *> fields // join 和 filtering 之后所需的 fields,包括 select list(project所需字段)、group by list(分组所需字段)、having clause(having字句字段)、window clause(窗口函数字段)、order by clause(order by字段)
  Item *select_limit // LIMIT 子句
  Item *offset_limit // LIMIT .. OFFSET 子句
  Item *m_where_cond // WHERE 子句
  Item *m_having_cond // HAVING 子句
}

Table_ref 重要成员

class Table_ref {
  Table_ref *next_local //某一层 SELECT 的 FROM 中表的链表指针
  const char *db
  const char *table_name

  Item *m_join_cond // JOIN 条件
  List<String> *join_using_fields //JOIN ...USING 对应 USING 子句宏的 field 名称列表
  /*嵌套连接
    1.代表外连接中的内部表(inner tables); 
    2.代表内连接中括号内的表(resolve时被消除); 
    3.代表派生表或视图中引用的表; 
    4.代表semi-join嵌套中的表; 
    5.代表子查询中的表;
  */
  NESTED_JOIN *nested_join 
  Table_ref *embedding //
  mem_root_deque<Table_ref *> *join_list //
}

示例

Q5: 普通JOIN查询

select * from t3, (t1, t2) where t1.c1 = t2.c2;

在这里插入图片描述

Q6:

select * from t1 left outer join(t2, t3) on t1.c1 = t2.c1 and t1.c2 = t3.c2 where t1.c1 = t2.c2;

在这里插入图片描述

本文代码版本为:MySQL 8.1.0
示例中表和视图结构

    create table t1(c1 int, c2 int, c3 int);
    create table t2(c1 int, c2 int, c3 int);
    create table t3(c1 int, c2 int, c3 int);
    create table t4(c1 int, c2 int, c3 int);
    create table t5(c1 int, c2 int, c3 int);
    create view v1 as select * from t5;
文章来源:https://blog.csdn.net/u010502974/article/details/134996395
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。