diff options
author | Georgi Kodinov <joro@sun.com> | 2009-05-27 16:05:29 +0300 |
---|---|---|
committer | Georgi Kodinov <joro@sun.com> | 2009-05-27 16:05:29 +0300 |
commit | bbe29a00d3ca24d4aa9c8c3b7c3f7bd8bcbd3389 (patch) | |
tree | 84a2cbd1035921bbaa22dbb65522b2d16b307602 | |
parent | cb07978da9a24244cf71d9be86eeb794088f67c7 (diff) | |
download | mariadb-git-bbe29a00d3ca24d4aa9c8c3b7c3f7bd8bcbd3389.tar.gz |
Bug #38159: Function parsing problem generates misleading error message
Added a more detailed error message on calling an ambiguous missing function.
-rw-r--r-- | mysql-test/r/ps.result | 4 | ||||
-rw-r--r-- | mysql-test/r/sp-error.result | 10 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 4 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 13 | ||||
-rw-r--r-- | sql/item_func.cc | 10 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 3 | ||||
-rw-r--r-- | sql/sql_derived.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.cc | 16 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 3 | ||||
-rw-r--r-- | sql/table.cc | 1 |
11 files changed, 60 insertions, 7 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 43c50998e20..e8e75c82b93 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -502,7 +502,7 @@ deallocate prepare stmt; create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; -ERROR 42000: FUNCTION test.char_length does not exist +ERROR 42000: FUNCTION test.char_length does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual drop table t1; prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0"; execute stmt; @@ -1147,7 +1147,7 @@ End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; -ERROR 42000: FUNCTION test.char_length does not exist +ERROR 42000: FUNCTION test.char_length does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual drop table t1; create table t1 (a char(3) not null, b char(3) not null, c char(3) not null, primary key (a, b, c)); diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index e83e8c2c71d..bf25f93cceb 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1520,3 +1520,13 @@ CALL p1((SELECT * FROM t1))| ERROR 21000: Subquery returns more than 1 row DROP PROCEDURE IF EXISTS p1| DROP TABLE t1| +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT MAX (a) FROM t1 WHERE b = 999999; +ERROR 42000: FUNCTION test.MAX does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT AVG (a) FROM t1 WHERE b = 999999; +AVG (a) +NULL +SELECT non_existent (a) FROM t1 WHERE b = 999999; +ERROR 42000: FUNCTION test.non_existent does not exist +DROP TABLE t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d9e593fd76f..99bc198259e 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -530,7 +530,7 @@ deallocate prepare stmt; # create table t1 (a varchar(20)); insert into t1 values ('foo'); ---error 1305 +--error ER_FUNC_INEXISTENT_NAME_COLLISION prepare stmt FROM 'SELECT char_length (a) FROM t1'; drop table t1; @@ -1239,7 +1239,7 @@ drop table t1; # create table t1 (a varchar(20)); insert into t1 values ('foo'); ---error 1305 +--error ER_FUNC_INEXISTENT_NAME_COLLISION prepare stmt FROM 'SELECT char_length (a) FROM t1'; drop table t1; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index c839b1e4374..8143fd56c6d 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2190,3 +2190,16 @@ delimiter ;| #drop procedure if exists bugNNNN| #--enable_warnings #create procedure bugNNNN... + +# +# Bug #38159: Function parsing problem generates misleading error message +# + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1), (2,2); +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT MAX (a) FROM t1 WHERE b = 999999; +SELECT AVG (a) FROM t1 WHERE b = 999999; +--error ER_SP_DOES_NOT_EXIST +SELECT non_existent (a) FROM t1 WHERE b = 999999; +DROP TABLE t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index 46e0f30d94e..6737b8cd1b0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5401,6 +5401,14 @@ Item_func_sp::func_name() const } +int my_missing_function_error(const LEX_STRING &token, const char *func_name) +{ + if (token.length && is_lex_native_function (&token)) + return my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name); + else + return my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name); +} + /** @brief Initialize the result field by creating a temporary dummy table @@ -5434,7 +5442,7 @@ Item_func_sp::init_result_field(THD *thd) if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name, &thd->sp_func_cache, TRUE))) { - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); + my_missing_function_error (m_name->m_name, m_name->m_qname.str); context->process_error(thd); DBUG_RETURN(TRUE); } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index c688ba88b7b..6113b18579f 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5649,3 +5649,6 @@ ER_XA_RBTIMEOUT XA106 eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" ER_XA_RBDEADLOCK XA102 eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected" + +ER_FUNC_INEXISTENT_NAME_COLLISION 42000 + eng "FUNCTION %s does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual" diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 830d1b7c36f..46718f74bd4 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -148,6 +148,7 @@ exit: if (orig_table_list->view) { if (thd->net.last_errno == ER_BAD_FIELD_ERROR || + thd->net.last_errno == ER_FUNC_INEXISTENT_NAME_COLLISION || thd->net.last_errno == ER_SP_DOES_NOT_EXIST) { thd->clear_error(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 436f41dd209..e7c87527d78 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -265,6 +265,22 @@ bool is_keyword(const char *name, uint len) return get_hash_symbol(name,len,0)!=0; } +/** + Check if name is a sql function + + @param name checked name + + @return is this a lex native function or not + @retval 0 name is a function + @retval 1 name isn't a function +*/ + +bool is_lex_native_function(const LEX_STRING *name) +{ + DBUG_ASSERT(name != NULL); + return (get_hash_symbol(name->str, (uint) name->length, 1) != 0); +} + /* make a copy of token before ptr and set yytoklen */ static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5c0367632e1..627003880d9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1390,3 +1390,5 @@ extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); extern char *skip_rear_comments(CHARSET_INFO *cs, char *begin, char *end); +extern bool is_lex_native_function(const LEX_STRING *name); +int my_missing_function_error(const LEX_STRING &token, const char *name); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 61020a3eed0..37d2658f46f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5968,8 +5968,7 @@ simple_expr: Reusing ER_SP_DOES_NOT_EXIST have a message consistent with the case when a default database exist, see below. */ - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), - "FUNCTION", $1.str); + my_missing_function_error ($1, $1.str); MYSQL_YYABORT; } diff --git a/sql/table.cc b/sql/table.cc index 55a9b50605d..3f34281f746 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2138,6 +2138,7 @@ void TABLE_LIST::hide_view_error(THD *thd) /* Hide "Unknown column" or "Unknown function" error */ if (thd->net.last_errno == ER_BAD_FIELD_ERROR || thd->net.last_errno == ER_SP_DOES_NOT_EXIST || + thd->net.last_errno == ER_FUNC_INEXISTENT_NAME_COLLISION || thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR || thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR || thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR || |