这篇文章主要介绍“MySQL的隐式转换如何实现及应用”,有一些人在MySQL的隐式转换如何实现及应用的问题上存在疑惑,接下来小编就给大家来介绍一下相关的内容,希望对大家解答有帮助,有这个方面学习需要的朋友就继续往下看吧。
MySQL的隐式转换
一、问题描述
show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
select * from t1;
+——————–+
| id |
+——————–+
| 204027026112927605 |
| 204027026112927603 |
| 2040270261129276 |
| 2040270261129275 |
| 100 |
| 101 |
+——————–+
6 rows in set (0.00 sec)
奇怪的现象:
select * from t1 where id=204027026112927603;
+——————–+
| id |
+——————–+
| 204027026112927605 |
| 204027026112927603 |
+——————–+
2 rows in set (0.00 sec)
二、源码解释
其中JOIN::exec()是执行的入口,Arg_comparator::compare_real()是进行等值判断的函数,其定义如下
int Arg_comparator::compare_real()
{
/*
Fix yet another manifestation of Bug#2338. 'Volatile' will instruct
gcc to flush double values out of 80-bit Intel FPU registers before
performing the comparison.
*/
volatile double val1, val2;
val1= (*a)->val_real();
if (!(*a)->null_value)
{
val2= (*b)->val_real();
if (!(*b)->null_value)
{
if (set_null)
owner->null_value= 0;
if (val1 < val2) return -1;
if (val1 == val2) return 0;
return 1;
}
}
if (set_null)
owner->null_value= 1;
return -1;
}
逐行读取t1表的id列放入val1,而常量204027026112927603存在于cache中,类型为double类型(2.0402702611292762E+17),所以到这里传值给val2后val2=2.0402702611292762E+17。
当扫描到第一行时,204027026112927605转成doule的值为2.0402702611292762e17,等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合
MySQL string转成double的定义函数如下:
{
char buf[DTOA_BUFF_SIZE];
double res;
DBUG_ASSERT(end != NULL && ((str != NULL && *end != NULL) ||
(str == NULL && *end == NULL)) &&
error != NULL);
res= my_strtod_int(str, end, error, buf, sizeof(buf));
return (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX);
}
真正转换函数my_strtod_int位置在dtoa.c
到此这篇关于“MySQL的隐式转换如何实现及应用”的文章就介绍到这了,更多相关内容请继续浏览下面的相关文章,希望大家以后多多支持!