深入理解 MySQL 8 C++ 源码:SELECT MOD(MONTH(NOW()), 2) 的函数执行过程
MySQL 作为最流行的关系型数据库之一,其内部实现机制一直是开发者探索的热点。本文将以一条简单的 SQL 查询 SELECT MOD(MONTH(NOW()), 2) 为例,深入分析 MySQL 8 源码中内置函数 MOD、MONTH 和 NOW 的执行过程,揭示其底层实现逻辑。
一、SQL 语句的解析与表达式树构建
当 MySQL 接收到 SQL 查询时,首先会通过 解析器 将文本转化为内部的表达式树结构。对于 MOD(MONTH(NOW()), 2),解析过程如下:
-
NOW():
被解析为Item_func_now类的实例,负责返回当前时间(datetime类型)。 -
MONTH(NOW()):
被解析为Item_func_month类的实例,接受NOW()的结果作为输入,提取月份值(整数类型)。 -
MOD(month_value, 2):
被解析为Item_func_mod类的实例,对MONTH()的结果和常量2进行取模运算。
最终,这三个函数会形成一个嵌套的表达式树:
Item_func_mod(Item_func_month(Item_func_now()), 2)。
二、关键源码文件与类定义
1. NOW() 函数的实现
- 声明文件:
sql/item_timefunc.h
类名:Item_func_now(或其派生类Item_func_now_local/Item_func_now_utc)。 - 实现文件:
sql/item_timefunc.cc
核心方法Item_func_now::val_datetime()负责获取当前时间。
2. MONTH() 函数的实现
- 声明文件:
sql/item_timefunc.h
类名:Item_func_month。 - 实现文件:
sql/item_timefunc.cc
核心方法Item_func_month::val_int()从日期中提取月份:longlong Item_func_month::val_int() {MYSQL_TIME ltime;if (get_arg0_date(<ime, TIME_FUZZY_DATE)) return 0;return ltime.month; // 返回月份(1-12) }
3. MOD() 函数的实现
- 声明文件:
sql/item_func.h
类名:Item_func_mod。 - 实现文件:
sql/item_func.cc
核心方法Item_func_mod::int_op()处理整数取模运算:longlong Item_func_mod::int_op() {longlong val1 = args[0]->val_int(); // 计算 MONTH(NOW())longlong val2 = args[1]->val_int(); // 常量 2if (val2 == 0) return 0; // 避免除零错误return val1 % val2; }
三、执行流程详解
1. 解析阶段
- 语法解析器(
sql/sql_yacc.yy)将 SQL 字符串转换为表达式树。 - 优化器确定表达式类型(例如
Item::INT_RESULT)。
2. 执行阶段
-
调用
NOW():
Item_func_now::val_datetime()获取当前时间(例如2023-10-05 12:34:56)。 -
调用
MONTH():
Item_func_month::val_int()从NOW()的结果中提取月份值(例如10)。 -
调用
MOD():
Item_func_mod::int_op()对月份值10和2取模,最终结果为0。
四、源码定位技巧
由于代码行号可能随版本变化,建议通过以下方式快速定位关键代码:
-
GitHub 搜索:
访问 MySQL 8.0 源码仓库,搜索Item_func_mod或Item_func_month。 -
本地代码搜索:
# 在 MySQL 源码根目录执行: grep -rn 'Item_func_mod' sql/ grep -rn 'Item_func_month' sql/
五、关键设计思想
-
表达式树模型:
MySQL 通过嵌套的Item类对象(如Item_func_mod)表示复杂表达式,支持递归求值。 -
类型推导与优化:
优化器在预处理阶段确定表达式的结果类型(如整数、浮点数),避免运行时类型转换开销。 -
错误处理:
内置函数需处理边界条件(如MOD的除零错误),返回合理默认值而非抛出异常,确保查询稳定性。
六、总结
通过分析 SELECT MOD(MONTH(NOW()), 2) 的执行过程,我们可以深入理解 MySQL 的以下机制:
- 内置函数的实现:通过
Item_func_*类封装逻辑。 - 表达式求值:递归调用
val_int()或val_datetime()方法。 - 源码结构:时间函数在
item_timefunc.*,数学函数在item_func.*。
掌握这些底层细节,不仅能帮助开发者调试复杂 SQL,还能为贡献 MySQL 源码或定制内置函数奠定基础。
##MOD函数 gdb调试堆栈
#0 Item_func_mod::int_op (this=0x746cd800e280) at /home/yym/mysql8/mysql-8.1.0/sql/item_func.cc:2616
#1 0x00005591538eda46 in Item_func_numhybrid::val_int (this=0x746cd800e280) at /home/yym/mysql8/mysql-8.1.0/sql/item_func.cc:1740
#2 0x00005591538600cb in Item::send (this=0x746cd800e280, protocol=0x746cd80052c0, buffer=0x746de10f5e20) at /home/yym/mysql8/mysql-8.1.0/sql/item.cc:7483
#3 0x00005591532bf8a0 in THD::send_result_set_row (this=0x746cd8001050, row_items=...) at /home/yym/mysql8/mysql-8.1.0/sql/sql_class.cc:2881
#4 0x0000559153b1ce85 in Query_result_send::send_data (this=0x746cd8010498, thd=0x746cd8001050, items=...) at /home/yym/mysql8/mysql-8.1.0/sql/query_result.cc:102
#5 0x0000559153513ef0 in Query_expression::ExecuteIteratorQuery (this=0x746cd800db40, thd=0x746cd8001050) at /home/yym/mysql8/mysql-8.1.0/sql/sql_union.cc:1785
#6 0x0000559153514181 in Query_expression::execute (this=0x746cd800db40, thd=0x746cd8001050) at /home/yym/mysql8/mysql-8.1.0/sql/sql_union.cc:1823
#7 0x0000559153454cf6 in Sql_cmd_dml::execute_inner (this=0x746cd8010460, thd=0x746cd8001050) at /home/yym/mysql8/mysql-8.1.0/sql/sql_select.cc:1022
#8 0x0000559153454067 in Sql_cmd_dml::execute (this=0x746cd8010460, thd=0x746cd8001050) at /home/yym/mysql8/mysql-8.1.0/sql/sql_select.cc:793
#9 0x00005591533c6841 in mysql_execute_command (thd=0x746cd8001050, first_level=true) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:4797
#10 0x00005591533c8cb3 in dispatch_sql_command (thd=0x746cd8001050, parser_state=0x746de10f79f0) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:5447
#11 0x00005591533be0d7 in dispatch_command (thd=0x746cd8001050, com_data=0x746de10f8340, command=COM_QUERY) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:2112
#12 0x00005591533bbf77 in do_command (thd=0x746cd8001050) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:1459
#13 0x0000559153613835 in handle_connection (arg=0x559198b65f80) at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_handler_per_thread.cc:303
#14 0x0000559155552bdc in pfs_spawn_thread (arg=0x559198b3ec30) at /home/yym/mysql8/mysql-8.1.0/storage/perfschema/pfs.cc:3043
#15 0x0000746df0e94ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#16 0x0000746df0f26850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
##MONTH函数 gdb调试堆栈
#0 Item_func_now::get_date (this=0x746cec01b6d0, res=0x746de13fbbd0) at /home/yym/mysql8/mysql-8.1.0/sql/item_timefunc.cc:2108
#1 0x00005591539bcb6d in Item_func::get_arg0_date (this=0x746cec01b7c8, ltime=0x746de13fbbd0, fuzzy_date=1) at /home/yym/mysql8/mysql-8.1.0/sql/item_func.h:510
#2 0x00005591539b1ea2 in Item_func_month::val_int (this=0x746cec01b7c8) at /home/yym/mysql8/mysql-8.1.0/sql/item_timefunc.cc:1268
#3 0x00005591538f1fe0 in Item_func_mod::int_op (this=0x746cec01b990) at /home/yym/mysql8/mysql-8.1.0/sql/item_func.cc:2585
#4 0x00005591538eda46 in Item_func_numhybrid::val_int (this=0x746cec01b990) at /home/yym/mysql8/mysql-8.1.0/sql/item_func.cc:1740
#5 0x00005591538600cb in Item::send (this=0x746cec01b990, protocol=0x746cec012d80, buffer=0x746de13fbe20) at /home/yym/mysql8/mysql-8.1.0/sql/item.cc:7483
#6 0x00005591532bf8a0 in THD::send_result_set_row (this=0x746cec000b90, row_items=...) at /home/yym/mysql8/mysql-8.1.0/sql/sql_class.cc:2881
#7 0x0000559153b1ce85 in Query_result_send::send_data (this=0x746cec01dba8, thd=0x746cec000b90, items=...) at /home/yym/mysql8/mysql-8.1.0/sql/query_result.cc:102
#8 0x0000559153513ef0 in Query_expression::ExecuteIteratorQuery (this=0x746cec01b250, thd=0x746cec000b90) at /home/yym/mysql8/mysql-8.1.0/sql/sql_union.cc:1785
#9 0x0000559153514181 in Query_expression::execute (this=0x746cec01b250, thd=0x746cec000b90) at /home/yym/mysql8/mysql-8.1.0/sql/sql_union.cc:1823
#10 0x0000559153454cf6 in Sql_cmd_dml::execute_inner (this=0x746cec01db70, thd=0x746cec000b90) at /home/yym/mysql8/mysql-8.1.0/sql/sql_select.cc:1022
#11 0x0000559153454067 in Sql_cmd_dml::execute (this=0x746cec01db70, thd=0x746cec000b90) at /home/yym/mysql8/mysql-8.1.0/sql/sql_select.cc:793
#12 0x00005591533c6841 in mysql_execute_command (thd=0x746cec000b90, first_level=true) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:4797
#13 0x00005591533c8cb3 in dispatch_sql_command (thd=0x746cec000b90, parser_state=0x746de13fd9f0) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:5447
#14 0x00005591533be0d7 in dispatch_command (thd=0x746cec000b90, com_data=0x746de13fe340, command=COM_QUERY) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:2112
#15 0x00005591533bbf77 in do_command (thd=0x746cec000b90) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:1459
#16 0x0000559153613835 in handle_connection (arg=0x559198b68010) at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_handler_per_thread.cc:303
#17 0x0000559155552bdc in pfs_spawn_thread (arg=0x559198b689e0) at /home/yym/mysql8/mysql-8.1.0/storage/perfschema/pfs.cc:3043
#18 0x0000746df0e94ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#19 0x0000746df0f26850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
相关文章:
深入理解 MySQL 8 C++ 源码:SELECT MOD(MONTH(NOW()), 2) 的函数执行过程
MySQL 作为最流行的关系型数据库之一,其内部实现机制一直是开发者探索的热点。本文将以一条简单的 SQL 查询 SELECT MOD(MONTH(NOW()), 2) 为例,深入分析 MySQL 8 源码中内置函数 MOD、MONTH 和 NOW 的执行过程,揭示其底层实现逻辑。 一、SQL…...
【算法系列】leetcode1419 数青蛙 --模拟
一、题目 二、思路 模拟⻘蛙的叫声。 当遇到 r o a k 这四个字符的时候,我们要去看看每⼀个字符对应的前驱字符,有没有⻘蛙叫出来。如果有⻘蛙叫出来,那就让这个⻘蛙接下来喊出来这个字符;如果没有则为异常字符串,直接…...
蓝桥杯 Java B 组之背包问题、最长递增子序列(LIS)
Day 4:背包问题、最长递增子序列(LIS) 📖 一、动态规划(Dynamic Programming)简介 动态规划是一种通过将复杂问题分解成更小的子问题来解决问题的算法设计思想。它主要用于解决具有最优子结构和重叠子问题…...
Git如何将一个分支的内容同步到另一个分支
在 Git 中,可以通过多种方法将一个分支的内容同步到另一个分支。以下是几种常用的方法: 1. 使用 merge 命令 这是最常见的方法,将一个分支的更改合并到另一个分支。 # 切换到目标分支 git checkout target-branch# 合并源分支的内容 git m…...
[C#]C# winform部署yolov12目标检测的onnx模型
yolov12官方框架:github.com/sunsmarterjie/yolov12 【测试环境】 vs2019 netframework4.7.2 opencvsharp4.8.0 onnxruntime1.16.3 【效果展示】 【调用代码】 using System; using System.Collections.Generic; using System.ComponentModel; using System.…...
51c大模型~合集69
我自己的原文哦~ https://blog.51cto.com/whaosoft/12221979 #7项基于SAM万物分割模型研究工作 1、CC-SAM: SAM with Cross-feature Attention and Context for Ultrasound Image Segmentation #ECCV2024 #SAM #图像分割 #医学图像 Segment Anything Model (SAM) 在自…...
2025寒假周报4
2025寒假天梯训练7-CSDN博客 眨眼间寒假训练就告一段落了,准备回校继续战斗了。这周练了3场OI赛制的篮球杯,感觉非常糟糕,不像天梯赛,天梯赛打起来非常舒适顺畅,一直都不喜欢OI赛制,打着非常不稳定..还需要…...
自学Java-AI结合GUI开发一个石头迷阵的游戏
自学Java-AI结合GUI开发一个石头迷阵的游戏 准备环节1、创建石头迷阵的界面2、打乱顺序3、控制上下左右移动4、判断是否通关5、统计移动步骤,重启游戏6、拓展问题 准备环节 技术: 1、GUI界面编程 2、二维数组 3、程序流程控制 4、面向对象编程 ∙ \bulle…...
buuctf-[极客大挑战 2019]Knife题解
一个很简单的web题,进入界面 网页名还加白给的shell,并且给的提示也很明显,给了一个一句话木马再加上菜刀,很怀疑是一个webshell题,那么直接打开蚁剑测试连接拿shell 用提示的一句话木马的密码,测试链接发现…...
Spring MVC 对象转换器:初级开发者入门指南
Spring MVC 对象转换器:初级开发者入门指南 为什么需要对象转换器? 在 Web 应用中,我们经常需要处理不同类型的对象。例如:前端数据到后端对象 :用户通过表单提交的数据通常是HttpServletRequest 对象,我们…...
语音直播交友app出海:语音直播交友系统软件源码搭建国际化发展技术层面分析
随着移动互联网的普及和全球社交需求的增长以及国内如火如荼的Ai大模型引起的全球发展热潮,语音直播软件出海成为了具有巨大发展潜力的业务领域。以下是一些关键的技术方向,将为语音直播软件在国际市场的成功推广及搭建合作奠定基础。 通信技术 实时语音…...
Web Scraper,强大的浏览器爬虫插件!
Web Scraper是一款功能丰富的浏览器扩展爬虫工具,有着直观的图形界面,无需编写代码即可自定义数据抓取规则,高效地从网页中提取结构化数据,而且它支持灵活的数据导出选项,广泛应用于电商监控、内容聚合、市场调研等多元…...
EasyRTC:基于WebRTC与P2P技术,开启智能硬件音视频交互的全新时代
在数字化浪潮的席卷下,智能硬件已成为我们日常生活的重要组成部分,从智能家居到智能穿戴,从工业物联网到远程协作,设备间的互联互通已成为不可或缺的趋势。然而,高效、低延迟且稳定的音视频交互一直是智能硬件领域亟待…...
go 定时任务 gocron timer
选型推荐(DeepSeek) 简单任务调度: 推荐使用 cron 或 gocron,它们轻量且易用。 复杂任务调度: 推荐使用 go-quartz,支持任务依赖和持久化。 分布式任务调度: 推荐使用 asynq,基于 Redis 实现,适合分布式…...
uniapp引入uview组件库(可以引用多个组件)
第一步安装 npm install uview-ui2.0.31 第二步更新uview npm update uview-ui 第三步在main.js中引入uview组件库 第四步在uni.scss中引入import "uview-ui/theme.scss"样式 第五步在文件中使用组件...
MySQL主从架构
MySQL主从架构 MySQL REPLICATION 在实际生产环境中,如果对数据库的读和写都在一个数据库服务器中操作。无论是在安全性、高可用性,还是高并发等各个方面都是完全不能满足实际需求的,因此,一般来说都是通过主从复制(…...
科普mfc100.dll丢失怎么办?有没有简单的方法修复mfc100.dll文件
当电脑频繁弹窗提示“mfc100.dll丢失”或应用程序突然闪退时,这个看似普通的系统文件已成为影响用户体验的核心痛点。作为微软基础类库(MFC)的核心组件,mfc100.dll直接关联着Visual Studio 2010开发的大量软件运行命脉。从工业设计…...
论文笔记:How Much Can Time-related Features Enhance Time Series Forecasting?
202412arxiv 许多时间序列预测方法靠变量建模,却忽略了时间戳相关特征(如季节、月份、星期几、小时、分钟等) ——>论文尝试仅基于时间戳进行预测(这个仅我觉得其实不是很严谨,还是用了时间序列变量的数据【不可能…...
Qt学习(六) 软件启动界面 ,注册表使用 ,QT绘图, 视图和窗口绘图,Graphics View绘图框架:简易CAD
一 软件启动界面 注册表使用 知识点1:这样创建的界面是不可以拖动的,需要手动创建函数来进行拖动,以下的3个函数是从父类继承过来的函数 virtual void mousePressEvent(QMouseEvent *event);virtual void mouseReleaseEvent(QMouseEvent *eve…...
JavaScript系列(80)--WebAssembly 基础入门
WebAssembly 基础入门 🚀 WebAssembly(简称Wasm)是一种低级的类汇编语言,它具有紧凑的二进制格式,能够以接近原生的性能在现代Web浏览器中运行。让我们深入了解这项革命性的技术。 WebAssembly 概述 🌟 &…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
