Commit 7642da10 authored by unknown's avatar unknown

Merge sanja.is.com.ua:/home/bell/mysql/mysql-4.1

into sanja.is.com.ua:/home/bell/mysql/work-crash-4.1

parents 7721c758 81a5afb9
......@@ -259,4 +259,5 @@
#define ER_SUBSELECT_NO_1_ROW 1240
#define ER_UNKNOWN_STMT_HANDLER 1241
#define ER_CORRUPT_HELP_DB 1242
#define ER_ERROR_MESSAGES 243
#define ER_CYCLIC_REFERENCE 1243
#define ER_ERROR_MESSAGES 244
......@@ -8,6 +8,8 @@ SELECT (SELECT 1) UNION SELECT (SELECT 2);
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
SELECT (SELECT 1 FROM (SELECT 1) HAVING a=1) as a;
Cyclic reference on subqueries
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
create table t1 (a int);
create table t2 (a int, b int);
......
select (select 2);
SELECT (SELECT 1) UNION SELECT (SELECT 2);
SELECT (SELECT (SELECT 0 UNION SELECT 0));
-- error 1243
SELECT (SELECT 1 FROM (SELECT 1) HAVING a=1) as a;
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
create table t1 (a int);
create table t2 (a int, b int);
......
......@@ -42,6 +42,20 @@ Item::Item()
decimals=0; max_length=0;
next=current_thd->free_list; // Put in free list
current_thd->free_list=this;
loop_id= 0;
}
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);
}
void Item::set_name(const char *str,uint length)
......@@ -862,6 +876,11 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
depended_from= last;
thd->lex.current_select->mark_as_dependent(last);
if (check_loop(thd->check_loops_counter++))
{
my_message(ER_CYCLIC_REFERENCE, ER(ER_CYCLIC_REFERENCE), MYF(0));
return 1;
}
}
}
else if (!ref)
......@@ -873,6 +892,14 @@ 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));
}
/*
** If item is a const function, calculate it and return a const item
** The original item is freed if not returned
......
......@@ -23,6 +23,7 @@ struct st_table_list;
void item_init(void); /* Init item functions */
class Item {
uint loop_id; /* Used to find selfrefering loops */
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
......@@ -88,6 +89,8 @@ public:
virtual CHARSET_INFO *charset() const { return str_value.charset(); };
virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
virtual bool check_loop(uint id);
};
......@@ -434,6 +437,7 @@ public:
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
table_map used_tables() const { return (*ref)->used_tables(); }
bool check_loop(uint id);
};
......
......@@ -344,6 +344,14 @@ void Item_func_interval::update_used_tables()
const_item_cache&=item->const_item();
}
bool Item_func_interval::check_loop(uint id)
{
DBUG_ENTER("Item_func_interval::check_loop");
if (Item_func::check_loop(id))
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
void Item_func_between::fix_length_and_dec()
{
max_length=1;
......@@ -776,6 +784,16 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0;
}
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();
......@@ -1137,6 +1155,20 @@ 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::split_sum_func(List<Item> &fields)
{
......
......@@ -186,6 +186,7 @@ public:
~Item_func_interval() { delete item; }
const char *func_name() const { return "interval"; }
void update_used_tables();
bool check_loop(uint id);
};
......@@ -262,6 +263,7 @@ 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);
};
......@@ -424,6 +426,13 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
void update_used_tables();
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));
}
};
......@@ -563,6 +572,7 @@ public:
void print(String *str);
void split_sum_func(List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id);
};
......
......@@ -126,6 +126,22 @@ 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::split_sum_func(List<Item> &fields)
{
......@@ -2264,6 +2280,19 @@ 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);
}
bool Item_func_match::fix_index()
{
......
......@@ -128,6 +128,7 @@ public:
bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id);
};
......@@ -606,6 +607,13 @@ 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));
}
};
......@@ -971,6 +979,7 @@ public:
bool fix_index();
void init_search(bool no_order);
bool check_loop(uint id);
};
......
......@@ -105,6 +105,13 @@ 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));
}
};
class Item_func_reverse :public Item_str_func
......@@ -361,6 +368,13 @@ 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));
}
};
......@@ -381,6 +395,13 @@ 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));
}
};
......
......@@ -95,6 +95,15 @@ 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));
}
void Item_subselect::fix_length_and_dec()
{
engine->fix_length_and_dec();
......@@ -228,6 +237,7 @@ subselect_single_select_engine::subselect_single_select_engine(THD *thd,
thd->fatal_error= 1;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
}
unit->item= item;
this->select_lex= select_lex;
}
......@@ -353,3 +363,18 @@ bool subselect_union_engine::depended()
{
return unit->dependent;
}
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);
}
......@@ -70,6 +70,7 @@ 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;
};
......@@ -176,6 +177,7 @@ public:
virtual uint cols()= 0; /* return number of columnss in select */
virtual bool depended()= 0; /* depended from outer select */
enum Item_result type() { return res_type; }
virtual bool check_loop(uint id)= 0;
};
class subselect_single_select_engine: public subselect_engine
......@@ -189,11 +191,12 @@ public:
subselect_single_select_engine(THD *thd, st_select_lex *select,
select_subselect *result,
Item_subselect *item);
virtual int prepare();
virtual void fix_length_and_dec();
virtual int exec();
virtual uint cols();
virtual bool depended();
int prepare();
void fix_length_and_dec();
int exec();
uint cols();
bool depended();
bool check_loop(uint id);
};
class subselect_union_engine: public subselect_engine
......@@ -204,9 +207,10 @@ public:
st_select_lex_unit *u,
select_subselect *result,
Item_subselect *item);
virtual int prepare();
virtual void fix_length_and_dec();
virtual int exec();
virtual uint cols();
virtual bool depended();
int prepare();
void fix_length_and_dec();
int exec();
uint cols();
bool depended();
bool check_loop(uint id);
};
......@@ -253,3 +253,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -247,3 +247,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -255,3 +255,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -249,3 +249,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -247,3 +247,4 @@
"Subselect return more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -246,3 +246,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -246,3 +246,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -246,3 +246,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -246,3 +246,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -248,3 +248,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -248,3 +248,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -247,3 +247,4 @@
" ",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
" ",
......@@ -240,3 +240,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -252,3 +252,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -245,3 +245,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -244,3 +244,4 @@
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
......@@ -249,3 +249,4 @@
"i i i 1 ",
"Unknown prepared statement handler (%ld) given to %s",
"Help database is corrupt or does not exist",
"i i",
......@@ -494,6 +494,7 @@ 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;
char scramble[9];
......
......@@ -2867,7 +2867,8 @@ mysql_init_query(THD *thd)
lex->select_lex.prev= &lex->unit.slave;
lex->olap=lex->describe=0;
lex->derived_tables= false;
thd->select_number= lex->select_lex.select_number= 1;
thd->check_loops_counter= 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;
......
......@@ -1035,6 +1035,24 @@ 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, TABLE_LIST *tables, List<Item> &fields, COND *conds,
ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
......
......@@ -245,6 +245,7 @@ class JOIN :public Sql_alloc
int reinit();
void exec();
int cleanup(THD *thd);
bool check_loop(uint id);
};
......
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