带你读 MySQL 源码:Where 条件怎么过滤记录?( 四 )


首先,我们来看一下 null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/false:
null_value 的初始值被设置为 false,表示 and 连接的 N 个 where 条件中,还没出现哪个 where 条件包含 NULL 值的情况(毕竟还啥都没干) 。
null_value 比较重要,它有可能最终决定 Item_cond_and::val_int() 的返回值(后面会介绍) 。
然后,再来看看 while 循环的逻辑,这块内容会有一点点多:
while 循环迭代 and 连接的 N 个 where 条件 。
每迭代一个 where 条件,都调用 item->val_bool() 方法,判断当前读取的记录是否匹配该条件 。
如果 val_bool() 的返回值是 true,说明记录匹配该条件,进入下一轮循环,迭代下一个 where 条件(如果有的话) 。

if (current_thd->is_error()),这行代码表示执行过程中出现了错误,我们先忽略它 。
如果 val_bool() 的返回值是 false,说明记录不匹配该条件 。
接下来是进入下一轮循环,还是执行 return 0 结束 Item_cond_and::val_int() 方法,就要由 if (ignore_unknown() || !(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value)) 决定了 。
展开介绍 if (ignore_unknown() || ...) 之前,先来看看 ignore_unknown() 的定义:
class Item_cond : public Item_bool_func {.../// Treat UNKNOWN result like FALSE/// because callers see no differencebool ignore_unknown() const { return abort_on_null; }...}从代码注释可以看到,ignore_unknown() 用于决定是否把 UNKNOWN 当作 FALSE 处理 。
那么,什么是 UNKNOWN?
在 MySQL 中,NULL 会被特殊对待 。NULL 和任何值(包含 NULL 本身)通过关系操作符(=、>、<、...)比较,得到的结果都是 NULL,这个结果就被认为是 UNKNOWN 。
如果想知道某个值是否为 NULL,只能使用 IS NULL、IS NOT NULL 进行判断 。
说完了 ignore_unknown(),我们回到 if (ignore_unknown() || !(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value)),它包含两个表达式:
  • ignore_unknown()
  • !(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value))
如果 ignore_unknown() 的返回值为 true,if 条件成立,执行流程就会进入 if 分支,执行 return 0,Item_cond_and::val_int() 方法的执行流程就此结束,表示当前读取的记录不匹配 and 连接的 N 个 where 条件 。
如果 ignore_unknown() 的返回值为 false,那么还需要再判断 !(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value)) 的值是 true 还是 false 。
我们先分解一下 !(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value)),其中包含 2 个步骤:
  • null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value
  • !null_value
如果 item->null_value 的值为 false,赋值给 null_value 之后,!null_value 的值为 true,if 条件成立,执行流程就会进入 if (ignore_unknown() || ...) 分支,执行 return 0,Item_cond_and::val_int() 方法的执行流程就此结束,表示当前读取的记录不匹配 and 连接的 N 个 where 条件 。
item->null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/false,表示对于当前读取的记录,where 条件不包含 NULL 值 。
如果 item->null_value 的值为 true,赋值给 null_value 之后,!null_value 的值为 false,即 !(null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/item->null_value)) 的值为 false,if 条件不成立,执行流程不会进入 if (ignore_unknown() || ...) 分支,也就不会执行 return 0 了,接下来就会进入下一轮循环,迭代下一个 where 条件(如果有的话) 。
item->null_value = https://www.isolves.com/it/sjk/MYSQL/2023-05-26/true,表示对于当前读取的记录,where 条件包含 NULL 值 。
最后,再来看看 return null_value ? 0 : 1:
while 循环迭代完 and 连接的 N 个 where 条件之前,如果 Item_cond_and::val_int() 方法的执行流程都没有被 while 代码块中包含的 return 0 提前结束,执行流程就会来到 return null_value ? 0 : 1 。
有两种场景会导致这种情况的出现:
场景 1:while 循环迭代 and 连接的 N 个 where 条件的过程中,对每个条件调用 item->val_bool() 的返回值都是 true 。
此时,null_value 属性的值为 false,null_value ? 0 : 1 表达式的值为 1,说明当前读取的记录匹配 and 连接的 N 个 where 条件 。
场景 2:while 循环迭代 and 连接的 N 个 where 条件的过程中,某个条件同时满足以下 4 个要求:


推荐阅读