mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Bug #38159: Function parsing problem generates misleading error message
Added a more detailed error message on calling an ambiguous missing function. mysql-test/r/ps.result: Bug #38159: fixed existing tests mysql-test/r/sp-error.result: Bug #38159: test case mysql-test/t/ps.test: Bug #38159: fixed existing tests mysql-test/t/sp-error.test: Bug #38159: test case sql/item_func.cc: Bug #38159: generate more detailed error message sql/share/errmsg.txt: Bug #38159: add a more detailed error message sql/sql_derived.cc: Bug #38159: treat the detailed error message the same way as the generic one sql/sql_lex.cc: Bug #38159: - detect if the token is ambiguous and print the appropriate error. - backport is_lex_native_function() from 5.1 sql/sql_lex.h: Bug #38159: detect if the token is ambiguous and print the appropriate error. sql/sql_yacc.yy: Bug #38159: generate more detailed error message sql/table.cc: Bug #38159: treat the detailed error message the same way as the generic one
This commit is contained in:
parent
f54beb2dcc
commit
80730df7d6
11 changed files with 60 additions and 7 deletions
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
Loading…
Add table
Reference in a new issue