前言

问题来自于 chinaunix, mysql select 子句的小白问题 

mysql 的一些基础的 算术运算符 的计算的实现

这里 整理如下 case, 执行之前 设置如下变量

set @a = 2;
set @b = 3;

select @a + @b;
select 'a' + 'b';
select 1 + 3;
select '1' + '3';
select 'a + b';
select a + b;

 

 

select @a + @b;

解析 sql 的时候, 会将 表达式 解析为一个 Item_func_plus, 左右操作数为 Item_func_get_user_var 变量名分别为 a, b

42 mysql “+“ 操作符的实现_variables

 

查询的时候 选择列即为 上面解析表达式的时候 resolve 的 Item_func_plus

然后由 Item_func_plus 来计算结果, 以及响应数据 

42 mysql “+“ 操作符的实现_variables_02

 

取变量的方式为, 从 user_var_entry 中获取存储的数据值, 这个值是上面 “set @a = 2;” 设置进去的 

42 mysql “+“ 操作符的实现_plus_03

 

具体的 计算业务是由这里的 val0 + val1, 以及 之后的符号相关处理 来完成的

得到结果 2 + 3 = 5

42 mysql “+“ 操作符的实现_mysql_04

 

 

select 'a' + 'b';

解析表达式的的时候, 合成一个 Item_func_plus, 左右操作数为 字面量 ”a”, ”b”

42 mysql “+“ 操作符的实现_variables_05

 

计算的时候, 尝试将 “a” 转换为 int 的时候 “a” 不符合 数字的相关规范, my_strntod 计算为 0

42 mysql “+“ 操作符的实现_字面量_06

 

因此 计算结果为 0 + 0 = 0

42 mysql “+“ 操作符的实现_plus_07

 

 

select 1 + 3; 

解析表达式的的时候, 合成一个 Item_func_plus, 左右操作数为 数字 1, 3

42 mysql “+“ 操作符的实现_字面量_08

 

计算的时候, 获取数字 1 的值, 为 1

42 mysql “+“ 操作符的实现_variables_09

 

计算结果为 1 + 3 = 4

42 mysql “+“ 操作符的实现_字面量_10

 

 

select '1' + '3';

解析表达式的的时候, 合成一个 Item_func_plus, 左右操作数为 字面量 ”1”, ”3”  

42 mysql “+“ 操作符的实现_variables_11

 

将字面量转换为数字的时候, “1” 转换为 1, “3” 转换为 3

42 mysql “+“ 操作符的实现_concat_12

 

计算结果为 1 + 3 = 4

42 mysql “+“ 操作符的实现_mysql_13

 

 

select 'a + b';

解析表达式的时候, 解析为一个 常量字面量 “a + b”

42 mysql “+“ 操作符的实现_plus_14

 

然后 响应的时候, 直接 响应给定的字面量的字符串

42 mysql “+“ 操作符的实现_plus_15

 

 

select a + b;

解析表达式的的时候, 合成一个 Item_func_plus, 左右操作数为 Identifier 标记分别为 “a”, “b”

42 mysql “+“ 操作符的实现_concat_16

 

如果这里是 表中的两个字段, 这里也是类似的效果 

select field1 + field2 from tz_test;

42 mysql “+“ 操作符的实现_plus_17

 

然后后面 setup_fields 的时候, 从数据表中获取 a, b 对应的字段, 不存在 该字段

然后 抛出了 ER_BAD_FIELD_ERROR 其错误码为 1054

42 mysql “+“ 操作符的实现_variables_18

 

 

@a, @b 这些变量取自哪里? 

执行 sql 如下 “set @a = 10;”

可以看到 是通过 “a” 从当前 session 的 user_vars 的一个 Map 中存取的变量 

42 mysql “+“ 操作符的实现_字面量_19