diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 105a5a2c406..11d831fe85a 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -261,4 +261,5 @@ #define ER_CORRUPT_HELP_DB 1242 #define ER_CYCLIC_REFERENCE 1243 #define ER_AUTO_CONVERT 1244 -#define ER_ERROR_MESSAGES 245 +#define ER_ILLEGAL_REFERENCE 1246 +#define ER_ERROR_MESSAGES 246 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index e54e1fb0fef..df56a43e5ba 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -9,9 +9,9 @@ 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 +Reference 'a' not supported (forward reference in item list) SELECT (SELECT 1 FROM (SELECT 1) HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) HAVING a=1) as b; -Cyclic reference on subqueries +Reference 'b' not supported (forward reference in item list) drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; create table t1 (a int); create table t2 (a int, b int); @@ -20,6 +20,8 @@ create table t4 (a int, b int); insert into t1 values (2); insert into t2 values (1,7),(2,7); insert into t4 values (4,8),(3,8),(5,9); +select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1; +Reference 'a1' not supported (forward reference in item list) select (select a from t1 where t1.a=t2.a), a from t2; (select a from t1 where t1.a=t2.a) a NULL 1 @@ -278,6 +280,12 @@ PRIMARY KEY (`numeropost`,`numreponse`), UNIQUE KEY `numreponse` (`numreponse`), KEY `pseudo` (`pseudo`,`numeropost`) ) TYPE=MyISAM; +SELECT (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a),numreponse FROM (SELECT * FROM threadhardwarefr7) as a; +Reference 'numreponse' not supported (forward reference in item list) +SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a) FROM (SELECT * FROM threadhardwarefr7) as a; +Unknown column 'a' in 'having clause' +SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=1) FROM (SELECT * FROM threadhardwarefr7) as a; +numreponse (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=1) INSERT INTO threadhardwarefr7 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test'); EXPLAIN SELECT numreponse FROM threadhardwarefr7 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM threadhardwarefr7 WHERE numeropost='1'); Subselect returns more than 1 record diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 7a507be4ed2..68deebd2177 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1,9 +1,9 @@ select (select 2); SELECT (SELECT 1) UNION SELECT (SELECT 2); SELECT (SELECT (SELECT 0 UNION SELECT 0)); --- error 1243 +-- error 1244 SELECT (SELECT 1 FROM (SELECT 1) HAVING a=1) as a; --- error 1243 +-- error 1244 SELECT (SELECT 1 FROM (SELECT 1) HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) HAVING a=1) as b; drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; create table t1 (a int); @@ -13,6 +13,8 @@ create table t4 (a int, b int); insert into t1 values (2); insert into t2 values (1,7),(2,7); insert into t4 values (4,8),(3,8),(5,9); +-- error 1244 +select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1; select (select a from t1 where t1.a=t2.a), a from t2; select (select a from t1 where t1.a=t2.b), a from t2; select (select a from t1), a from t2; @@ -176,6 +178,11 @@ CREATE TABLE `threadhardwarefr7` ( UNIQUE KEY `numreponse` (`numreponse`), KEY `pseudo` (`pseudo`,`numeropost`) ) TYPE=MyISAM; +-- error 1244 +SELECT (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a),numreponse FROM (SELECT * FROM threadhardwarefr7) as a; +-- error 1054 +SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a) FROM (SELECT * FROM threadhardwarefr7) as a; +SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=1) FROM (SELECT * FROM threadhardwarefr7) as a; INSERT INTO threadhardwarefr7 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test'); -- error 1240 EXPLAIN SELECT numreponse FROM threadhardwarefr7 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM threadhardwarefr7 WHERE numeropost='1'); diff --git a/sql/item.cc b/sql/item.cc index 48ec11d02c2..b56486c5027 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -34,7 +34,8 @@ void item_init(void) item_user_lock_init(); } -Item::Item() +Item::Item(): + fixed(0) { marker=0; maybe_null=null_value=with_sum_func=unsigned_flag=0; @@ -139,6 +140,7 @@ CHARSET_INFO * Item::thd_charset() const Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) { set_field(f); + fixed= 1; // This item is not needed in fix_fields } @@ -438,6 +440,7 @@ bool Item::fix_fields(THD *thd, struct st_table_list *list, Item ** ref) { + fixed= 1; return 0; } @@ -459,23 +462,48 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) */ SELECT_LEX *last= 0; + Item **refer= (Item **)not_found_item; // Prevent using outer fields in subselects, that is not supported now if (thd->lex.current_select->linkage != DERIVED_TABLE_TYPE) for (SELECT_LEX *sl= thd->lex.current_select->outer_select(); sl; sl= sl->outer_select()) + { if ((tmp= find_field_in_tables(thd, this, (last= sl)->get_table_list(), 0)) != not_found_field) break; + if((refer= find_item_in_list(this, (last= sl)->item_list, + REPORT_EXCEPT_NOT_FOUND)) != + (Item **)not_found_item) + break; + + } if (!tmp) return -1; - else if (tmp == not_found_field) + else if (!refer) + return 1; + else if (tmp == not_found_field && refer == (Item **)not_found_item) { // call to return error code find_field_in_tables(thd, this, tables, 1); return -1; } + else if (refer != (Item **)not_found_item) + { + Item_ref *r; + *ref= r= new Item_ref((char *)db_name, (char *)table_name, + (char *)field_name); + if (!r) + return 1; + int res; + if ((res= r->fix_fields(thd, tables, ref))) + return res; + r->depended_from= last; + thd->lex.current_select->mark_as_dependent(last); + thd->add_possible_loop(r); + return 0; + } else { depended_from= last; @@ -507,6 +535,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 1; return (*ref)->fix_fields(thd, tables, ref); } + fixed= 1; return 0; } @@ -885,6 +914,19 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; } + if (((*ref)->with_sum_func && + (depended_from || + !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE && + thd->lex.current_select->select_lex()->having_fix_field))) || + !(*ref)->fixed) + { + my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, + ((*ref)->with_sum_func? + "reference on group function": + "forward reference in item list")); + return 1; + } + fixed= 1; return 0; } diff --git a/sql/item.h b/sql/item.h index c67c16c50ad..7228b5dc785 100644 --- a/sql/item.h +++ b/sql/item.h @@ -46,6 +46,7 @@ public: my_bool null_value; /* if item is null */ my_bool unsigned_flag; my_bool with_sum_func; + my_bool fixed; /* If item fixed with fix_fields */ // alloc & destruct is done as start of select using sql_alloc Item(); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 74eb5734ecf..a3c8328bb06 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1152,6 +1152,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (thd) thd->cond_count+=list.elements; fix_length_and_dec(); + fixed= 1; return 0; } @@ -1425,6 +1426,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } else maybe_null=1; + fixed= 1; return 0; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 4c7985cd1bf..ed395a40246 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -123,6 +123,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } } fix_length_and_dec(); + fixed= 1; return 0; } diff --git a/sql/item_func.h b/sql/item_func.h index 8996919e284..ac8ae962d94 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -754,6 +754,7 @@ public: bool res= udf.fix_fields(thd, tables, this, arg_count, args); used_tables_cache= udf.used_tables_cache; const_item_cache= udf.const_item_cache; + fixed= 1; return res; } Item_result result_type () const { return udf.result_type(); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1a561c9eb34..6a0aaa3b032 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2065,6 +2065,7 @@ bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables, I const_item_cache=args[0]->const_item(); set_charset(conv_charset); fix_length_and_dec(); + fixed= 1; return 0; } @@ -2099,6 +2100,7 @@ bool Item_func_set_collation::fix_fields(THD *thd,struct st_table_list *tables, used_tables_cache=args[0]->used_tables(); const_item_cache=args[0]->const_item(); fix_length_and_dec(); + fixed= 1; return 0; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 1f1944026ef..01ce5fad4a6 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -92,6 +92,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } fix_length_and_dec(); } + fixed= 1; return res; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index db4c45fc412..9c7a73a6904 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -135,6 +135,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) null_value=1; fix_length_and_dec(); thd->allow_sum_func=1; // Allow group functions + fixed= 1; return 0; } @@ -165,6 +166,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) null_value=1; fix_length_and_dec(); thd->allow_sum_func=1; // Allow group functions + fixed= 1; return 0; } diff --git a/sql/item_sum.h b/sql/item_sum.h index 3e67f1e3624..cc49ac8578f 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -384,6 +384,7 @@ public: const char *func_name() const { return udf.name(); } bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { + fixed= 1; return udf.fix_fields(thd,tables,this,this->arg_count,this->args); } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } diff --git a/sql/item_uniq.h b/sql/item_uniq.h index f0d1d353cfb..2004be63de2 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -43,5 +43,9 @@ public: bool add() { return 0; } void reset_field() {} void update_field(int offset) {} - bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;} + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) + { + fixed= 1; + return 0; + } }; diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 0eef4ae9cad..16b7ec54b45 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -255,3 +255,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index c2e0ddb064f..91857f8add6 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -249,3 +249,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 7a3f7b787b2..ebfb24f6631 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -257,3 +257,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index e746b461a6d..78a95d940b4 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -246,3 +246,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index ee20b9890c4..60c8e49170c 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -251,3 +251,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 89b82b3851b..84c5ce591c7 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -246,3 +246,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 3b354ee3298..fc51117144a 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -249,3 +249,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 38ce4217888..6107a48a0d8 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -246,3 +246,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index f2fd63765d9..f2d93a8493f 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -248,3 +248,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 2b24a123e25..31d1cd798db 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -246,3 +246,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 7b428cae703..8a6d5c71226 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -248,3 +248,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 8fbc33bf690..ab693752d2d 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -246,3 +246,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 1c3cf11e10c..13af3a2047d 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -248,3 +248,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 1db0068685c..58a67dcec7f 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -248,3 +248,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index bda25b01065..66a500b11c7 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -250,3 +250,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 947f935fd33..1b0e170ee45 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -246,3 +246,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 71baf4ca098..12d26800848 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -250,3 +250,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 03ea8b74ce5..47e83e1c325 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -249,3 +249,4 @@ "Help database is corrupt or does not exist", "Циклическая ссылка на подзапрос", "Converting column '%s' from %s to %s" +"Ссылка '%-.64s' не поддерживается (%s)", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 0ee69010aca..0951cd14db6 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -242,3 +242,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 36f5e421561..4a849c98abb 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -254,3 +254,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 5a087d6fa17..6218f1b3201 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -247,3 +247,4 @@ "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 42f2e72ec45..e8d9235d405 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -246,3 +246,4 @@ "HjДlp databasen finns inte eller Дr skadad", "Syklisk referens i subselect", "Konvertar kolumn '%s' frЕn %s till %s" +"Reference '%-.64s' not supported (%s)", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index f41041de2bb..5c74f431fd3 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -251,3 +251,4 @@ "Help database is corrupt or does not exist", "Циклiчне посилання на пiдзапит", "Converting column '%s' from %s to %s" +"Посилання '%-.64s' не пiдтримуется (%s)",