mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
store/restore sql_mode which was in force during ctrigger creation (BUG#5891)
other sql_mode fixes mysql-test/r/information_schema.result: changes in information schema mysql-test/r/trigger.result: storing and restoring sql modes for triggers mysql-test/t/trigger.test: storing and restoring parsing modes for triggers sql/mysqld.cc: add length of mode names sql/parse_file.cc: new type of list (ulonglong) sql/parse_file.h: new type of list (ulonglong) sql/set_var.cc: mode output made as static method sql/set_var.h: mode output made as static method sql/sp_head.cc: added sql_mode storing/restoring during SP execution optimised sql_mode printing sql/sp_head.h: comment fixed according this changes sql/sql_show.cc: added sql_mode field sql/sql_trigger.cc: store/restore sql_mode which was in force during ctrigger creation sql/sql_trigger.h: store/restore sql_mode which was in force during ctrigger creation sql/sql_view.cc: fixed sql_mode
This commit is contained in:
@ -32,8 +32,12 @@ const char * const triggers_file_ext= ".TRG";
|
||||
*/
|
||||
static File_option triggers_file_parameters[]=
|
||||
{
|
||||
{{(char*)"triggers", 8}, offsetof(class Table_triggers_list, definitions_list),
|
||||
FILE_OPTIONS_STRLIST},
|
||||
{{(char*)"triggers", 8},
|
||||
offsetof(class Table_triggers_list, definitions_list),
|
||||
FILE_OPTIONS_STRLIST},
|
||||
{{(char*)"sql_modes", 13},
|
||||
offsetof(class Table_triggers_list, definition_modes_list),
|
||||
FILE_OPTIONS_ULLLIST},
|
||||
{{0, 0}, 0, FILE_OPTIONS_STRING}
|
||||
};
|
||||
|
||||
@ -127,12 +131,13 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/*
|
||||
We do not allow creation of triggers on views or temporary tables.
|
||||
We have to do this check here and not in
|
||||
Table_triggers_list::create_trigger() because we want to avoid messing
|
||||
with table cash for views and temporary tables.
|
||||
We do not allow creation of triggers on temporary tables. We also don't
|
||||
allow creation of triggers on views but fulfilment of this restriction
|
||||
is guaranteed by open_ltable(). It is better to have this check here
|
||||
than do it in Table_triggers_list::create_trigger() and mess with table
|
||||
cache.
|
||||
*/
|
||||
if (tables->view || table->s->tmp_table != NO_TMP_TABLE)
|
||||
if (table->s->tmp_table != NO_TMP_TABLE)
|
||||
{
|
||||
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -221,6 +226,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
|
||||
trigname_path[FN_REFLEN];
|
||||
LEX_STRING dir, file, trigname_file;
|
||||
LEX_STRING *trg_def, *name;
|
||||
ulonglong *trg_sql_mode;
|
||||
Item_trigger_field *trg_field;
|
||||
struct st_trigname trigname;
|
||||
|
||||
@ -307,11 +313,15 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
|
||||
*/
|
||||
if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root,
|
||||
sizeof(LEX_STRING))) ||
|
||||
definitions_list.push_back(trg_def, &table->mem_root))
|
||||
definitions_list.push_back(trg_def, &table->mem_root) ||
|
||||
!(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root,
|
||||
sizeof(ulonglong))) ||
|
||||
definition_modes_list.push_back(trg_sql_mode, &table->mem_root))
|
||||
goto err_with_cleanup;
|
||||
|
||||
trg_def->str= thd->query;
|
||||
trg_def->length= thd->query_length;
|
||||
*trg_sql_mode= thd->variables.sql_mode;
|
||||
|
||||
if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
|
||||
(gptr)this, triggers_file_parameters, 3))
|
||||
@ -390,11 +400,13 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
|
||||
LEX_STRING *name;
|
||||
List_iterator_fast<LEX_STRING> it_name(names_list);
|
||||
List_iterator<LEX_STRING> it_def(definitions_list);
|
||||
List_iterator<ulonglong> it_mod(definition_modes_list);
|
||||
char path[FN_REFLEN];
|
||||
|
||||
while ((name= it_name++))
|
||||
{
|
||||
it_def++;
|
||||
it_mod++;
|
||||
|
||||
if (my_strcasecmp(system_charset_info, lex->spname->m_name.str,
|
||||
name->str) == 0)
|
||||
@ -404,6 +416,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
|
||||
clean trigger removing since table will be reopened anyway.
|
||||
*/
|
||||
it_def.remove();
|
||||
it_mod.remove();
|
||||
|
||||
if (definitions_list.is_empty())
|
||||
{
|
||||
@ -549,10 +562,48 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
||||
if (!triggers)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/*
|
||||
We don't have sql_modes in old versions of .TRG file, so we should
|
||||
initialize list for safety.
|
||||
*/
|
||||
triggers->definition_modes_list.empty();
|
||||
|
||||
if (parser->parse((gptr)triggers, &table->mem_root,
|
||||
triggers_file_parameters, 1))
|
||||
triggers_file_parameters, 2))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
|
||||
LEX_STRING *trg_create_str, *trg_name_str;
|
||||
ulonglong *trg_sql_mode;
|
||||
|
||||
if (triggers->definition_modes_list.is_empty() &&
|
||||
!triggers->definitions_list.is_empty())
|
||||
{
|
||||
/*
|
||||
It is old file format => we should fill list of sql_modes.
|
||||
|
||||
We use one mode (current) for all triggers, because we have not
|
||||
information about mode in old format.
|
||||
*/
|
||||
if (!(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root,
|
||||
sizeof(ulonglong))))
|
||||
{
|
||||
DBUG_RETURN(1); // EOM
|
||||
}
|
||||
*trg_sql_mode= global_system_variables.sql_mode;
|
||||
while ((trg_create_str= it++))
|
||||
{
|
||||
if (triggers->definition_modes_list.push_back(trg_sql_mode,
|
||||
&table->mem_root))
|
||||
{
|
||||
DBUG_RETURN(1); // EOM
|
||||
}
|
||||
}
|
||||
it.rewind();
|
||||
}
|
||||
|
||||
DBUG_ASSERT(triggers->definition_modes_list.elements ==
|
||||
triggers->definitions_list.elements);
|
||||
table->triggers= triggers;
|
||||
|
||||
/*
|
||||
@ -574,15 +625,17 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
||||
if (!names_only && triggers->prepare_record1_accessors(table))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
|
||||
LEX_STRING *trg_create_str, *trg_name_str;
|
||||
char *trg_name_buff;
|
||||
List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
|
||||
LEX *old_lex= thd->lex, lex;
|
||||
ulong save_sql_mode= thd->variables.sql_mode;
|
||||
|
||||
thd->lex= &lex;
|
||||
|
||||
while ((trg_create_str= it++))
|
||||
{
|
||||
trg_sql_mode= itm++;
|
||||
thd->variables.sql_mode= (ulong)*trg_sql_mode;
|
||||
lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
|
||||
|
||||
if (yyparse((void *)thd) || thd->is_fatal_error)
|
||||
@ -595,9 +648,11 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
||||
goto err_with_lex_cleanup;
|
||||
}
|
||||
|
||||
lex.sphead->m_sql_mode= *trg_sql_mode;
|
||||
triggers->bodies[lex.trg_chistics.event]
|
||||
[lex.trg_chistics.action_time]= lex.sphead;
|
||||
if (triggers->names_list.push_back(&lex.sphead->m_name, &table->mem_root))
|
||||
if (triggers->names_list.push_back(&lex.sphead->m_name,
|
||||
&table->mem_root))
|
||||
goto err_with_lex_cleanup;
|
||||
|
||||
if (names_only)
|
||||
@ -611,8 +666,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
||||
in old/new versions of row in trigger to Field objects in table being
|
||||
opened.
|
||||
|
||||
We ignore errors here, because if even something is wrong we still will
|
||||
be willing to open table to perform some operations (e.g. SELECT)...
|
||||
We ignore errors here, because if even something is wrong we still
|
||||
will be willing to open table to perform some operations (e.g.
|
||||
SELECT)...
|
||||
Anyway some things can be checked only during trigger execution.
|
||||
*/
|
||||
for (Item_trigger_field *trg_field=
|
||||
@ -624,6 +680,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
||||
lex_end(&lex);
|
||||
}
|
||||
thd->lex= old_lex;
|
||||
thd->variables.sql_mode= save_sql_mode;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
|
||||
@ -631,6 +688,7 @@ err_with_lex_cleanup:
|
||||
// QQ: anything else ?
|
||||
lex_end(&lex);
|
||||
thd->lex= old_lex;
|
||||
thd->variables.sql_mode= save_sql_mode;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
@ -657,6 +715,7 @@ err_with_lex_cleanup:
|
||||
time_type - trigger action time
|
||||
name - returns name of trigger
|
||||
stmt - returns statement of trigger
|
||||
sql_mode - returns sql_mode of trigger
|
||||
|
||||
RETURN VALUE
|
||||
False - success
|
||||
@ -666,7 +725,8 @@ err_with_lex_cleanup:
|
||||
bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
||||
trg_action_time_type time_type,
|
||||
LEX_STRING *trigger_name,
|
||||
LEX_STRING *trigger_stmt)
|
||||
LEX_STRING *trigger_stmt,
|
||||
ulong *sql_mode)
|
||||
{
|
||||
sp_head *body;
|
||||
DBUG_ENTER("get_trigger_info");
|
||||
@ -674,6 +734,7 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
||||
{
|
||||
*trigger_name= body->m_name;
|
||||
*trigger_stmt= body->m_body;
|
||||
*sql_mode= body->m_sql_mode;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
|
Reference in New Issue
Block a user