Bug#33798 prepared statements improperly handle large unsigned ints

The unsignedness of large integer user variables was not being
properly preserved when feeded to prepared statements. This was
happening because the unsigned flags wasn't being updated when
converting the user variable is converted to a parameter.

The solution is to copy the unsigned flag when converting the
user variable to a parameter and take the unsigned flag into
account when converting the integer to a string.
parent bf7991ba
...@@ -567,4 +567,19 @@ master-bin.000001 36585 Rotate 1 36629 master-bin.000002;pos=4 ...@@ -567,4 +567,19 @@ master-bin.000001 36585 Rotate 1 36629 master-bin.000002;pos=4
drop table t1; drop table t1;
set global binlog_cache_size=@bcs; set global binlog_cache_size=@bcs;
set session autocommit = @ac; set session autocommit = @ac;
drop table if exists t1;
reset master;
create table t1 (a bigint unsigned, b bigint(20) unsigned);
prepare stmt from "insert into t1 values (?,?)";
set @a= 9999999999999999;
set @b= 14632475938453979136;
execute stmt using @a, @b;
deallocate prepare stmt;
drop table t1;
show binlog events from 0;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 98 Server version, Binlog ver: 4
master-bin.000001 98 Query 1 219 use `test`; create table t1 (a bigint unsigned, b bigint(20) unsigned)
master-bin.000001 219 Query 1 343 use `test`; insert into t1 values (9999999999999999,14632475938453979136)
master-bin.000001 343 Query 1 419 use `test`; drop table t1
End of 5.0 tests End of 5.0 tests
...@@ -1693,4 +1693,20 @@ t1 CREATE TABLE `t1` ( ...@@ -1693,4 +1693,20 @@ t1 CREATE TABLE `t1` (
`?` decimal(2,1) default NULL `?` decimal(2,1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
drop table if exists t1;
create table t1 (a bigint unsigned, b bigint(20) unsigned);
prepare stmt from "insert into t1 values (?,?)";
set @a= 9999999999999999;
set @b= 14632475938453979136;
insert into t1 values (@a, @b);
select * from t1 where a = @a and b = @b;
a b
9999999999999999 14632475938453979136
execute stmt using @a, @b;
select * from t1 where a = @a and b = @b;
a b
9999999999999999 14632475938453979136
9999999999999999 14632475938453979136
deallocate prepare stmt;
drop table t1;
End of 5.0 tests. End of 5.0 tests.
...@@ -106,4 +106,21 @@ drop table t1; ...@@ -106,4 +106,21 @@ drop table t1;
set global binlog_cache_size=@bcs; set global binlog_cache_size=@bcs;
set session autocommit = @ac; set session autocommit = @ac;
#
# Bug#33798: prepared statements improperly handle large unsigned ints
#
--disable_warnings
drop table if exists t1;
--enable_warnings
reset master;
create table t1 (a bigint unsigned, b bigint(20) unsigned);
prepare stmt from "insert into t1 values (?,?)";
set @a= 9999999999999999;
set @b= 14632475938453979136;
execute stmt using @a, @b;
deallocate prepare stmt;
drop table t1;
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /Server ver: [^,]*,/Server version,/
show binlog events from 0;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -1807,4 +1807,21 @@ execute stmt using @a; ...@@ -1807,4 +1807,21 @@ execute stmt using @a;
show create table t1; show create table t1;
drop table t1; drop table t1;
#
# Bug#33798: prepared statements improperly handle large unsigned ints
#
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (a bigint unsigned, b bigint(20) unsigned);
prepare stmt from "insert into t1 values (?,?)";
set @a= 9999999999999999;
set @b= 14632475938453979136;
insert into t1 values (@a, @b);
select * from t1 where a = @a and b = @b;
execute stmt using @a, @b;
select * from t1 where a = @a and b = @b;
deallocate prepare stmt;
drop table t1;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -2580,6 +2580,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) ...@@ -2580,6 +2580,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
if (entry && entry->value) if (entry && entry->value)
{ {
item_result_type= entry->type; item_result_type= entry->type;
unsigned_flag= entry->unsigned_flag;
if (strict_type && required_result_type != item_result_type) if (strict_type && required_result_type != item_result_type)
DBUG_RETURN(1); DBUG_RETURN(1);
switch (item_result_type) { switch (item_result_type) {
...@@ -2875,6 +2876,9 @@ const String *Item_param::query_val_str(String* str) const ...@@ -2875,6 +2876,9 @@ const String *Item_param::query_val_str(String* str) const
{ {
switch (state) { switch (state) {
case INT_VALUE: case INT_VALUE:
if (unsigned_flag)
str->set((ulonglong) value.integer, &my_charset_bin);
else
str->set(value.integer, &my_charset_bin); str->set(value.integer, &my_charset_bin);
break; break;
case REAL_VALUE: case REAL_VALUE:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment