summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/subselect.result11
-rw-r--r--mysql-test/t/subselect.test15
-rw-r--r--sql/item.h13
-rw-r--r--sql/item_func.cc15
-rw-r--r--sql/item_func.h1
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();