Commit bbe29a00 authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #38159: Function parsing problem generates misleading error message

      
Added a more detailed error message on calling an ambiguous missing function.
parent cb07978d
...@@ -502,7 +502,7 @@ deallocate prepare stmt; ...@@ -502,7 +502,7 @@ deallocate prepare stmt;
create table t1 (a varchar(20)); create table t1 (a varchar(20));
insert into t1 values ('foo'); insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1'; 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; drop table t1;
prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0"; prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0";
execute stmt; execute stmt;
...@@ -1147,7 +1147,7 @@ End of 4.1 tests. ...@@ -1147,7 +1147,7 @@ End of 4.1 tests.
create table t1 (a varchar(20)); create table t1 (a varchar(20));
insert into t1 values ('foo'); insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1'; 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; drop table t1;
create table t1 (a char(3) not null, b char(3) not null, create table t1 (a char(3) not null, b char(3) not null,
c char(3) not null, primary key (a, b, c)); c char(3) not null, primary key (a, b, c));
......
...@@ -1520,3 +1520,13 @@ CALL p1((SELECT * FROM t1))| ...@@ -1520,3 +1520,13 @@ CALL p1((SELECT * FROM t1))|
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
DROP PROCEDURE IF EXISTS p1| DROP PROCEDURE IF EXISTS p1|
DROP TABLE t1| 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;
...@@ -530,7 +530,7 @@ deallocate prepare stmt; ...@@ -530,7 +530,7 @@ deallocate prepare stmt;
# #
create table t1 (a varchar(20)); create table t1 (a varchar(20));
insert into t1 values ('foo'); insert into t1 values ('foo');
--error 1305 --error ER_FUNC_INEXISTENT_NAME_COLLISION
prepare stmt FROM 'SELECT char_length (a) FROM t1'; prepare stmt FROM 'SELECT char_length (a) FROM t1';
drop table t1; drop table t1;
...@@ -1239,7 +1239,7 @@ drop table t1; ...@@ -1239,7 +1239,7 @@ drop table t1;
# #
create table t1 (a varchar(20)); create table t1 (a varchar(20));
insert into t1 values ('foo'); insert into t1 values ('foo');
--error 1305 --error ER_FUNC_INEXISTENT_NAME_COLLISION
prepare stmt FROM 'SELECT char_length (a) FROM t1'; prepare stmt FROM 'SELECT char_length (a) FROM t1';
drop table t1; drop table t1;
......
...@@ -2190,3 +2190,16 @@ delimiter ;| ...@@ -2190,3 +2190,16 @@ delimiter ;|
#drop procedure if exists bugNNNN| #drop procedure if exists bugNNNN|
#--enable_warnings #--enable_warnings
#create procedure bugNNNN... #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;
...@@ -5401,6 +5401,14 @@ Item_func_sp::func_name() const ...@@ -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 @brief Initialize the result field by creating a temporary dummy table
...@@ -5434,7 +5442,7 @@ Item_func_sp::init_result_field(THD *thd) ...@@ -5434,7 +5442,7 @@ Item_func_sp::init_result_field(THD *thd)
if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name, if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
&thd->sp_func_cache, TRUE))) &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); context->process_error(thd);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
...@@ -5649,3 +5649,6 @@ ER_XA_RBTIMEOUT XA106 ...@@ -5649,3 +5649,6 @@ ER_XA_RBTIMEOUT XA106
eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long"
ER_XA_RBDEADLOCK XA102 ER_XA_RBDEADLOCK XA102
eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected" 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"
...@@ -148,6 +148,7 @@ exit: ...@@ -148,6 +148,7 @@ exit:
if (orig_table_list->view) if (orig_table_list->view)
{ {
if (thd->net.last_errno == ER_BAD_FIELD_ERROR || 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->net.last_errno == ER_SP_DOES_NOT_EXIST)
{ {
thd->clear_error(); thd->clear_error();
......
...@@ -265,6 +265,22 @@ bool is_keyword(const char *name, uint len) ...@@ -265,6 +265,22 @@ bool is_keyword(const char *name, uint len)
return get_hash_symbol(name,len,0)!=0; 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 */ /* make a copy of token before ptr and set yytoklen */
static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length) static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
......
...@@ -1390,3 +1390,5 @@ extern void lex_end(LEX *lex); ...@@ -1390,3 +1390,5 @@ extern void lex_end(LEX *lex);
extern int MYSQLlex(void *arg, void *yythd); extern int MYSQLlex(void *arg, void *yythd);
extern char *skip_rear_comments(CHARSET_INFO *cs, char *begin, char *end); 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);
...@@ -5968,8 +5968,7 @@ simple_expr: ...@@ -5968,8 +5968,7 @@ simple_expr:
Reusing ER_SP_DOES_NOT_EXIST have a message consistent with Reusing ER_SP_DOES_NOT_EXIST have a message consistent with
the case when a default database exist, see below. the case when a default database exist, see below.
*/ */
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), my_missing_function_error ($1, $1.str);
"FUNCTION", $1.str);
MYSQL_YYABORT; MYSQL_YYABORT;
} }
......
...@@ -2138,6 +2138,7 @@ void TABLE_LIST::hide_view_error(THD *thd) ...@@ -2138,6 +2138,7 @@ void TABLE_LIST::hide_view_error(THD *thd)
/* Hide "Unknown column" or "Unknown function" error */ /* Hide "Unknown column" or "Unknown function" error */
if (thd->net.last_errno == ER_BAD_FIELD_ERROR || if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST || 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_PROCACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR || thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR || thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR ||
......
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