diff options
author | unknown <konstantin@mysql.com> | 2005-05-05 12:55:09 +0400 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2005-05-05 12:55:09 +0400 |
commit | c758512a9176b40532f8431e7771f8dbeed77111 (patch) | |
tree | 63803fbeb418fd4efd8e3bc6fe890e46fef1ee1e | |
parent | f3883ad0fa972a10c88431e92768a05bda8d774b (diff) | |
download | mariadb-git-c758512a9176b40532f8431e7771f8dbeed77111.tar.gz |
A fix and test case for Bug#9777 " Empty set returned by Prepared Statement when it
should return a non empty one"
(see comments for the changed files for details).
mysql-test/r/ps.result:
A test case for Bug#9777: tests results fixed.
mysql-test/t/ps.test:
A test case for Bug#9777
sql/item.cc:
A fix for Bug#9777: when creating a constant item from within
Item_int_with_ref::new_item, create the item by value, not by name.
This should work with prepared statements placeholders.
Item_int_with_ref is a special optimization case used
when we compare datetime constants with datetime value.
Converting the item to integer early is OK as it is in line
with the purpose of Item_int_with_ref - to speed up comparison by
using integers.
Minor cleanups.
sql/item.h:
Declaration for Item_int_with_ref::new_item
-rw-r--r-- | mysql-test/r/ps.result | 38 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 47 | ||||
-rw-r--r-- | sql/item.cc | 24 | ||||
-rw-r--r-- | sql/item.h | 7 |
4 files changed, 110 insertions, 6 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index df3e24afd1a..d66114fe44e 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -519,3 +519,41 @@ c1 c2 200887 860 200887 200887 deallocate prepare stmt; +drop table t1; +create table t1 ( +id bigint(20) not null auto_increment, +code varchar(20) character set utf8 collate utf8_bin not null default '', +company_name varchar(250) character set utf8 collate utf8_bin default null, +setup_mode tinyint(4) default null, +start_date datetime default null, +primary key (id), unique key code (code) +); +create table t2 ( +id bigint(20) not null auto_increment, +email varchar(250) character set utf8 collate utf8_bin default null, +name varchar(250) character set utf8 collate utf8_bin default null, +t1_id bigint(20) default null, +password varchar(250) character set utf8 collate utf8_bin default null, +primary_contact tinyint(4) not null default '0', +email_opt_in tinyint(4) not null default '1', +primary key (id), unique key email (email), key t1_id (t1_id), +constraint t2_fk1 foreign key (t1_id) references t1 (id) +); +insert into t1 values +(1, 'demo', 'demo s', 0, current_date()), +(2, 'code2', 'name 2', 0, current_date()), +(3, 'code3', 'name 3', 0, current_date()); +insert into t2 values +(2, 'email1', 'name1', 3, 'password1', 0, 0), +(3, 'email2', 'name1', 1, 'password2', 1, 0), +(5, 'email3', 'name3', 2, 'password3', 0, 0); +prepare stmt from 'select t2.id from t2, t1 where (t1.id=? and t2.t1_id=t1.id)'; +set @a=1; +execute stmt using @a; +id +3 +select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id); +id +3 +deallocate prepare stmt; +drop table t1, t2; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index ef36b8b1b0b..96b83a09497 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -522,3 +522,50 @@ set @a=200887, @b=860; # this query did not return all matching rows execute stmt using @a, @b; deallocate prepare stmt; +drop table t1; + +# +# Bug#9777 - another occurrence of the problem stated in Bug#9096: +# we can not compare basic constants by their names, because a placeholder +# is a basic constant while his name is always '?' +# + +create table t1 ( + id bigint(20) not null auto_increment, + code varchar(20) character set utf8 collate utf8_bin not null default '', + company_name varchar(250) character set utf8 collate utf8_bin default null, + setup_mode tinyint(4) default null, + start_date datetime default null, + primary key (id), unique key code (code) +); + +create table t2 ( + id bigint(20) not null auto_increment, + email varchar(250) character set utf8 collate utf8_bin default null, + name varchar(250) character set utf8 collate utf8_bin default null, + t1_id bigint(20) default null, + password varchar(250) character set utf8 collate utf8_bin default null, + primary_contact tinyint(4) not null default '0', + email_opt_in tinyint(4) not null default '1', + primary key (id), unique key email (email), key t1_id (t1_id), + constraint t2_fk1 foreign key (t1_id) references t1 (id) +); + +insert into t1 values +(1, 'demo', 'demo s', 0, current_date()), +(2, 'code2', 'name 2', 0, current_date()), +(3, 'code3', 'name 3', 0, current_date()); + +insert into t2 values +(2, 'email1', 'name1', 3, 'password1', 0, 0), +(3, 'email2', 'name1', 1, 'password2', 1, 0), +(5, 'email3', 'name3', 2, 'password3', 0, 0); + +prepare stmt from 'select t2.id from t2, t1 where (t1.id=? and t2.t1_id=t1.id)'; +set @a=1; +execute stmt using @a; + +select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id); + +deallocate prepare stmt; +drop table t1, t2; diff --git a/sql/item.cc b/sql/item.cc index 7e74bb1fd85..211e165cc6b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -769,6 +769,13 @@ Item_uint::Item_uint(const char *str_arg, uint length): } +Item_uint::Item_uint(const char *str_arg, longlong i, uint length): + Item_int(str_arg, i, length) +{ + unsigned_flag= 1; +} + + String *Item_uint::val_str(String *str) { // following assert is redundant, because fixed=1 assigned in constructor @@ -1377,7 +1384,9 @@ Item_param::new_item() case NULL_VALUE: return new Item_null(name); case INT_VALUE: - return new Item_int(name, value.integer, max_length); + return (unsigned_flag ? + new Item_uint(name, value.integer, max_length) : + new Item_int(name, value.integer, max_length)); case REAL_VALUE: return new Item_real(name, value.real, decimals, max_length); case STRING_VALUE: @@ -2023,6 +2032,19 @@ bool Item_int::eq(const Item *arg, bool binary_cmp) const } +Item *Item_int_with_ref::new_item() +{ + DBUG_ASSERT(ref->basic_const_item()); + /* + We need to evaluate the constant to make sure it works with + parameter markers. + */ + return (ref->unsigned_flag ? + new Item_uint(ref->name, ref->val_int(), ref->max_length) : + new Item_int(ref->name, ref->val_int(), ref->max_length)); +} + + Item_num *Item_uint::neg() { return new Item_real(name, - ((double) value), 0, max_length); diff --git a/sql/item.h b/sql/item.h index 3f3ff491bb5..6f1f56451ab 100644 --- a/sql/item.h +++ b/sql/item.h @@ -651,6 +651,7 @@ class Item_uint :public Item_int { public: Item_uint(const char *str_arg, uint length); + Item_uint(const char *str_arg, longlong i, uint length); Item_uint(uint32 i) :Item_int((longlong) i, 10) { unsigned_flag= 1; } double val() @@ -1046,11 +1047,7 @@ public: { return ref->save_in_field(field, no_conversions); } - Item *new_item() - { - return (ref->unsigned_flag)? new Item_uint(ref->name, ref->max_length) : - new Item_int(ref->name, ref->max_length); - } + Item *new_item(); }; |