MySQL 源码|83 - SQL 语句的执行过程|V20240918

目录文档:MySQL 源码|源码剖析文档目录


SQL 语句执行过程

MySQL 中解析 SQL 语句,并构造抽象语法树的逻辑,主要在 parse_sql 函数中,主要执行过程如下:

  • dispatch_commandsql/sql_parse.cc):执行一个连接层级的命令。
    • dispatch_sql_commandsql/sql_parse.cc):从文本字符串中解析一个 SQL 命令,并将生成的抽象语法树(AST)传递给查询执行器。
      • parse_sqlsql/sql_parse.cc):使用提供的解析器状态和对象创建上下文,将一个 SQL 语句转换成一个准备解决的抽象语法树(AST)。

        • THD::sql_parsersql/sql_class.cc):首先调用解析器将语句转换为解析树;然后,进一步将解析树转换为抽象语法树(AST),以备解析(resolve)之用。
          • my_sql_parser_parse:Bison 解析器生成的语法解析入口函数
          • LEX::make_sql_cmdsql/sql_lex.cc):使用解析树(parse_tree)实例化一个 Sql_cmd 对象,并将其赋值给 Lex。
            • Parse_tree_root::make_cmdsql/parse_tree_nodes.h):各个语句根据自身抽象语法树(AST)构造 Sql_cmt 对象。
      • mysql_execute_commandsql/sql_parse.cc):执行保存在 thdlex->sql_command 中的命令。

        • Sql_cmd::commandsql/sql_cmd.h):执行 Sql_cmd 中的 SQL 语句。
dispatch_command 函数

执行一个连接层级的命令。

函数签名如下:

bool dispatch_command(THD *thd, const COM_DATA *com_data,
                      enum enum_server_command command)
  • thd:线程上下文(连接处理器)
  • command:命令类型
  • com_data:用于存储生成命令的联合体

其中调用了 dispatch_sql_command 函数:

dispatch_sql_command(thd, &parser_state);
dispatch_sql_command 函数

从文本字符串中解析一个 SQL 命令,并将生成的抽象语法树(AST)传递给查询执行器。

函数签名如下:

void dispatch_sql_command(THD *thd, Parser_state *parser_state)
  • thd:线程上下文(当前会话)
  • parser_state:解析器状态

其中调用了 parse_sql 函数:

err = parse_sql(thd, parser_state, nullptr);

也调用了 mysql_execute_command 函数:

error = mysql_execute_command(thd, true);
parse_sql 函数

使用提供的解析器状态和对象创建上下文,将一个 SQL 语句转换成一个准备解决的抽象语法树(AST)。

函数签名如下:

bool parse_sql(THD *thd, Parser_state *parser_state,
               Object_creation_ctx *creation_ctx)

参数含义如下:

  • thd:线程上下文
  • parser_state:解析器状态
  • creation_ctx:构造对象的上下文

其中调用了 THD::sql_parser() 函数:

const bool mysql_parse_status = thd->sql_parser();
THD::sql_parser() 函数

首先调用解析器将语句转换为解析树;然后,进一步将解析树转换为抽象语法树(AST),以备解析(resolve)之用。

函数逻辑如下,其中调用了 my_sql_parser_parse 函数和 LEX::make_sql_cmd 函数:

bool THD::sql_parser() {
  extern int my_sql_parser_parse(class THD * thd,
                                 class Parse_tree_root * *root);

  Parse_tree_root *root = nullptr;
  if (my_sql_parser_parse(this, &root) || is_error()) {
    cleanup_after_parse_error();
    return true;
  }
  if (root != nullptr && lex->make_sql_cmd(root)) {
    return true;
  }
  return false;
}

THD::sql_parser 函数在其他调用位置如下:

  • parsesql/item_strfunc.cc):解析一个字符串并填充 Token 缓冲区。
  • reparse_common_table_exprsql/sql_parse.cc):从子查询的文本中生成一个 PT_subquery 对象
my_sql_parser_parse 函数

Bison 解析器生成的语法解析入口函数,详见 MySQL 源码|82 - 词法解析和语法解析的入口逻辑

LEX::make_sql_cmd 函数

使用解析树(parse_tree)实例化一个 Sql_cmd 对象,并将其赋值给 Lex。

函数逻辑如下,其中调用了 Parse_tree_root::make_cmd 函数:

bool LEX::make_sql_cmd(Parse_tree_root *parse_tree) {
  if (!will_contextualize) return false;

  m_sql_cmd = parse_tree->make_cmd(thd);
  if (m_sql_cmd == nullptr) return true;

  assert(m_sql_cmd->sql_command_code() == sql_command);

  return false;
}
Parse_tree_root::make_cmd 函数

Parse_tree_root 是语法解析中各类语句的根节点的基类,其中定义了 make_cmd 函数,并由各个语句子类去实现。因此,Parse_tree_root::make_cmd 函数实际上就是各个语句根据自身抽象语法树(AST)构造 Sql_cmt 对象的过程。

mysql_execute_command 函数

执行保存在 thdlex->sql_command 中的命令。

函数签名如下:

int mysql_execute_command(THD *thd, bool first_level)
  • thd:线程上下文
  • first_level:调用 mysql_execute_command() 的是一个顶级查询还是子查询。在顶级查询时,first_level 的值为 true;在子查询时,first_level(递归调用 mysql_execute_command())将为 false

mysql_execute_command 函数中,不同类型的 SQL 语句有不同的处理方法,但 DQL、DML 等语法均调用了 Sql_cmd 的子类的 execute 成员函数:

lex->m_sql_cmd->execute(thd);
Sql_cmd::command 函数

执行 Sql_cmd 中的 SQL 语句。

函数签名如下:

virtual bool execute(THD *thd) = 0;
  • thd:线程上下文
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值