summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2002-11-14 00:26:40 +0200
committerunknown <bell@sanja.is.com.ua>2002-11-14 00:26:40 +0200
commit7642da10d44a5b94bb289573c9ebc0be5aa930d6 (patch)
tree0cff6f15455fc133d757f6e2fc539e63b0e67b2f
parent7721c7582a5d0b03435e4c0a7001fd3b4bf424de (diff)
parent81a5afb925e9c41f7f43e58e8f36d93b5befd364 (diff)
downloadmariadb-git-7642da10d44a5b94bb289573c9ebc0be5aa930d6.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/work-crash-4.1
-rw-r--r--include/mysqld_error.h3
-rw-r--r--mysql-test/r/subselect.result4
-rw-r--r--mysql-test/t/subselect.test4
-rw-r--r--sql/item.cc27
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_cmpfunc.cc32
-rw-r--r--sql/item_cmpfunc.h10
-rw-r--r--sql/item_func.cc29
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/item_strfunc.h21
-rw-r--r--sql/item_subselect.cc25
-rw-r--r--sql/item_subselect.h24
-rw-r--r--sql/share/czech/errmsg.txt3
-rw-r--r--sql/share/danish/errmsg.txt3
-rw-r--r--sql/share/dutch/errmsg.txt3
-rw-r--r--sql/share/english/errmsg.txt3
-rw-r--r--sql/share/estonian/errmsg.txt3
-rw-r--r--sql/share/french/errmsg.txt3
-rw-r--r--sql/share/german/errmsg.txt3
-rw-r--r--sql/share/greek/errmsg.txt3
-rw-r--r--sql/share/hungarian/errmsg.txt3
-rw-r--r--sql/share/italian/errmsg.txt3
-rw-r--r--sql/share/japanese/errmsg.txt3
-rw-r--r--sql/share/korean/errmsg.txt3
-rw-r--r--sql/share/norwegian-ny/errmsg.txt3
-rw-r--r--sql/share/norwegian/errmsg.txt3
-rw-r--r--sql/share/polish/errmsg.txt3
-rw-r--r--sql/share/portuguese/errmsg.txt3
-rw-r--r--sql/share/romanian/errmsg.txt3
-rw-r--r--sql/share/russian/errmsg.txt3
-rw-r--r--sql/share/serbian/errmsg.txt3
-rw-r--r--sql/share/slovak/errmsg.txt3
-rw-r--r--sql/share/spanish/errmsg.txt3
-rw-r--r--sql/share/swedish/errmsg.txt3
-rw-r--r--sql/share/ukrainian/errmsg.txt3
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_select.cc18
-rw-r--r--sql/sql_select.h3
39 files changed, 250 insertions, 40 deletions
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 125059af7fd..456d675a045 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -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
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 5820c3259be..1b799a6cb63 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -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);
@@ -46,7 +48,7 @@ a b
1 7
2 7
3 8
-select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b
1 7
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index cfd22bc48c9..f690a823f85 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1,6 +1,8 @@
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);
@@ -18,7 +20,7 @@ insert into t3 values (6),(7),(3);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
union (select * from t4 order by a limit 2) limit 3;
-select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
diff --git a/sql/item.cc b/sql/item.cc
index ea797679957..f317759553b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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
diff --git a/sql/item.h b/sql/item.h
index fb6bed75d51..c67c16c50ad 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -20,10 +20,11 @@
#endif
struct st_table_list;
-void item_init(void); /* Init item functions */
+void item_init(void); /* Init item functions */
class Item {
- Item(const Item &); /* Prevent use of these */
+ uint loop_id; /* Used to find selfrefering loops */
+ Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
@@ -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);
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index b6ea4beb339..744ed1bceca 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -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)
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index c0dcc2bba8f..489d54ae786 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -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);
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 543a96107dc..aa39b3cc857 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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()
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 1e1f2ba39fc..581809fc9cb 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -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);
};
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 1a3193318b6..2b308630b48 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -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));
+ }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 37c85501b06..1f1944026ef 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -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);
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 58726f16ba9..3ad6c68a6ba 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -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);
};
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index c8ac594f00b..d43a433da06 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -252,4 +252,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 5638260277e..3a947bcbe38 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -246,4 +246,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index acbda2829d0..1cb81849be1 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -254,4 +254,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 36d8831fd39..6e96fdb393e 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 96bd758cc6a..394c40c5778 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -248,4 +248,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 932182a2c94..b18d3f8fb38 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index febd723df89..49ea31dd05b 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -246,4 +246,5 @@
"Subselect return more than 1 field",
"Subselect return more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 9d9aa07af8d..b203c63949b 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index d596c8f3433..07081e689ad 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -245,4 +245,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index d9ccf54d7ea..0a380e2b48f 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 22a53801efd..2e0a083ca06 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -245,4 +245,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 27a8fdde027..19fcf98e3c7 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 8e8b5aa7e61..810aaf38f74 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -245,4 +245,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 0f4650c186c..a74a0a910b8 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -245,4 +245,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 758e96e5ca3..efde31ff4c9 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -247,4 +247,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 21ebe5c39dc..e90d5844b9b 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index c84049d6192..18f0bf7f79d 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -247,4 +247,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 0ee79ce5811..790d738031c 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -246,4 +246,5 @@
"Подзапрос возвращает более одного поля",
"Подзапрос возвращает более одной записи",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Циклическая ссылка на подзапрос",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index d120630b636..e8186d38a5b 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -239,4 +239,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index eb9e2a240a0..216d46fcd3a 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -251,4 +251,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 0b7de283481..5076b1b6679 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -244,4 +244,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 052cd1506d3..a3bb40fb4f5 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -243,4 +243,5 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 5cfad494a32..426c2a14e3b 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -248,4 +248,5 @@
"Пiдзапит поверта╓ бiльш нiж 1 стовбець",
"Пiдзапит поверта╓ бiльш нiж 1 запис",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Циклiчне посилання на пiдзапит",
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 08066e83ee7..6f6547a358c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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];
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6a2c8e17185..1586469de42 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5f4bfc5462a..dd84b2a46c8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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,
diff --git a/sql/sql_select.h b/sql/sql_select.h
index c5b5357be50..3b89c1ce0d3 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -244,7 +244,8 @@ class JOIN :public Sql_alloc
int global_optimize();
int reinit();
void exec();
- int cleanup(THD *thd);
+ int cleanup(THD *thd);
+ bool check_loop(uint id);
};