调用 item->val_bool() 的返回值是 false,说明当前读取的记录不匹配该条件 。
ignore_unknown() 的返回值也是 false,表示包含 NULL 值的 where 条件的比较结果(UNKNOWN)不按 false 处理,而是要等到 while 循环结束之后,根据 null_value 属性的值(true 或 false)算总帐 。
这是由 Item_cond_and 对象控制的行为,而不是 and 连接的某个 where 条件控制的行为 。!(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value)) 表达式的值为 false,说明该条件包含 NULL 值,那么它就是 ignore_unknown() = false 时需要等到 while 循环结束之后,根据 null_value 属性的值算总帐的条件 。
该条件之后的其它 where 条件,不会导致 while 循环被提前中止(这样执行流程才能来到 return null_value ? 0 : 1) 。
此时,null_value 属性的值为 true,null_value ? 0 : 1 表达式的值为 0,说明当前读取的记录不匹配 and 连接的 N 个 where 条件 。
Item_func_eq::val_int()
// sql/item_cmpfunc.cclonglong Item_func_eq::val_int() {assert(fixed == 1);int value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/cmp.compare();return value == 0 ? 1 : 0;}
这里调用的 cmp.compare() 就是前面介绍的 Arg_comparator::compare() 方法 。对于示例 SQL 来说,Arg_comparator::compare() 调用的是 Arg_comparator::compare_int_signed() 方法,返回值只有 3 种:
- -1:表示 where 条件操作符左边的值小于右边的值 。
- 0:表示 where 条件操作符左边的值等于右边的值 。
- 1:表示 where 条件操作符左边的值大于右边的值 。
文章插图
i1 字段值为 50,对 where 条件 i1 = 50 调用 cmp.compare(),得到的返回值为 0(即 value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/0) 。
value =https://www.isolves.com/it/sjk/MYSQL/2023-05-26/= 0 ? 1 : 0 表达式的值为 1,这就是 Item_func_eq::val_int() 的返回值,表示 id = 5 的记录匹配 where 条件 i1 = 50 。
Item_cond_or::val_int()
// sql/item_cmpfunc.cclonglong Item_cond_or::val_int() {assert(fixed == 1);List_iterator_fast<Item> li(list);Item *item;null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/false;while ((item = li++)) {if (item->val_bool()) {null_value = false;return 1;}if (item->null_value) null_value = true;...}return 0;}
我们以 id = 8 的记录和示例 SQL 的 where 条件 i1 = 50 or i1 = 80 为例,介绍 Item_cond_or::val_int() 的逻辑:文章插图
Item_cond_or 对象的 list 属性包含 2 个条件:i1 = 50、i1 = 80,List_iterator_fastli(list) 根据 list 构造一个迭代器 。
对于 id = 8 的记录,i1 字段值为 80,while 循环每次迭代一个 where 条件:
第 1 次迭代,对 where 条件 i1 = 50 调用 item->val_bool(),返回值为 false,不进入 if (item->val_bool()) 分支 。
if (item->null_value) 条件不成立,不执行 null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/true 。
第 2 次迭代,对 where 条件 i1 = 80 调用 item->val_bool(),返回值为 true,进入 if (item->val_bool()) 分支 。
设置 Item_cond_or 对象的 null_value 属性值为 false,表示 Item_cond_or 所代表的 or 连接的 where 条件(i1 = 50、i1 = 80)都不包含 NULL 值 。
return 1,这就是 Item_cond_or::val_int() 的返回值,表示 id = 8 的记录匹配 where 条件 i1 = 50 or i1 = 80 。
总结本文介绍了 SQL 的 where 条件中包含 and、or 的实现逻辑:
从存储引擎读取一条记录之后,对 and 连接的 N 个 where 条件(N >= 2)调用 item->val_bool() 的返回值必须全部等于 true,记录才匹配 and 连接的 N 个 where 条件 。
Item_cond_and::val_int() 的代码不多,但是这个方法中调用了 ignore_known() 用于控制怎么处理 where 条件包含 NULL 值的场景,代码细节并不太好理解,所以花了比较长的篇幅介绍 Item_cond_and::val_int() 方法的逻辑,需要多花点时间去理解其中的逻辑 。
从存储引擎读取一条记录之后,对 or 连接的 N 个 where 条件(N >= 2)调用 item->val_bool(),只要其中一个返回值等于 true,记录就匹配 or 连接的 N 个 where 条件 。
本文转载自微信公众号「一树一溪」
推荐阅读
- 绿松石|读完这个就是翡翠专家了
- 李维嘉|李维嘉为什么消失了?带你揭秘事实的背后
- 有MySQL了,为什么还硬要搭个MongoDB集群?
- 贾玲|贾玲没参加华表奖,沈腾不读颁奖词,疑已经知道好友没获奖
- 求职|研究生白读了?985研究生求职被拒,HR直言:我们只看第一学历
- 大学|考不上高中,读职高很丢脸吗?为什么家长非要孩子去读私立高中
- MySQL Router高可用搭建,你学会了吗?
- 一文读懂低代码
- 在 Meta 构建和部署 MySQL Raft
- ChatGPT的打字回复效果,原理是什么?我带你们实现!