diff options
-rw-r--r-- | mysql-test/r/subselect.result | 11 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 15 | ||||
-rw-r--r-- | sql/item.h | 13 | ||||
-rw-r--r-- | sql/item_func.cc | 15 | ||||
-rw-r--r-- | sql/item_func.h | 1 |
5 files changed, 52 insertions, 3 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6d8cb7f5b9a..6710b8fc941 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4749,4 +4749,15 @@ sum(a) sub 1 3 deallocate prepare stmt1; drop table t1,t2; +# +# Bug LP#693935/#58727: Assertion failure with +# a single row subquery returning more than one row +# +create table t1 (a char(1) charset utf8); +insert into t1 values ('a'), ('b'); +create table t2 (a binary(1)); +insert into t2 values ('x'), ('y'); +select * from t2 where a=(select a from t1) and a='x'; +ERROR 21000: Subquery returns more than 1 row +drop table t1,t2; End of 5.1 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index bd333d5a649..9bacaaaf6ec 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3759,4 +3759,19 @@ deallocate prepare stmt1; drop table t1,t2; +--echo # +--echo # Bug LP#693935/#58727: Assertion failure with +--echo # a single row subquery returning more than one row +--echo # + +create table t1 (a char(1) charset utf8); +insert into t1 values ('a'), ('b'); +create table t2 (a binary(1)); +insert into t2 values ('x'), ('y'); + +-- error ER_SUBQUERY_NO_1_ROW +select * from t2 where a=(select a from t1) and a='x'; + +drop table t1,t2; + --echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index f66892a76cc..4bee370642e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -556,10 +556,17 @@ public: Field *make_string_field(TABLE *table); virtual bool fix_fields(THD *, Item **); /* - should be used in case where we are sure that we do not need + This method should be used in case where we are sure that we do not need complete fix_fields() procedure. - */ - inline void quick_fix_field() { fixed= 1; } + Usually this method is used by the optimizer when it has to create a new + item out of other already fixed items. For example, if the optimizer has + to create a new Item_func for an inferred equality whose left and right + parts are already fixed items. In some cases the optimizer cannot use + directly fixed items as the arguments of the created functional item, + but rather uses intermediate type conversion items. Then the method is + supposed to be applied recursively. + */ + virtual inline void quick_fix_field() { fixed= 1; } /* Function returns 1 on overflow and -1 on fatal errors */ int save_in_field_no_warnings(Field *field, bool no_conversions); virtual int save_in_field(Field *field, bool no_conversions); diff --git a/sql/item_func.cc b/sql/item_func.cc index c35db7ad1cb..ab84303101c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -202,6 +202,21 @@ Item_func::fix_fields(THD *thd, Item **ref) return FALSE; } +void +Item_func::quick_fix_field() +{ + Item **arg,**arg_end; + if (arg_count) + { + for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) + { + if (!(*arg)->fixed) + (*arg)->quick_fix_field(); + } + } + fixed= 1; +} + bool Item_func::walk(Item_processor processor, bool walk_subquery, uchar *argument) diff --git a/sql/item_func.h b/sql/item_func.h index e45638472e4..3d2cb709ce3 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -117,6 +117,7 @@ public: // Constructor used for Item_cond_and/or (see Item comment) Item_func(THD *thd, Item_func *item); bool fix_fields(THD *, Item **ref); + void quick_fix_field(); table_map used_tables() const; table_map not_null_tables() const; void update_used_tables(); |