diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index c96173e74cc..9d2da82813f 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -521,8 +521,8 @@ select count(*) from t1 where x = 18446744073709551601; count(*) 1 create table t2 (x bigint not null); -insert into t2(x) values (cast(0xfffffffffffffff0+0 as signed)); -insert into t2(x) values (cast(0xfffffffffffffff1+0 as signed)); +insert into t2(x) values (-16); +insert into t2(x) values (-15); select * from t2; x -16 diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index a7f6f638966..d31be4390f7 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2811,6 +2811,23 @@ select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; min(key1) 0.37619999051094 DROP TABLE t1,t2; +create table t1(a bigint unsigned, b bigint); +insert into t1 values (0xfffffffffffffffff, 0xfffffffffffffffff), +(0x10000000000000000, 0x10000000000000000), +(0x8fffffffffffffff, 0x8fffffffffffffff); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1264 Out of range value adjusted for column 'b' 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 'b' at row 2 +Warning 1264 Out of range value adjusted for column 'b' at row 3 +select hex(a), hex(b) from t1; +hex(a) hex(b) +FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF +8FFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF +drop table t1; +End of 4.1 tests CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000', diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index f3883077919..fad0e1f7974 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -568,7 +568,7 @@ create table t1 (a bit(7)); insert into t1 values (0x60); select * from t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 a a 16 7 1 Y 0 0 63 +def test t1 t1 a a 16 7 1 Y 32 0 63 a ` drop table t1; diff --git a/mysql-test/r/type_bit_innodb.result b/mysql-test/r/type_bit_innodb.result index 1f6857277bd..c4506231f27 100644 --- a/mysql-test/r/type_bit_innodb.result +++ b/mysql-test/r/type_bit_innodb.result @@ -406,7 +406,7 @@ create table t1 (a bit(7)) engine=innodb; insert into t1 values (0x60); select * from t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 a a 16 7 1 Y 0 0 63 +def test t1 t1 a a 16 7 1 Y 32 0 63 a ` drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5f00aa60b11..749864c1f59 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1171,6 +1171,7 @@ deallocate prepare stmt2; # Protect ourselves from data left in tmp/ by a previos possibly failed # test --system rm -f $MYSQLTEST_VARDIR/tmp/t1.* +--disable_warnings --disable_query_log eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'"; --enable_query_log @@ -1190,6 +1191,7 @@ execute stmt; --disable_result_log show create table t1; --enable_result_log +--enable_warnings drop table t1; deallocate prepare stmt; diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 5a146bbcf86..c7f27d7ca08 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -406,8 +406,8 @@ select count(*) from t1 where x = 18446744073709551601; create table t2 (x bigint not null); -insert into t2(x) values (cast(0xfffffffffffffff0+0 as signed)); -insert into t2(x) values (cast(0xfffffffffffffff1+0 as signed)); +insert into t2(x) values (-16); +insert into t2(x) values (-15); select * from t2; select count(*) from t2 where x>0; select count(*) from t2 where x=0; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 332389220f6..e8d864b81f9 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2349,7 +2349,18 @@ select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; DROP TABLE t1,t2; --enable_ps_protocol -# End of 4.1 tests +# +# Bug #22533: storing large hex strings +# + +create table t1(a bigint unsigned, b bigint); +insert into t1 values (0xfffffffffffffffff, 0xfffffffffffffffff), + (0x10000000000000000, 0x10000000000000000), + (0x8fffffffffffffff, 0x8fffffffffffffff); +select hex(a), hex(b) from t1; +drop table t1; + +--echo End of 4.1 tests # # Test for bug #6474 diff --git a/mysys/string.c b/mysys/string.c index 0928bca809a..df78f2b98b5 100644 --- a/mysys/string.c +++ b/mysys/string.c @@ -131,37 +131,35 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) { #ifdef __WIN__ - char quote_str[]= "\""; + const char *quote_str= "\""; + const uint quote_len= 1; #else - char quote_str[]= "\'"; + const char *quote_str= "\'"; + const uint quote_len= 1; #endif /* __WIN__ */ my_bool ret= TRUE; va_list dirty_text; - ret&= dynstr_append(str, quote_str); /* Leading quote */ - va_start(dirty_text,append); + ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */ + va_start(dirty_text, append); while (append != NullS) { - char *cur_pos= append; - char *next_pos= cur_pos; + const char *cur_pos= append; + const char *next_pos= cur_pos; /* Search for quote in each string and replace with escaped quote */ while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0') { - char *tmp_buff= my_malloc((next_pos - cur_pos) + 1, MYF(MY_ZEROFILL)); - strnmov(tmp_buff, cur_pos, (next_pos - cur_pos)); - ret&= dynstr_append(str, tmp_buff); - my_free((gptr)tmp_buff, MYF(0)); - - ret&= dynstr_append(str ,"\\"); - ret&= dynstr_append(str, quote_str); + ret&= dynstr_append_mem(str, cur_pos, next_pos - cur_pos); + ret&= dynstr_append_mem(str ,"\\", 1); + ret&= dynstr_append_mem(str, quote_str, quote_len); cur_pos= next_pos + 1; } - ret&= dynstr_append(str, cur_pos); + ret&= dynstr_append_mem(str, cur_pos, next_pos - cur_pos); append= va_arg(dirty_text, char *); } va_end(dirty_text); - ret&= dynstr_append(str, quote_str); /* Trailing quote */ + ret&= dynstr_append_mem(str, quote_str, quote_len); /* Trailing quote */ return ret; } diff --git a/sql/field.cc b/sql/field.cc index 32b2631d071..efe608b7bdd 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8037,6 +8037,7 @@ Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7), bytes_in_rec(len_arg / 8) { + flags|= UNSIGNED_FLAG; /* Ensure that Field::eq() can distinguish between two different bit fields. (two bit fields that are not null, may have same ptr and null_ptr) @@ -8276,6 +8277,7 @@ Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg, : Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, 0, 0, unireg_check_arg, field_name_arg, table_arg) { + flags|= UNSIGNED_FLAG; bit_len= 0; bytes_in_rec= (len_arg + 7) / 8; } diff --git a/sql/item.cc b/sql/item.cc index cc653a7db14..d73be7206d6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4553,18 +4553,31 @@ my_decimal *Item_hex_string::val_decimal(my_decimal *decimal_value) int Item_hex_string::save_in_field(Field *field, bool no_conversions) { - int error; field->set_notnull(); if (field->result_type() == STRING_RESULT) + return field->store(str_value.ptr(), str_value.length(), + collation.collation); + + ulonglong nr; + uint32 length= str_value.length(); + if (length > 8) { - error=field->store(str_value.ptr(),str_value.length(),collation.collation); + nr= field->flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX; + goto warn; } - else + nr= (ulonglong) val_int(); + if ((length == 8) && !(field->flags & UNSIGNED_FLAG) && (nr > LONGLONG_MAX)) { - longlong nr=val_int(); - error=field->store(nr, TRUE); // Assume hex numbers are unsigned + nr= LONGLONG_MAX; + goto warn; } - return error; + return field->store((longlong) nr, TRUE); // Assume hex numbers are unsigned + +warn: + if (!field->store((longlong) nr, TRUE)) + field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, + 1); + return 1; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 1937f74f797..792f955d729 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -12923,7 +12923,6 @@ static void test_bug15518() DIE_UNLESS(rc && mysql_stmt_errno(stmt)); mysql_stmt_close(stmt); - DIE_UNLESS(mysql_errno(mysql1)); }