国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

解析MySQL隱式轉換問題

2024-07-24 12:41:41
字體:
來源:轉載
供稿:網友

一、問題描述

root@mysqldb 22:12: [xucl]> show create table t1/G*************************** 1. row *************************** Table: t1Create Table: CREATE TABLE `t1` ( `id` varchar(255) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec) root@mysqldb 22:19: [xucl]> select * from t1;+--------------------+| id   |+--------------------+| 204027026112927605 || 204027026112927603 || 2040270261129276 || 2040270261129275 || 100  || 101  |+--------------------+6 rows in set (0.00 sec)

奇怪的現象:

root@mysqldb 22:19: [xucl]> select * from t1 where id=204027026112927603;+--------------------+| id   |+--------------------+| 204027026112927605 || 204027026112927603 |+--------------------+2 rows in set (0.00 sec)640?wx_fmt=jpeg

什么鬼,明明查的是204027026112927603,為什么204027026112927605也出來了

二、源碼解釋

堆棧調用關系如下所示:

其中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也同樣符合

如何檢測string類型的數字轉成doule類型是否溢出呢?這里經過測試,當數字超過16位以后,轉成double類型就已經不準確了,例如20402702611292711會表示成20402702611292712(如圖中val1)

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(太復雜了,簡單貼個注釋吧)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 扬中市| 内乡县| 衡山县| 开阳县| 甘孜| 江孜县| 柯坪县| 湘乡市| 抚州市| 万盛区| 台北市| 保德县| 大丰市| 剑河县| 西吉县| 普宁市| 炎陵县| 东方市| 咸丰县| 古田县| 桐庐县| 曲水县| 瑞昌市| 江北区| 黄陵县| 遂昌县| 桃江县| 新竹县| 东乡| 银川市| 大名县| 花莲市| 柯坪县| 东明县| 淮安市| 汕尾市| 连云港市| 会同县| 鹤峰县| 郴州市| 聊城市|