From 03d411b1d14560ca3b982c7cab2cb78530964806 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Jul 2006 13:41:12 +0500 Subject: [PATCH] Bug#6147: Traditional: Assigning a string to a numeric column has unexpected results The problem was that when converting a string to an exact number, rounding didn't work, because conversion didn't understand approximate numbers notation. Fix: a new function for string-to-number conversion was implemented, which is aware of approxinate number notation (with decimal point and exponent, e.g. -19.55e-1) include/m_ctype.h: Adding new function into MY_CHARSET_HANDLER Adding prototypes for 8bit and ucs2 functions. mysql-test/r/loaddata.result: Fixing results mysql-test/r/ps_2myisam.result: Fixing results mysql-test/r/ps_3innodb.result: Fixing results mysql-test/r/ps_4heap.result: Fixing results mysql-test/r/ps_5merge.result: Fixing results mysql-test/r/ps_6bdb.result: Fixing results mysql-test/r/rpl_rewrite_db.result: Fixing results mysql-test/r/select.result: Fixing results mysql-test/r/sp-vars.result: Fixing results mysql-test/r/strict.result: Fixing results mysql-test/r/view.result: Fixing results mysql-test/r/warnings.result: Fixing results mysql-test/t/strict.test: Fixing results sql/field.cc: Using new function strings/ctype-big5.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-bin.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-cp932.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-euc_kr.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-eucjpms.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-gb2312.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-gbk.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-latin1.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-simple.c: Implementing my_strntoull10_8bit Adding new function into MY_CHARSET_HANDLER strings/ctype-sjis.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-tis620.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-ucs2.c: Implementing UCS2 wrapper for 8bit version Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-ujis.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-utf8.c: Adding new function into the MY_CHARSET_HANDLER structure mysql-test/r/round.result: New BitKeeper file ``mysql-test/r/round.result'' mysql-test/t/round.test: New BitKeeper file ``mysql-test/t/round.test'' --- include/m_ctype.h | 10 + mysql-test/r/loaddata.result | 7 +- mysql-test/r/ps_2myisam.result | 48 ++-- mysql-test/r/ps_3innodb.result | 48 ++-- mysql-test/r/ps_4heap.result | 48 ++-- mysql-test/r/ps_5merge.result | 96 ++++---- mysql-test/r/ps_6bdb.result | 48 ++-- mysql-test/r/round.result | 272 +++++++++++++++++++++++ mysql-test/r/rpl_rewrite_db.result | 7 +- mysql-test/r/select.result | 2 +- mysql-test/r/sp-vars.result | 2 +- mysql-test/r/strict.result | 8 +- mysql-test/r/view.result | 4 +- mysql-test/r/warnings.result | 60 ++--- mysql-test/t/round.test | 145 +++++++++++++ mysql-test/t/strict.test | 8 +- sql/field.cc | 193 +++++++---------- strings/ctype-big5.c | 1 + strings/ctype-bin.c | 1 + strings/ctype-cp932.c | 1 + strings/ctype-euc_kr.c | 1 + strings/ctype-eucjpms.c | 1 + strings/ctype-gb2312.c | 1 + strings/ctype-gbk.c | 1 + strings/ctype-latin1.c | 1 + strings/ctype-simple.c | 337 +++++++++++++++++++++++++++++ strings/ctype-sjis.c | 1 + strings/ctype-tis620.c | 1 + strings/ctype-ucs2.c | 30 +++ strings/ctype-ujis.c | 1 + strings/ctype-utf8.c | 1 + 31 files changed, 1083 insertions(+), 302 deletions(-) create mode 100644 mysql-test/r/round.result create mode 100644 mysql-test/t/round.test diff --git a/include/m_ctype.h b/include/m_ctype.h index 54ae41bf2e0..9dbe277bf82 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -205,6 +205,9 @@ typedef struct my_charset_handler_st int *err); longlong (*strtoll10)(struct charset_info_st *cs, const char *nptr, char **endptr, int *error); + ulonglong (*strntoull10rnd)(struct charset_info_st *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); ulong (*scan)(struct charset_info_st *, const char *b, const char *e, int sq); } MY_CHARSET_HANDLER; @@ -341,6 +344,13 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs, longlong my_strtoll10_ucs2(CHARSET_INFO *cs, const char *nptr, char **endptr, int *error); +ulonglong my_strntoull10rnd_8bit(CHARSET_INFO *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); + void my_fill_8bit(CHARSET_INFO *cs, char* to, uint l, int fill); my_bool my_like_range_simple(CHARSET_INFO *cs, diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 17e1966dbc9..d415bd468e0 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -43,9 +43,9 @@ drop table t1; create table t1 (a int, b char(10)); load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value adjusted for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 Warning 1262 Row 5 was truncated; it contained more data than there were input columns select * from t1; a b @@ -57,7 +57,8 @@ a b truncate table t1; load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: ' +' for column 'a' at row 4 Warning 1261 Row 4 doesn't contain data for all columns select * from t1; a b diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 207d9ea7475..92dc7c342d3 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -2689,21 +2689,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2739,21 +2739,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 13aa549949c..243e6fcd3bf 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index a08dae945bd..524e8b4ff68 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -2673,21 +2673,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2723,21 +2723,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 6682b085097..831037496af 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -2609,21 +2609,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2659,21 +2659,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 @@ -5623,21 +5623,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -5673,21 +5673,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index dc3b984949d..4d7b4b81fd6 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/round.result b/mysql-test/r/round.result new file mode 100644 index 00000000000..e9a80df0f49 --- /dev/null +++ b/mysql-test/r/round.result @@ -0,0 +1,272 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (sint8 tinyint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint8' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-127.4'); +INSERT INTO t1 VALUES ('-127.5'); +INSERT INTO t1 VALUES ('-128.4'); +INSERT INTO t1 VALUES ('-128.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint8' at row 1 +SELECT * FROM t1; +sint8 +0 +1 +127 +127 +0 +-1 +-127 +-128 +-128 +-128 +DROP TABLE t1; +CREATE TABLE t1 (uint8 tinyint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint8' at row 1 +INSERT INTO t1 VALUES ('255.4'); +INSERT INTO t1 VALUES ('255.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint8' at row 1 +SELECT * FROM t1; +uint8 +0 +1 +127 +128 +0 +0 +255 +255 +DROP TABLE t1; +CREATE TABLE t1 (sint16 smallint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint16' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-32767.4'); +INSERT INTO t1 VALUES ('-32767.5'); +INSERT INTO t1 VALUES ('-32768.4'); +INSERT INTO t1 VALUES ('-32768.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint16' at row 1 +SELECT * FROM t1; +sint16 +0 +1 +32767 +32767 +0 +-1 +-32767 +-32768 +-32768 +-32768 +DROP TABLE t1; +CREATE TABLE t1 (uint16 smallint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint16' at row 1 +INSERT INTO t1 VALUES ('65535.4'); +INSERT INTO t1 VALUES ('65535.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint16' at row 1 +SELECT * FROM t1; +uint16 +0 +1 +32767 +32768 +0 +0 +65535 +65535 +DROP TABLE t1; +CREATE TABLE t1 (sint24 mediumint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint24' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-8388607.4'); +INSERT INTO t1 VALUES ('-8388607.5'); +INSERT INTO t1 VALUES ('-8388608.4'); +INSERT INTO t1 VALUES ('-8388608.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint24' at row 1 +SELECT * FROM t1; +sint24 +0 +1 +8388607 +8388607 +0 +-1 +-8388607 +-8388608 +-8388608 +-8388608 +DROP TABLE t1; +CREATE TABLE t1 (uint24 mediumint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint24' at row 1 +INSERT INTO t1 VALUES ('16777215.4'); +INSERT INTO t1 VALUES ('16777215.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint24' at row 1 +SELECT * FROM t1; +uint24 +0 +1 +8388607 +8388608 +0 +0 +16777215 +16777215 +DROP TABLE t1; +CREATE TABLE t1 (sint64 bigint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint64' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-9223372036854775807.4'); +INSERT INTO t1 VALUES ('-9223372036854775807.5'); +INSERT INTO t1 VALUES ('-9223372036854775808.4'); +INSERT INTO t1 VALUES ('-9223372036854775808.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint64' at row 1 +SELECT * FROM t1; +sint64 +0 +1 +9223372036854775807 +9223372036854775807 +0 +-1 +-9223372036854775807 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +DROP TABLE t1; +CREATE TABLE t1 (uint64 bigint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint64' at row 1 +INSERT INTO t1 VALUES ('18446744073709551615.4'); +INSERT INTO t1 VALUES ('18446744073709551615.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint64' at row 1 +INSERT INTO t1 VALUES ('1844674407370955161.0'); +INSERT INTO t1 VALUES ('1844674407370955161.1'); +INSERT INTO t1 VALUES ('1844674407370955161.2'); +INSERT INTO t1 VALUES ('1844674407370955161.3'); +INSERT INTO t1 VALUES ('1844674407370955161.4'); +INSERT INTO t1 VALUES ('1844674407370955161.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0e1'); +INSERT INTO t1 VALUES ('1844674407370955161.1e1'); +INSERT INTO t1 VALUES ('1844674407370955161.2e1'); +INSERT INTO t1 VALUES ('1844674407370955161.3e1'); +INSERT INTO t1 VALUES ('1844674407370955161.4e1'); +INSERT INTO t1 VALUES ('1844674407370955161.5e1'); +INSERT INTO t1 VALUES ('18446744073709551610e-1'); +INSERT INTO t1 VALUES ('18446744073709551611e-1'); +INSERT INTO t1 VALUES ('18446744073709551612e-1'); +INSERT INTO t1 VALUES ('18446744073709551613e-1'); +INSERT INTO t1 VALUES ('18446744073709551614e-1'); +INSERT INTO t1 VALUES ('18446744073709551615e-1'); +SELECT * FROM t1; +uint64 +0 +1 +9223372036854775807 +9223372036854775808 +0 +0 +18446744073709551615 +18446744073709551615 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955162 +18446744073709551610 +18446744073709551611 +18446744073709551612 +18446744073709551613 +18446744073709551614 +18446744073709551615 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955162 +DROP TABLE t1; +CREATE TABLE t1 (str varchar(128), sint64 bigint not null default 0); +INSERT INTO t1 (str) VALUES ('1.5'); +INSERT INTO t1 (str) VALUES ('1.00005e4'); +INSERT INTO t1 (str) VALUES ('1.0005e3'); +INSERT INTO t1 (str) VALUES ('1.005e2'); +INSERT INTO t1 (str) VALUES ('1.05e1'); +INSERT INTO t1 (str) VALUES ('1.5e0'); +INSERT INTO t1 (str) VALUES ('100005e-1'); +INSERT INTO t1 (str) VALUES ('100050e-2'); +INSERT INTO t1 (str) VALUES ('100500e-3'); +INSERT INTO t1 (str) VALUES ('105000e-4'); +INSERT INTO t1 (str) VALUES ('150000e-5'); +UPDATE t1 SET sint64=str; +SELECT * FROM t1; +str sint64 +1.5 2 +1.00005e4 10001 +1.0005e3 1001 +1.005e2 101 +1.05e1 11 +1.5e0 2 +100005e-1 10001 +100050e-2 1001 +100500e-3 101 +105000e-4 11 +150000e-5 2 +DROP TABLE t1; diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result index 71ac39010b5..1b843bffdca 100644 --- a/mysql-test/r/rpl_rewrite_db.result +++ b/mysql-test/r/rpl_rewrite_db.result @@ -67,9 +67,9 @@ drop table t1; create table t1 (a int, b char(10)); load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value adjusted for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 Warning 1262 Row 5 was truncated; it contained more data than there were input columns select * from rewrite.t1; a b @@ -81,7 +81,8 @@ a b truncate table t1; load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: ' +' for column 'a' at row 4 Warning 1261 Row 4 doesn't contain data for all columns select * from rewrite.t1; a b diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e6c590489a0..280df0bdd89 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2734,7 +2734,7 @@ CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01') -0 1 1 1 +1 1 1 1 DROP TABLE t1; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index 83ee188bfa4..14040f8420e 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -896,7 +896,7 @@ sp_var @user_var 0 Warnings: -Warning 1264 Out of range value adjusted for column 'sp_var' at row 1 +Warning 1366 Incorrect integer value: 'Hello, world!' for column 'sp_var' at row 1 DROP PROCEDURE p1; DROP TABLE t1; diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index d0cf11d0511..16464d67301 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -611,9 +611,9 @@ ERROR 22012: Division by 0 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ERROR 22012: Division by 0 INSERT INTO t1 (col1) VALUES (''); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('a59b'); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('1a'); ERROR 01000: Data truncated for column 'col1' at row 1 INSERT IGNORE INTO t1 (col1) VALUES ('2a'); @@ -693,9 +693,9 @@ ERROR 22012: Division by 0 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ERROR 22012: Division by 0 INSERT INTO t1 (col1) VALUES (''); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('a59b'); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('1a'); ERROR 01000: Data truncated for column 'col1' at row 1 INSERT IGNORE INTO t1 (col1) VALUES ('2a'); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72cffb9531c..281cd473c2c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1306,9 +1306,9 @@ a b delete from t1; load data infile '../std_data_ln/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Error 1369 CHECK OPTION failed 'test.v1' -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 4 Error 1369 CHECK OPTION failed 'test.v1' select * from t1; a b diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index f9006ebca37..d66a26ec8c1 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -31,19 +31,19 @@ Error 1064 You have an error in your SQL syntax; check the manual that correspon insert into t1 values (1); insert into t1 values ("hej"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 insert into t1 values ("hej"),("då"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'd?' for column 'a' at row 2 set SQL_WARNINGS=1; insert into t1 values ("hej"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 insert into t1 values ("hej"),("då"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'd?' for column 'a' at row 2 drop table t1; set SQL_WARNINGS=0; drop temporary table if exists not_exists; @@ -187,44 +187,44 @@ create table t1 (a int); insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); update t1 set a='abc'; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 -Warning 1264 Out of range value adjusted for column 'a' at row 3 -Warning 1264 Out of range value adjusted for column 'a' at row 4 -Warning 1264 Out of range value adjusted for column 'a' at row 5 -Warning 1264 Out of range value adjusted for column 'a' at row 6 -Warning 1264 Out of range value adjusted for column 'a' at row 7 -Warning 1264 Out of range value adjusted for column 'a' at row 8 -Warning 1264 Out of range value adjusted for column 'a' at row 9 -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 6 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 7 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 8 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 9 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 2, 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 show warnings limit 0, 10; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 -Warning 1264 Out of range value adjusted for column 'a' at row 3 -Warning 1264 Out of range value adjusted for column 'a' at row 4 -Warning 1264 Out of range value adjusted for column 'a' at row 5 -Warning 1264 Out of range value adjusted for column 'a' at row 6 -Warning 1264 Out of range value adjusted for column 'a' at row 7 -Warning 1264 Out of range value adjusted for column 'a' at row 8 -Warning 1264 Out of range value adjusted for column 'a' at row 9 -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 6 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 7 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 8 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 9 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 9, 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 10, 1; Level Code Message show warnings limit 9, 2; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 0, 0; Level Code Message show warnings limit 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 show warnings limit 0; Level Code Message show warnings limit 1, 0; diff --git a/mysql-test/t/round.test b/mysql-test/t/round.test new file mode 100644 index 00000000000..d018fa7e34e --- /dev/null +++ b/mysql-test/t/round.test @@ -0,0 +1,145 @@ +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (sint8 tinyint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-127.4'); +INSERT INTO t1 VALUES ('-127.5'); +INSERT INTO t1 VALUES ('-128.4'); +INSERT INTO t1 VALUES ('-128.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint8 tinyint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('255.4'); +INSERT INTO t1 VALUES ('255.5'); +SELECT * FROM t1; +DROP TABLE t1; + + +CREATE TABLE t1 (sint16 smallint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-32767.4'); +INSERT INTO t1 VALUES ('-32767.5'); +INSERT INTO t1 VALUES ('-32768.4'); +INSERT INTO t1 VALUES ('-32768.5'); +SELECT * FROM t1; +DROP TABLE t1; + + +CREATE TABLE t1 (uint16 smallint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('65535.4'); +INSERT INTO t1 VALUES ('65535.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (sint24 mediumint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-8388607.4'); +INSERT INTO t1 VALUES ('-8388607.5'); +INSERT INTO t1 VALUES ('-8388608.4'); +INSERT INTO t1 VALUES ('-8388608.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint24 mediumint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('16777215.4'); +INSERT INTO t1 VALUES ('16777215.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (sint64 bigint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-9223372036854775807.4'); +INSERT INTO t1 VALUES ('-9223372036854775807.5'); +INSERT INTO t1 VALUES ('-9223372036854775808.4'); +INSERT INTO t1 VALUES ('-9223372036854775808.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint64 bigint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('18446744073709551615.4'); +INSERT INTO t1 VALUES ('18446744073709551615.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0'); +INSERT INTO t1 VALUES ('1844674407370955161.1'); +INSERT INTO t1 VALUES ('1844674407370955161.2'); +INSERT INTO t1 VALUES ('1844674407370955161.3'); +INSERT INTO t1 VALUES ('1844674407370955161.4'); +INSERT INTO t1 VALUES ('1844674407370955161.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0e1'); +INSERT INTO t1 VALUES ('1844674407370955161.1e1'); +INSERT INTO t1 VALUES ('1844674407370955161.2e1'); +INSERT INTO t1 VALUES ('1844674407370955161.3e1'); +INSERT INTO t1 VALUES ('1844674407370955161.4e1'); +INSERT INTO t1 VALUES ('1844674407370955161.5e1'); +INSERT INTO t1 VALUES ('18446744073709551610e-1'); +INSERT INTO t1 VALUES ('18446744073709551611e-1'); +INSERT INTO t1 VALUES ('18446744073709551612e-1'); +INSERT INTO t1 VALUES ('18446744073709551613e-1'); +INSERT INTO t1 VALUES ('18446744073709551614e-1'); +INSERT INTO t1 VALUES ('18446744073709551615e-1'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (str varchar(128), sint64 bigint not null default 0); +INSERT INTO t1 (str) VALUES ('1.5'); +INSERT INTO t1 (str) VALUES ('1.00005e4'); +INSERT INTO t1 (str) VALUES ('1.0005e3'); +INSERT INTO t1 (str) VALUES ('1.005e2'); +INSERT INTO t1 (str) VALUES ('1.05e1'); +INSERT INTO t1 (str) VALUES ('1.5e0'); +INSERT INTO t1 (str) VALUES ('100005e-1'); +INSERT INTO t1 (str) VALUES ('100050e-2'); +INSERT INTO t1 (str) VALUES ('100500e-3'); +INSERT INTO t1 (str) VALUES ('105000e-4'); +INSERT INTO t1 (str) VALUES ('150000e-5'); +UPDATE t1 SET sint64=str; +SELECT * FROM t1; +DROP TABLE t1; + + diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index ce269b42ee9..75ac0be7aff 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -635,9 +635,9 @@ UPDATE t1 SET col2 =col2 + 50 WHERE col2 > 0; UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0; --error 1365 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES (''); ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES ('a59b'); --error 1265 INSERT INTO t1 (col1) VALUES ('1a'); @@ -696,9 +696,9 @@ INSERT INTO t1 (col2) VALUES(18446744073709551616.0); UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0; --error 1365 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES (''); ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES ('a59b'); --error 1265 INSERT INTO t1 (col1) VALUES ('1a'); diff --git a/sql/field.cc b/sql/field.cc index 946351efe36..2b6af888dd4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2580,30 +2580,27 @@ void Field_new_decimal::sql_type(String &str) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > 255) { - tmp=0; /* purecov: inspected */ - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp > 255) - { - tmp= 255; + set_if_smaller(tmp, 255); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + ptr[0]= (char) tmp; } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < -128) { tmp= -128; @@ -2618,8 +2615,10 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + ptr[0]= (char) tmp; } - ptr[0]= (char) tmp; return error; } @@ -2784,30 +2783,34 @@ void Field_tiny::sql_type(String &res) const int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > UINT_MAX16) { - tmp=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp > UINT_MAX16) - { - tmp=UINT_MAX16; + set_if_smaller(tmp, UINT_MAX16); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; +#ifdef WORDS_BIGENDIAN + if (table->s->db_low_byte_first) + { + int2store(ptr,tmp); + } + else +#endif + shortstore(ptr,(short) tmp); } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < INT_MIN16) { tmp= INT_MIN16; @@ -2822,15 +2825,17 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; - } + else + error= 0; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - { - int2store(ptr,tmp); - } - else + if (table->s->db_low_byte_first) + { + int2store(ptr,tmp); + } + else #endif - shortstore(ptr,(short) tmp); + shortstore(ptr,(short) tmp); + } return error; } @@ -3058,30 +3063,27 @@ void Field_short::sql_type(String &res) const int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > UINT_MAX24) { - tmp=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp >= (long) (1L << 24)) - { - tmp=(long) (1L << 24)-1L; + set_if_smaller(tmp, UINT_MAX24); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + int3store(ptr,tmp); } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < INT_MIN24) { tmp= INT_MIN24; @@ -3096,9 +3098,10 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + int3store(ptr,tmp); } - - int3store(ptr,tmp); return error; } @@ -3294,64 +3297,47 @@ static bool test_if_minus(CHARSET_INFO *cs, int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) { - ulong tmp_scan; - longlong tmp; long store_tmp; int error; char *end; - tmp_scan= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= tmp_scan; - from+= tmp_scan; - - end= (char*) from+len; - tmp= cs->cset->strtoll10(cs, from, &end, &error); - - if (error != MY_ERRNO_EDOM) + if (unsigned_flag) { - if (unsigned_flag) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > (ulonglong) UINT_MAX32) { - if (error < 0) - { - error= 1; - tmp= 0; - } - else if ((ulonglong) tmp > (ulonglong) UINT_MAX32) - { - tmp= UINT_MAX32; - error= 1; - } - else - error= 0; + set_if_smaller(tmp, (ulonglong) UINT_MAX32); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; } + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; else - { - if (error < 0) - { - error= 0; - if (tmp < INT_MIN32) - { - tmp= INT_MIN32; - error= 1; - } - } - else if (tmp > INT_MAX32) - { - tmp= INT_MAX32; - error= 1; - } - } + error= 0; + store_tmp= (long) tmp; } - if (error) + else { - error= error != MY_ERRNO_EDOM ? 1 : 2; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); + if (tmp < INT_MIN32) + { + tmp= INT_MIN32; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; + } + else if (tmp > INT_MAX32) + { + tmp=INT_MAX32; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; + } + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; + else + error= 0; + store_tmp= (long) tmp; } - else if (from+len != end && table->in_use->count_cuted_fields && - check_int(from,len,end,cs)) - error= 2; - store_tmp= (long) tmp; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -3587,33 +3573,20 @@ void Field_long::sql_type(String &res) const int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) { - longlong tmp; - int error= 0; + int error; char *end; + ulonglong tmp; - tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= (uint)tmp; - from+= tmp; - if (unsigned_flag) - { - if (!len || test_if_minus(cs, from, from + len)) - { - tmp=0; // Set negative to 0 - error= 1; - } - else - tmp=(longlong) my_strntoull(cs,from,len,10,&end,&error); - } - else - tmp=my_strntoll(cs,from,len,10,&end,&error); - if (error) + tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error); + if (error == MY_ERRNO_ERANGE) { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } - else if (from+len != end && table->in_use->count_cuted_fields && - check_int(from,len,end,cs)) - error= 2; + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; + else + error= 0; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 0ca1cf21129..479fb789816 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6370,6 +6370,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 54c35c82652..0bd5a1fda76 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -517,6 +517,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index 5f8a93b1c2b..b4e9ba16d92 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5492,6 +5492,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index d6df46f7e05..40e0f4e3d2d 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8711,6 +8711,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 348eb2f6e87..65fef2dfc4c 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -8677,6 +8677,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 29ecafc3527..c2fc1e2c190 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5762,6 +5762,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index ef1b33fd82c..c4d06d67eb9 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -10015,6 +10015,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index a3f5aec9605..1298b66bb7e 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -411,6 +411,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 12ef77c59b1..e40a1948dcf 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -17,6 +17,7 @@ #include #include "m_string.h" #include "m_ctype.h" +#include "my_sys.h" /* Needed for MY_ERRNO_ERANGE */ #include #include "stdarg.h" @@ -1354,6 +1355,341 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)), } +#undef ULONGLONG_MAX +/* + Needed under MetroWerks Compiler, since MetroWerks compiler does not + properly handle a constant expression containing a mod operator +*/ +#if defined(__NETWARE__) && defined(__MWERKS__) +static ulonglong ulonglong_max= ~(ulonglong) 0; +#define ULONGLONG_MAX ulonglong_max +#else +#define ULONGLONG_MAX (~(ulonglong) 0) +#endif /* __NETWARE__ && __MWERKS__ */ + + +#define CUTOFF (ULONGLONG_MAX / 10) +#define CUTLIM (ULONGLONG_MAX % 10) +#define DIGITS_IN_ULONGLONG 20 + +static ulonglong d10[DIGITS_IN_ULONGLONG]= +{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; + + +/* + + Convert a string to unsigned long long integer value + with rounding. + + SYNOPSYS + my_strntoull10_8bit() + cs in pointer to character set + str in pointer to the string to be converted + length in string length + unsigned_flag in whether the number is unsigned + endptr out pointer to the stop character + error out returned error code + + DESCRIPTION + This function takes the decimal representation of integer number + from string str and converts it to an signed or unsigned + long long integer value. + Space characters and tab are ignored. + A sign character might precede the digit characters. + The number may have any number of pre-zero digits. + The number may have decimal point and exponent. + Rounding is always done in "away from zero" style: + 0.5 -> 1 + -0.5 -> -1 + + The function stops reading the string str after "length" bytes + or at the first character that is not a part of correct number syntax: + + ::= + [ ] [ E [ ] ] + + ::= + [ [ ] ] + | + ::= ... + + RETURN VALUES + Value of string as a signed/unsigned longlong integer + + endptr cannot be NULL. The function will store the end pointer + to the stop character here. + + The error parameter contains information how things went: + 0 ok + ERANGE If the the value of the converted number is out of range + In this case the return value is: + - ULONGLONG_MAX if unsigned_flag and the number was too big + - 0 if unsigned_flag and the number was negative + - LONGLONG_MAX if no unsigned_flag and the number is too big + - LONGLONG_MIN if no unsigned_flag and the number it too big negative + + EDOM If the string didn't contain any digits. + In this case the return value is 0. +*/ + +ulonglong +my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *str, uint length, int unsigned_flag, + char **endptr, int *error) +{ + const char *dot, *end9, *beg, *end= str + length; + ulonglong ull; + ulong ul; + unsigned char ch; + int shift= 0, digits= 0, negative, addon; + + /* Skip leading spaces and tabs */ + for ( ; str < end && (*str == ' ' || *str == '\t') ; str++); + + if (str >= end) + goto ret_edom; + + if ((negative= (*str == '-')) || *str=='+') /* optional sign */ + { + if (++str == end) + goto ret_edom; + } + + beg= str; + end9= (str + 9) > end ? end : (str + 9); + /* Accumulate small number into ulong, for performance purposes */ + for (ul= 0 ; str < end9 && (ch= (unsigned char) (*str - '0')) < 10; str++) + { + ul= ul * 10 + ch; + } + + if (str >= end) /* Small number without dots and expanents */ + { + *endptr= (char*) str; + if (negative) + { + if (unsigned_flag) + { + *error= ul ? MY_ERRNO_ERANGE : 0; + return 0; + } + else + { + *error= 0; + return (ulonglong) (longlong) (long) -ul; + } + } + else + { + *error=0; + return (ulonglong) ul; + } + } + + digits= str - beg; + + /* Continue to accumulate into ulonglong */ + for (dot= NULL, ull= ul; str < end; str++) + { + if ((ch= (unsigned char) (*str - '0')) < 10) + { + if (ull < CUTOFF || (ull == CUTOFF && ch <= CUTLIM)) + { + ull= ull * 10 + ch; + digits++; + continue; + } + /* + Adding the next digit would overflow. + Remember the next digit in "addon", for rounding. + Scan all digits with an optional single dot. + */ + if (ull == CUTOFF) + { + ull= ULONGLONG_MAX; + addon= 1; + str++; + } + else + addon= (*str >= '5'); + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++) + { + if (!dot) + shift++; + } + if (str < end && *str == '.' && !dot) + { + str++; + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++); + } + goto exp; + } + + if (*str == '.') + { + if (dot) + { + /* The second dot character */ + addon= 0; + goto exp; + } + else + { + dot= str + 1; + } + continue; + } + + /* Unknown character, exit the loop */ + break; + } + shift= dot ? dot - str : 0; /* Right shift */ + addon= 0; + +exp: /* [ E [ ] ] */ + + if (!digits) + { + str= beg; + goto ret_edom; + } + + if (str < end && (*str == 'e' || *str == 'E')) + { + str++; + if (str < end) + { + int negative_exp, exp; + if ((negative_exp= (*str == '-')) || *str=='+') + { + if (++str == end) + goto ret_sign; + } + for (exp= 0 ; + str < end && (ch= (unsigned char) (*str - '0')) < 10; + str++) + { + exp= exp * 10 + ch; + } + shift+= negative_exp ? -exp : exp; + } + } + + if (shift == 0) /* No shift, check addon digit */ + { + if (addon) + { + if (ull == ULONGLONG_MAX) + goto ret_too_big; + ull++; + } + goto ret_sign; + } + + if (shift < 0) /* Right shift */ + { + ulonglong d, r; + + if (-shift >= DIGITS_IN_ULONGLONG) + goto ret_zero; /* Exponent is a big negative number, return 0 */ + + d= d10[-shift]; + r= (ull % d) * 2; + ull /= d; + if (r >= d) + ull++; + goto ret_sign; + } + + if (shift > DIGITS_IN_ULONGLONG) /* Huge left shift */ + { + if (!ull) + goto ret_sign; + goto ret_too_big; + } + + for ( ; shift > 0; shift--, ull*= 10) /* Left shift */ + { + if (ull > CUTOFF) + goto ret_too_big; /* Overflow, number too big */ + } + +ret_sign: + *endptr= (char*) str; + + if (!unsigned_flag) + { + if (negative) + { + if (ull > (ulonglong) LONGLONG_MIN) + { + *error= MY_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MIN; + } + *error= 0; + return (ulonglong) -ull; + } + else + { + if (ull > (ulonglong) LONGLONG_MAX) + { + *error= MY_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MAX; + } + *error= 0; + return ull; + } + } + + /* Unsigned number */ + if (negative && ull) + { + *error= MY_ERRNO_ERANGE; + return 0; + } + *error= 0; + return ull; + +ret_zero: + *endptr= (char*) str; + *error= 0; + return 0; + +ret_edom: + *endptr= (char*) str; + *error= MY_ERRNO_EDOM; + return 0; + +ret_too_big: + *endptr= (char*) str; + *error= MY_ERRNO_ERANGE; + return unsigned_flag ? + ULONGLONG_MAX : + negative ? (ulonglong) LONGLONG_MIN : (ulonglong) LONGLONG_MAX; +} + + /* Check if a constant can be propagated @@ -1434,6 +1770,7 @@ MY_CHARSET_HANDLER my_charset_8bit_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 57d6d8bae2b..3854837e09a 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4663,6 +4663,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index dc4f18b516b..85ebbe82731 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -891,6 +891,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 97dca79e84b..4a60220f73e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -974,6 +974,35 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), } +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *nptr, uint length, int unsign_fl, + char **endptr, int *err) +{ + char buf[256], *b= buf; + ulonglong res; + const uchar *end, *s= (const uchar*) nptr; + my_wc_t wc; + int cnv; + + /* Cut too long strings */ + if (length >= sizeof(buf)) + length= sizeof(buf)-1; + end= s + length; + + while ((cnv= cs->cset->mb_wc(cs,&wc,s,end)) > 0) + { + s+= cnv; + if (wc > (int) (uchar) 'e' || !wc) + break; /* Can't be a number part */ + *b++= (char) wc; + } + + res= my_strntoull10rnd_8bit(cs, buf, b - buf, unsign_fl, endptr, err); + *endptr= (char*) nptr + 2 * (uint) (*endptr- buf); + return res; +} + + /* This is a fast version optimized for the case of radix 10 / -10 */ @@ -1629,6 +1658,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler= my_strntoull_ucs2, my_strntod_ucs2, my_strtoll10_ucs2, + my_strntoull10rnd_ucs2, my_scan_ucs2 }; diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index ca27b4bef6b..675ac918e2c 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8545,6 +8545,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 3594ab954c6..3a5c01a2861 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2548,6 +2548,7 @@ MY_CHARSET_HANDLER my_charset_utf8_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit };