mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
fixed column number fetchinmg for subqueries. (BUG#8020)
fixed cols() method call (it have to be called only after fix_fields()) mysql-test/r/subselect.result: Comparison subquery with * and row mysql-test/t/subselect.test: Comparison subquery with * and row sql/item_cmpfunc.h: initialization allowed_arg_cols for autodetection sql/item_func.cc: support of allowed_arg_cols autodetection by first argument sql/item_func.h: commant sql/item_subselect.cc: correct column number fetching for subqueries sql/sql_lex.h: method to check that UNION is prepared
This commit is contained in:
@ -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);
|
||||
a1
|
||||
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
|
||||
WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000);
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Test for BUG#7885: Server crash when 'any' subselect compared to
|
||||
# non-existant field.
|
||||
#
|
||||
create table t1 (a1 int);
|
||||
create table t2 (b1 int);
|
||||
--error 1054
|
||||
@ -1423,3 +1426,14 @@ select * from t1 where a2 > any(select b1 from t2);
|
||||
select * from t1 where a1 > any(select b1 from 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
|
||||
public:
|
||||
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);
|
||||
virtual Item *negated_item();
|
||||
@ -390,7 +390,10 @@ class Item_func_interval :public Item_int_func
|
||||
double *intervals;
|
||||
public:
|
||||
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();
|
||||
void fix_length_and_dec();
|
||||
const char *func_name() const { return "interval"; }
|
||||
@ -743,7 +746,7 @@ class Item_func_in :public Item_int_func
|
||||
Item_func_in(List<Item> &list)
|
||||
: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();
|
||||
void fix_length_and_dec();
|
||||
|
@ -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 shouldn't call fix_fields() twice, so check 'fixed' field first
|
||||
*/
|
||||
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
|
||||
(*arg)->check_cols(allowed_arg_cols))
|
||||
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
|
||||
return 1; /* purecov: inspected */
|
||||
|
||||
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)
|
||||
maybe_null=1;
|
||||
|
||||
|
@ -32,6 +32,10 @@ class Item_func :public Item_result_field
|
||||
{
|
||||
protected:
|
||||
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;
|
||||
public:
|
||||
uint arg_count;
|
||||
|
@ -1421,13 +1421,15 @@ int subselect_indexsubquery_engine::exec()
|
||||
|
||||
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()
|
||||
{
|
||||
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 @@ public:
|
||||
|
||||
ulong init_prepare_fake_select_lex(THD *thd);
|
||||
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 int subselect_union_engine::exec();
|
||||
|
Reference in New Issue
Block a user