Commit 76ae5cac authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

fixed column number fetchinmg for subqueries. (BUG#8020)

fixed cols() method call (it have to be called only after fix_fields())
parent 5e36e831
...@@ -2160,3 +2160,17 @@ ERROR 42S22: Unknown column 'a2' in 'scalar IN/ALL/ANY subquery' ...@@ -2160,3 +2160,17 @@ ERROR 42S22: Unknown column 'a2' in 'scalar IN/ALL/ANY subquery'
select * from t1 where a1 > any(select b1 from t2); select * from t1 where a1 > any(select b1 from t2);
a1 a1
drop table t1,t2; drop table t1,t2;
create table t1 (a integer, b integer);
select (select * from t1) = (select 1,2);
(select * from t1) = (select 1,2)
NULL
select (select 1,2) = (select * from t1);
(select 1,2) = (select * from t1)
NULL
select row(1,2) = ANY (select * from t1);
row(1,2) = ANY (select * from t1)
0
select row(1,2) != ALL (select * from t1);
row(1,2) != ALL (select * from t1)
1
drop table t1;
...@@ -1414,8 +1414,11 @@ SELECT f1 FROM t1 ...@@ -1414,8 +1414,11 @@ SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000); WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000);
drop table t1,t2; drop table t1,t2;
#
# Test for BUG#7885: Server crash when 'any' subselect compared to # Test for BUG#7885: Server crash when 'any' subselect compared to
# non-existant field. # non-existant field.
#
create table t1 (a1 int); create table t1 (a1 int);
create table t2 (b1 int); create table t2 (b1 int);
--error 1054 --error 1054
...@@ -1423,3 +1426,14 @@ select * from t1 where a2 > any(select b1 from t2); ...@@ -1423,3 +1426,14 @@ select * from t1 where a2 > any(select b1 from t2);
select * from t1 where a1 > any(select b1 from t2); select * from t1 where a1 > any(select b1 from t2);
drop table t1,t2; drop table t1,t2;
#
# Comparison subquery with * and row
#
create table t1 (a integer, b integer);
select (select * from t1) = (select 1,2);
select (select 1,2) = (select * from t1);
# queries whih can be converted to IN
select row(1,2) = ANY (select * from t1);
select row(1,2) != ALL (select * from t1);
drop table t1;
...@@ -213,7 +213,7 @@ class Item_bool_rowready_func2 :public Item_bool_func2 ...@@ -213,7 +213,7 @@ class Item_bool_rowready_func2 :public Item_bool_func2
public: public:
Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b) Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
{ {
allowed_arg_cols= a->cols(); allowed_arg_cols= 0; // Fetch this value from first argument
} }
Item *neg_transformer(THD *thd); Item *neg_transformer(THD *thd);
virtual Item *negated_item(); virtual Item *negated_item();
...@@ -390,7 +390,10 @@ class Item_func_interval :public Item_int_func ...@@ -390,7 +390,10 @@ class Item_func_interval :public Item_int_func
double *intervals; double *intervals;
public: public:
Item_func_interval(Item_row *a) Item_func_interval(Item_row *a)
:Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); } :Item_int_func(a),row(a),intervals(0)
{
allowed_arg_cols= 0; // Fetch this value from first argument
}
longlong val_int(); longlong val_int();
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "interval"; } const char *func_name() const { return "interval"; }
...@@ -743,7 +746,7 @@ class Item_func_in :public Item_int_func ...@@ -743,7 +746,7 @@ class Item_func_in :public Item_int_func
Item_func_in(List<Item> &list) Item_func_in(List<Item> &list)
:Item_int_func(list), array(0), in_item(0), have_null(0) :Item_int_func(list), array(0), in_item(0), have_null(0)
{ {
allowed_arg_cols= args[0]->cols(); allowed_arg_cols= 0; // Fetch this value from first argument
} }
longlong val_int(); longlong val_int();
void fix_length_and_dec(); void fix_length_and_dec();
......
...@@ -303,10 +303,24 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -303,10 +303,24 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
We can't yet set item to *arg as fix_fields may change *arg We can't yet set item to *arg as fix_fields may change *arg
We shouldn't call fix_fields() twice, so check 'fixed' field first We shouldn't call fix_fields() twice, so check 'fixed' field first
*/ */
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) || if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
(*arg)->check_cols(allowed_arg_cols))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
item= *arg; item= *arg;
if (allowed_arg_cols)
{
if (item->check_cols(allowed_arg_cols))
return 1;
}
else
{
/* we have to fetch allowed_arg_cols from first argument */
DBUG_ASSERT(arg == args); // it is first argument
allowed_arg_cols= item->cols();
DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
}
if (item->maybe_null) if (item->maybe_null)
maybe_null=1; maybe_null=1;
......
...@@ -32,6 +32,10 @@ class Item_func :public Item_result_field ...@@ -32,6 +32,10 @@ class Item_func :public Item_result_field
{ {
protected: protected:
Item **args, *tmp_arg[2]; Item **args, *tmp_arg[2];
/*
Allowed numbers of columns in result (usually 1, which means scalar value)
0 means get this number from first argument
*/
uint allowed_arg_cols; uint allowed_arg_cols;
public: public:
uint arg_count; uint arg_count;
......
...@@ -1421,13 +1421,15 @@ int subselect_indexsubquery_engine::exec() ...@@ -1421,13 +1421,15 @@ int subselect_indexsubquery_engine::exec()
uint subselect_single_select_engine::cols() uint subselect_single_select_engine::cols()
{ {
return select_lex->item_list.elements; DBUG_ASSERT(select_lex->join); // should be called after fix_fields()
return select_lex->join->fields_list.elements;
} }
uint subselect_union_engine::cols() uint subselect_union_engine::cols()
{ {
return unit->first_select()->item_list.elements; DBUG_ASSERT(unit->is_prepared()); // should be called after fix_fields()
return unit->types.elements;
} }
......
...@@ -371,6 +371,7 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -371,6 +371,7 @@ class st_select_lex_unit: public st_select_lex_node {
ulong init_prepare_fake_select_lex(THD *thd); ulong init_prepare_fake_select_lex(THD *thd);
int change_result(select_subselect *result, select_subselect *old_result); int change_result(select_subselect *result, select_subselect *old_result);
inline bool is_prepared() { return prepared; }
friend void lex_start(THD *thd, uchar *buf, uint length); friend void lex_start(THD *thd, uchar *buf, uint length);
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
......
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