mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Fix for BUG#24923: Functions with ENUM issues.
The problem was that the RETURNS column in the mysql.proc was of CHAR(64). That was not enough for storing long-named datatypes. The fix is to change CHAR(64) to LONGBLOB, and to throw warnings at the time a stored routine is created if some data is truncated during writing into mysql.proc.
This commit is contained in:
parent
ee3e6d8171
commit
49a0f09bbf
8 changed files with 222 additions and 40 deletions
|
@ -6860,4 +6860,55 @@ DROP FUNCTION f2;
|
|||
DROP VIEW v1;
|
||||
DROP VIEW v2;
|
||||
|
||||
#
|
||||
# - Bug#24923: prepare.
|
||||
#
|
||||
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
|
||||
#
|
||||
# - Bug#24923: create required objects.
|
||||
#
|
||||
|
||||
CREATE FUNCTION f1(p INT)
|
||||
RETURNS ENUM ('Very_long_enum_element_identifier',
|
||||
'Another_very_long_enum_element_identifier')
|
||||
BEGIN
|
||||
CASE p
|
||||
WHEN 1 THEN
|
||||
RETURN 'Very_long_enum_element_identifier';
|
||||
ELSE
|
||||
RETURN 'Another_very_long_enum_element_identifier';
|
||||
END CASE;
|
||||
END|
|
||||
|
||||
#
|
||||
# - Bug#24923: check.
|
||||
#
|
||||
|
||||
SELECT f1(1);
|
||||
f1(1)
|
||||
Very_long_enum_element_identifier
|
||||
|
||||
SELECT f1(2);
|
||||
f1(2)
|
||||
Another_very_long_enum_element_identifier
|
||||
|
||||
SHOW CREATE FUNCTION f1;
|
||||
Function sql_mode Create Function character_set_client collation_connection Database Collation
|
||||
f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`(p INT) RETURNS enum('Very_long_enum_element_identifier','Another_very_long_enum_element_identifier') CHARSET latin1
|
||||
BEGIN
|
||||
CASE p
|
||||
WHEN 1 THEN
|
||||
RETURN 'Very_long_enum_element_identifier';
|
||||
ELSE
|
||||
RETURN 'Another_very_long_enum_element_identifier';
|
||||
END CASE;
|
||||
END latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
#
|
||||
# - Bug#24923: cleanup.
|
||||
#
|
||||
|
||||
DROP FUNCTION f1;
|
||||
|
||||
End of 5.1 tests
|
||||
|
|
|
@ -7986,4 +7986,74 @@ DROP VIEW v2;
|
|||
|
||||
###########################################################################
|
||||
|
||||
#
|
||||
# Bug#24923: Functions with ENUM issues.
|
||||
#
|
||||
|
||||
###########################################################################
|
||||
|
||||
--echo #
|
||||
--echo # - Bug#24923: prepare.
|
||||
--echo #
|
||||
|
||||
--echo
|
||||
|
||||
--disable_warnings
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
--enable_warnings
|
||||
|
||||
--echo
|
||||
|
||||
--echo #
|
||||
--echo # - Bug#24923: create required objects.
|
||||
--echo #
|
||||
|
||||
--echo
|
||||
|
||||
delimiter |;
|
||||
|
||||
CREATE FUNCTION f1(p INT)
|
||||
RETURNS ENUM ('Very_long_enum_element_identifier',
|
||||
'Another_very_long_enum_element_identifier')
|
||||
BEGIN
|
||||
CASE p
|
||||
WHEN 1 THEN
|
||||
RETURN 'Very_long_enum_element_identifier';
|
||||
ELSE
|
||||
RETURN 'Another_very_long_enum_element_identifier';
|
||||
END CASE;
|
||||
END|
|
||||
|
||||
delimiter ;|
|
||||
|
||||
--echo
|
||||
|
||||
--echo #
|
||||
--echo # - Bug#24923: check.
|
||||
--echo #
|
||||
|
||||
--echo
|
||||
|
||||
SELECT f1(1);
|
||||
|
||||
--echo
|
||||
|
||||
SELECT f1(2);
|
||||
|
||||
--echo
|
||||
|
||||
SHOW CREATE FUNCTION f1;
|
||||
|
||||
--echo #
|
||||
--echo # - Bug#24923: cleanup.
|
||||
--echo #
|
||||
|
||||
--echo
|
||||
|
||||
DROP FUNCTION f1;
|
||||
|
||||
--echo
|
||||
|
||||
###########################################################################
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
|
|
@ -60,7 +60,7 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign
|
|||
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
|
||||
CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL,
|
|||
'MODIFIES_SQL_DATA'
|
||||
) DEFAULT 'CONTAINS_SQL' NOT NULL,
|
||||
MODIFY body longblob NOT NULL,
|
||||
MODIFY returns longblob NOT NULL,
|
||||
MODIFY sql_mode
|
||||
set('REAL_AS_FLOAT',
|
||||
'PIPES_AS_CONCAT',
|
||||
|
|
|
@ -6109,3 +6109,6 @@ ER_EVENT_INVALID_CREATION_CTX
|
|||
|
||||
ER_TRG_CANT_OPEN_TABLE
|
||||
eng "Cannot open table for trigger `%-.64s`.`%-.64s`"
|
||||
|
||||
ER_CANT_CREATE_SROUTINE
|
||||
eng "Cannot create stored routine `%-.64s`. Check warnings"
|
||||
|
|
131
sql/sp.cc
131
sql/sp.cc
|
@ -682,6 +682,10 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
|
|||
|
||||
CHARSET_INFO *db_cs= get_default_db_collation(thd, sp->m_db.str);
|
||||
|
||||
enum_check_fields saved_count_cuted_fields;
|
||||
|
||||
bool store_failed= FALSE;
|
||||
|
||||
DBUG_ENTER("sp_create_routine");
|
||||
DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length,
|
||||
sp->m_name.str));
|
||||
|
@ -696,6 +700,9 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
|
|||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
saved_count_cuted_fields= thd->count_cuted_fields;
|
||||
thd->count_cuted_fields= CHECK_FIELD_WARN;
|
||||
|
||||
if (!(table= open_proc_table_for_update(thd)))
|
||||
ret= SP_OPEN_TABLE_FAILED;
|
||||
else
|
||||
|
@ -725,43 +732,77 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
|
|||
ret= SP_BODY_TOO_LONG;
|
||||
goto done;
|
||||
}
|
||||
table->field[MYSQL_PROC_FIELD_DB]->
|
||||
store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
||||
table->field[MYSQL_PROC_FIELD_NAME]->
|
||||
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
||||
table->field[MYSQL_PROC_MYSQL_TYPE]->
|
||||
store((longlong)type, TRUE);
|
||||
table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
|
||||
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
||||
|
||||
store_failed=
|
||||
table->field[MYSQL_PROC_FIELD_DB]->
|
||||
store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_NAME]->
|
||||
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_MYSQL_TYPE]->
|
||||
store((longlong)type, TRUE);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
|
||||
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
||||
|
||||
if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS)
|
||||
table->field[MYSQL_PROC_FIELD_ACCESS]->
|
||||
store((longlong)sp->m_chistics->daccess, TRUE);
|
||||
table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
|
||||
store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE);
|
||||
{
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_ACCESS]->
|
||||
store((longlong)sp->m_chistics->daccess, TRUE);
|
||||
}
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
|
||||
store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE);
|
||||
|
||||
if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID)
|
||||
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
|
||||
store((longlong)sp->m_chistics->suid, TRUE);
|
||||
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
|
||||
store(sp->m_params.str, sp->m_params.length, system_charset_info);
|
||||
{
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
|
||||
store((longlong)sp->m_chistics->suid, TRUE);
|
||||
}
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
|
||||
store(sp->m_params.str, sp->m_params.length, system_charset_info);
|
||||
|
||||
if (sp->m_type == TYPE_ENUM_FUNCTION)
|
||||
{
|
||||
String retstr(64);
|
||||
sp_returns_type(thd, retstr, sp);
|
||||
table->field[MYSQL_PROC_FIELD_RETURNS]->
|
||||
store(retstr.ptr(), retstr.length(), system_charset_info);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_RETURNS]->
|
||||
store(retstr.ptr(), retstr.length(), system_charset_info);
|
||||
}
|
||||
table->field[MYSQL_PROC_FIELD_BODY]->
|
||||
store(sp->m_body.str, sp->m_body.length, system_charset_info);
|
||||
table->field[MYSQL_PROC_FIELD_DEFINER]->
|
||||
store(definer, (uint)strlen(definer), system_charset_info);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_BODY]->
|
||||
store(sp->m_body.str, sp->m_body.length, system_charset_info);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_DEFINER]->
|
||||
store(definer, (uint)strlen(definer), system_charset_info);
|
||||
|
||||
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
|
||||
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
|
||||
table->field[MYSQL_PROC_FIELD_SQL_MODE]->
|
||||
store((longlong)thd->variables.sql_mode, TRUE);
|
||||
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_SQL_MODE]->
|
||||
store((longlong)thd->variables.sql_mode, TRUE);
|
||||
|
||||
if (sp->m_chistics->comment.str)
|
||||
table->field[MYSQL_PROC_FIELD_COMMENT]->
|
||||
store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
|
||||
system_charset_info);
|
||||
{
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_COMMENT]->
|
||||
store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
|
||||
system_charset_info);
|
||||
}
|
||||
|
||||
if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
|
||||
!trust_function_creators && mysql_bin_log.is_open())
|
||||
|
@ -794,24 +835,34 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
|
|||
}
|
||||
|
||||
table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->set_notnull();
|
||||
table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->store(
|
||||
thd->charset()->csname,
|
||||
strlen(thd->charset()->csname),
|
||||
system_charset_info);
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->store(
|
||||
thd->charset()->csname,
|
||||
strlen(thd->charset()->csname),
|
||||
system_charset_info);
|
||||
|
||||
table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->set_notnull();
|
||||
table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->store(
|
||||
thd->variables.collation_connection->name,
|
||||
strlen(thd->variables.collation_connection->name),
|
||||
system_charset_info);
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->store(
|
||||
thd->variables.collation_connection->name,
|
||||
strlen(thd->variables.collation_connection->name),
|
||||
system_charset_info);
|
||||
|
||||
table->field[MYSQL_PROC_FIELD_DB_COLLATION]->set_notnull();
|
||||
table->field[MYSQL_PROC_FIELD_DB_COLLATION]->store(
|
||||
db_cs->name, strlen(db_cs->name), system_charset_info);
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_DB_COLLATION]->store(
|
||||
db_cs->name, strlen(db_cs->name), system_charset_info);
|
||||
|
||||
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull();
|
||||
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store(
|
||||
sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info);
|
||||
store_failed= store_failed ||
|
||||
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store(
|
||||
sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info);
|
||||
|
||||
if (store_failed)
|
||||
{
|
||||
ret= SP_FLD_STORE_FAILED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret= SP_OK;
|
||||
if (table->file->ha_write_row(table->record[0]))
|
||||
|
@ -842,6 +893,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
|
|||
}
|
||||
|
||||
done:
|
||||
thd->count_cuted_fields= saved_count_cuted_fields;
|
||||
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
|
1
sql/sp.h
1
sql/sp.h
|
@ -29,6 +29,7 @@
|
|||
#define SP_NO_DB_ERROR -8
|
||||
#define SP_BAD_IDENTIFIER -9
|
||||
#define SP_BODY_TOO_LONG -10
|
||||
#define SP_FLD_STORE_FAILED -11
|
||||
|
||||
/* Drop all routines in database 'db' */
|
||||
int
|
||||
|
|
|
@ -3812,6 +3812,9 @@ end_with_restore_list:
|
|||
case SP_BODY_TOO_LONG:
|
||||
my_error(ER_TOO_LONG_BODY, MYF(0), name);
|
||||
break;
|
||||
case SP_FLD_STORE_FAILED:
|
||||
my_error(ER_CANT_CREATE_SROUTINE, MYF(0), name);
|
||||
break;
|
||||
default:
|
||||
my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue