cyclic reference test removed, becouse testing of Item::fixed field apply more strict limitation
mysql-test/r/subselect.result: test of cyclic reference false alarm mysql-test/t/subselect.test: test of cyclic reference false alarm
This commit is contained in:
parent
251320477c
commit
a0ddb72d52
@ -122,6 +122,9 @@ SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
|
||||
0
|
||||
SELECT (SELECT * FROM (SELECT 'test' a,'test' b) a);
|
||||
Cardinality error (more/less than 1 columns)
|
||||
SELECT 1 as a,(SELECT a+a) b,(SELECT b);
|
||||
a b (SELECT b)
|
||||
1 2 2
|
||||
create table t1 (a int);
|
||||
create table t2 (a int, b int);
|
||||
create table t3 (a int);
|
||||
|
@ -54,6 +54,8 @@ SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
|
||||
-- error 1239
|
||||
SELECT (SELECT * FROM (SELECT 'test' a,'test' b) a);
|
||||
|
||||
SELECT 1 as a,(SELECT a+a) b,(SELECT b);
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 (a int, b int);
|
||||
create table t3 (a int);
|
||||
|
23
sql/item.cc
23
sql/item.cc
@ -71,19 +71,6 @@ Item_ident::Item_ident(Item_ident &item):
|
||||
depended_from(item.depended_from)
|
||||
{}
|
||||
|
||||
bool Item::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item::check_loop");
|
||||
DBUG_PRINT("info", ("id %u, name %s", id, name));
|
||||
if (loop_id == id)
|
||||
{
|
||||
DBUG_PRINT("info", ("id match"));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
loop_id= id;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
bool Item::check_cols(uint c)
|
||||
{
|
||||
if (c != 1)
|
||||
@ -680,7 +667,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
return 1;
|
||||
r->depended_from= last;
|
||||
cursel->mark_as_dependent(last);
|
||||
thd->add_possible_loop(r);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@ -1170,7 +1156,6 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
||||
}
|
||||
ref= (depended_from= last)->ref_pointer_array + counter-1;
|
||||
thd->lex.current_select->mark_as_dependent(last);
|
||||
thd->add_possible_loop(this);
|
||||
}
|
||||
}
|
||||
else if (!ref)
|
||||
@ -1208,14 +1193,6 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_ref::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_ref::check_loop");
|
||||
if (Item_ident::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN((*ref)->check_loop(id));
|
||||
}
|
||||
|
||||
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
return item->type() == DEFAULT_VALUE_ITEM &&
|
||||
|
@ -92,7 +92,6 @@ public:
|
||||
virtual bool get_date(TIME *ltime,bool fuzzydate);
|
||||
virtual bool get_time(TIME *ltime);
|
||||
virtual bool is_null() { return 0; };
|
||||
virtual bool check_loop(uint id);
|
||||
virtual void top_level_item() {}
|
||||
virtual Item * get_same() { return this; }
|
||||
virtual Item * get_tmp_table_item() { return get_same(); }
|
||||
@ -500,7 +499,6 @@ public:
|
||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||
enum_field_types field_type() const { return (*ref)->field_type(); }
|
||||
table_map used_tables() const { return (*ref)->used_tables(); }
|
||||
bool check_loop(uint id);
|
||||
};
|
||||
|
||||
class Item_in_subselect;
|
||||
@ -689,10 +687,6 @@ public:
|
||||
enum Type type() const { return DEFAULT_VALUE_ITEM; }
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
return Item_field::check_loop(id) || arg->check_loop(id);
|
||||
}
|
||||
void set_outer_resolving() { arg->set_outer_resolving(); }
|
||||
void print(String *str);
|
||||
virtual bool basic_const_item() const { return true; }
|
||||
|
@ -925,16 +925,6 @@ void Item_func_case::set_outer_resolving()
|
||||
Item_func::set_outer_resolving();
|
||||
}
|
||||
|
||||
bool Item_func_case::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_case::check_loop");
|
||||
if (Item_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
DBUG_RETURN((first_expr && first_expr->check_loop(id)) ||
|
||||
(else_expr && else_expr->check_loop(id)));
|
||||
}
|
||||
|
||||
void Item_func_case::update_used_tables()
|
||||
{
|
||||
Item_func::update_used_tables();
|
||||
@ -1486,21 +1476,6 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_cond::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_cond::check_loop");
|
||||
if (Item_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
List_iterator<Item> li(list);
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
{
|
||||
if (item->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
void Item_cond::set_outer_resolving()
|
||||
{
|
||||
Item_func::set_outer_resolving();
|
||||
|
@ -354,7 +354,6 @@ public:
|
||||
void print(String *str);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
Item *find_item(String *str);
|
||||
bool check_loop(uint id);
|
||||
void set_outer_resolving();
|
||||
};
|
||||
|
||||
@ -637,13 +636,6 @@ class Item_func_in :public Item_int_func
|
||||
const char *func_name() const { return " IN "; }
|
||||
void update_used_tables();
|
||||
void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_in::check_loop");
|
||||
if (Item_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(item->check_loop(id));
|
||||
}
|
||||
bool nulls_in_row();
|
||||
void set_outer_resolving()
|
||||
{
|
||||
@ -789,7 +781,6 @@ public:
|
||||
void print(String *str);
|
||||
void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
|
||||
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
|
||||
bool check_loop(uint id);
|
||||
void top_level_item() { abort_on_null=1; }
|
||||
void set_outer_resolving();
|
||||
};
|
||||
|
@ -128,23 +128,6 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_func::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func::check_loop");
|
||||
if (Item_result_field::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
if (arg_count)
|
||||
{
|
||||
Item **arg,**arg_end;
|
||||
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
||||
{
|
||||
if ((*arg)->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
void Item_func::set_outer_resolving()
|
||||
{
|
||||
if (arg_count)
|
||||
@ -2365,20 +2348,6 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_func_match::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_match::check_loop");
|
||||
if (Item_real_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
List_iterator<Item> li(fields);
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
if (item->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
void Item_func_match::set_outer_resolving()
|
||||
{
|
||||
Item_real_func::set_outer_resolving();
|
||||
|
@ -133,7 +133,6 @@ public:
|
||||
friend class udf_handler;
|
||||
Field *tmp_table_field() { return result_field; }
|
||||
Field *tmp_table_field(TABLE *t_arg);
|
||||
bool check_loop(uint id);
|
||||
void set_outer_resolving();
|
||||
Item * get_tmp_table_item();
|
||||
};
|
||||
@ -627,13 +626,6 @@ public:
|
||||
const_item_cache&= item->const_item();
|
||||
with_sum_func= with_sum_func || item->with_sum_func;
|
||||
}
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_field::check_loop");
|
||||
if (Item_int_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(item->check_loop(id));
|
||||
}
|
||||
void set_outer_resolving()
|
||||
{
|
||||
item->set_outer_resolving();
|
||||
@ -1013,7 +1005,6 @@ public:
|
||||
|
||||
bool fix_index();
|
||||
void init_search(bool no_order);
|
||||
bool check_loop(uint id);
|
||||
void set_outer_resolving();
|
||||
};
|
||||
|
||||
|
@ -120,13 +120,3 @@ void Item_row::set_outer_resolving()
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
items[i]->set_outer_resolving();
|
||||
}
|
||||
|
||||
bool Item_row::check_loop(uint id)
|
||||
{
|
||||
if (Item::check_loop(id))
|
||||
return 1;
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
if (items[i]->check_loop(id))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ public:
|
||||
bool const_item() const { return const_item_cache; };
|
||||
enum Item_result result_type() const { return ROW_RESULT; }
|
||||
void update_used_tables();
|
||||
bool check_loop(uint id);
|
||||
void set_outer_resolving();
|
||||
|
||||
uint cols() { return arg_count; }
|
||||
|
@ -106,13 +106,6 @@ public:
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
const char *func_name() const { return "concat_ws"; }
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_concat_ws::check_loop");
|
||||
if (Item_str_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(separator->check_loop(id));
|
||||
}
|
||||
void set_outer_resolving()
|
||||
{
|
||||
separator->set_outer_resolving();
|
||||
@ -389,13 +382,6 @@ public:
|
||||
void fix_length_and_dec();
|
||||
void update_used_tables();
|
||||
const char *func_name() const { return "elt"; }
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_elt::check_loop");
|
||||
if (Item_str_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(item->check_loop(id));
|
||||
}
|
||||
void set_outer_resolving()
|
||||
{
|
||||
item->set_outer_resolving();
|
||||
@ -422,13 +408,6 @@ public:
|
||||
void fix_length_and_dec();
|
||||
void update_used_tables();
|
||||
const char *func_name() const { return "make_set"; }
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_make_set::check_loop");
|
||||
if (Item_str_func::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(item->check_loop(id));
|
||||
}
|
||||
void set_outer_resolving()
|
||||
{
|
||||
item->set_outer_resolving();
|
||||
|
@ -108,15 +108,6 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Item_subselect::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_subselect::check_loop");
|
||||
if (Item_result_field::check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
DBUG_RETURN(engine->check_loop(id));
|
||||
}
|
||||
|
||||
Item::Type Item_subselect::type() const
|
||||
{
|
||||
return SUBSELECT_ITEM;
|
||||
@ -858,21 +849,6 @@ bool subselect_union_engine::uncacheable()
|
||||
return unit->uncacheable;
|
||||
}
|
||||
|
||||
bool subselect_single_select_engine::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("subselect_single_select_engine::check_loop");
|
||||
DBUG_RETURN(join->check_loop(id));
|
||||
}
|
||||
|
||||
bool subselect_union_engine::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("subselect_union_engine::check_loop");
|
||||
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
|
||||
if (sl->join && sl->join->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
void subselect_single_select_engine::exclude()
|
||||
{
|
||||
select_lex->master_unit()->exclude_level();
|
||||
|
@ -83,7 +83,6 @@ public:
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
virtual void fix_length_and_dec();
|
||||
table_map used_tables() const;
|
||||
bool check_loop(uint id);
|
||||
|
||||
friend class select_subselect;
|
||||
friend class Item_in_optimizer;
|
||||
@ -226,7 +225,6 @@ public:
|
||||
virtual bool dependent()= 0; /* depended from outer select */
|
||||
virtual bool uncacheable()= 0; /* query is uncacheable */
|
||||
enum Item_result type() { return res_type; }
|
||||
virtual bool check_loop(uint id)= 0;
|
||||
virtual void exclude()= 0;
|
||||
bool may_be_null() { return maybe_null; };
|
||||
};
|
||||
@ -248,7 +246,6 @@ public:
|
||||
uint cols();
|
||||
bool dependent();
|
||||
bool uncacheable();
|
||||
bool check_loop(uint id);
|
||||
void exclude();
|
||||
};
|
||||
|
||||
@ -266,6 +263,5 @@ public:
|
||||
uint cols();
|
||||
bool dependent();
|
||||
bool uncacheable();
|
||||
bool check_loop(uint id);
|
||||
void exclude();
|
||||
};
|
||||
|
@ -479,14 +479,6 @@ void THD::close_active_vio()
|
||||
}
|
||||
#endif
|
||||
|
||||
void THD::add_possible_loop (Item *item)
|
||||
{
|
||||
if (!possible_loops)
|
||||
{
|
||||
possible_loops= new List<Item>;
|
||||
}
|
||||
possible_loops->push_back(item);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Functions to provide a interface to select results
|
||||
|
@ -506,7 +506,6 @@ public:
|
||||
table_map used_tables;
|
||||
USER_CONN *user_connect;
|
||||
CHARSET_INFO *db_charset;
|
||||
List<Item> *possible_loops; // Items that may cause loops in subselects
|
||||
List<TABLE> temporary_tables_should_be_free; // list of temporary tables
|
||||
List <MYSQL_ERROR> warn_list;
|
||||
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
|
||||
@ -521,7 +520,6 @@ public:
|
||||
uint32 query_length;
|
||||
uint32 db_length;
|
||||
uint select_number; //number of select (used for EXPLAIN)
|
||||
uint check_loops_counter; //last id used to check loops
|
||||
/* variables.transaction_isolation is reset to this after each commit */
|
||||
enum_tx_isolation session_tx_isolation;
|
||||
// extend scramble to handle new auth
|
||||
@ -661,8 +659,6 @@ public:
|
||||
#else
|
||||
void clear_error();
|
||||
#endif
|
||||
|
||||
void add_possible_loop(Item *);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -3146,18 +3146,16 @@ mysql_init_query(THD *thd)
|
||||
lex->select_lex.prev= &lex->unit.slave;
|
||||
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
|
||||
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
|
||||
lex->olap=lex->describe=0;
|
||||
lex->olap=lex->describe= 0;
|
||||
lex->derived_tables= false;
|
||||
lex->lock_option=TL_READ;
|
||||
lex->found_colon=0;
|
||||
thd->check_loops_counter= thd->select_number=
|
||||
lex->select_lex.select_number= 1;
|
||||
lex->lock_option= TL_READ;
|
||||
lex->found_colon= 0;
|
||||
thd->select_number= lex->select_lex.select_number= 1;
|
||||
thd->free_list= 0;
|
||||
thd->total_warn_count=0; // Warnings for this query
|
||||
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
||||
thd->sent_row_count= thd->examined_row_count= 0;
|
||||
thd->fatal_error= thd->rand_used= 0;
|
||||
thd->possible_loops= 0;
|
||||
thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -1274,24 +1274,6 @@ JOIN::cleanup(THD *thd)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
bool JOIN::check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("JOIN::check_loop");
|
||||
Item *item;
|
||||
List_iterator<Item> it(all_fields);
|
||||
DBUG_PRINT("info", ("all_fields:"));
|
||||
while ((item= it++))
|
||||
if (item->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_PRINT("info", ("where:"));
|
||||
if (select_lex->where && select_lex->where->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_PRINT("info", ("having:"));
|
||||
if (select_lex->having && select_lex->having->check_loop(id))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int
|
||||
mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
|
||||
@ -1329,23 +1311,6 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
{
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (thd->possible_loops)
|
||||
{
|
||||
Item *item;
|
||||
while (thd->possible_loops->elements)
|
||||
{
|
||||
item= thd->possible_loops->pop();
|
||||
if (item->check_loop(thd->check_loops_counter++))
|
||||
{
|
||||
delete thd->possible_loops;
|
||||
thd->possible_loops= 0;
|
||||
my_message(ER_CYCLIC_REFERENCE, ER(ER_CYCLIC_REFERENCE), MYF(0));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
delete thd->possible_loops;
|
||||
thd->possible_loops= 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((err= join->optimize()))
|
||||
|
@ -261,7 +261,6 @@ class JOIN :public Sql_alloc
|
||||
int reinit();
|
||||
void exec();
|
||||
int cleanup(THD *thd);
|
||||
bool check_loop(uint id);
|
||||
void restore_tmp();
|
||||
|
||||
inline void init_items_ref_array()
|
||||
|
Loading…
x
Reference in New Issue
Block a user