store/restore sql_mode which was in force during ctrigger creation (BUG#5891)
other sql_mode fixes
This commit is contained in:
parent
c1c504abf4
commit
b220fc47ef
@ -713,6 +713,7 @@ information_schema ROUTINES SQL_MODE
|
|||||||
information_schema VIEWS VIEW_DEFINITION
|
information_schema VIEWS VIEW_DEFINITION
|
||||||
information_schema TRIGGERS ACTION_CONDITION
|
information_schema TRIGGERS ACTION_CONDITION
|
||||||
information_schema TRIGGERS ACTION_STATEMENT
|
information_schema TRIGGERS ACTION_STATEMENT
|
||||||
|
information_schema TRIGGERS SQL_MODE
|
||||||
select table_name, column_name, data_type from information_schema.columns
|
select table_name, column_name, data_type from information_schema.columns
|
||||||
where data_type = 'datetime';
|
where data_type = 'datetime';
|
||||||
table_name column_name data_type
|
table_name column_name data_type
|
||||||
@ -790,45 +791,45 @@ set @fired:= "Yes";
|
|||||||
end if;
|
end if;
|
||||||
end|
|
end|
|
||||||
show triggers;
|
show triggers;
|
||||||
Trigger Event Table Statement Timing Created
|
Trigger Event Table Statement Timing Created sql_mode
|
||||||
trg1 INSERT t1
|
trg1 INSERT t1
|
||||||
begin
|
begin
|
||||||
if new.j > 10 then
|
if new.j > 10 then
|
||||||
set new.j := 10;
|
set new.j := 10;
|
||||||
end if;
|
end if;
|
||||||
end BEFORE NULL
|
end BEFORE NULL
|
||||||
trg2 UPDATE t1
|
trg2 UPDATE t1
|
||||||
begin
|
begin
|
||||||
if old.i % 2 = 0 then
|
if old.i % 2 = 0 then
|
||||||
set new.j := -1;
|
set new.j := -1;
|
||||||
end if;
|
end if;
|
||||||
end BEFORE NULL
|
end BEFORE NULL
|
||||||
trg3 UPDATE t1
|
trg3 UPDATE t1
|
||||||
begin
|
begin
|
||||||
if new.j = -1 then
|
if new.j = -1 then
|
||||||
set @fired:= "Yes";
|
set @fired:= "Yes";
|
||||||
end if;
|
end if;
|
||||||
end AFTER NULL
|
end AFTER NULL
|
||||||
select * from information_schema.triggers;
|
select * from information_schema.triggers;
|
||||||
TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED
|
TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE
|
||||||
NULL test trg1 INSERT NULL test t1 0 NULL
|
NULL test trg1 INSERT NULL test t1 0 NULL
|
||||||
begin
|
begin
|
||||||
if new.j > 10 then
|
if new.j > 10 then
|
||||||
set new.j := 10;
|
set new.j := 10;
|
||||||
end if;
|
end if;
|
||||||
end ROW BEFORE NULL NULL OLD NEW NULL
|
end ROW BEFORE NULL NULL OLD NEW NULL
|
||||||
NULL test trg2 UPDATE NULL test t1 0 NULL
|
NULL test trg2 UPDATE NULL test t1 0 NULL
|
||||||
begin
|
begin
|
||||||
if old.i % 2 = 0 then
|
if old.i % 2 = 0 then
|
||||||
set new.j := -1;
|
set new.j := -1;
|
||||||
end if;
|
end if;
|
||||||
end ROW BEFORE NULL NULL OLD NEW NULL
|
end ROW BEFORE NULL NULL OLD NEW NULL
|
||||||
NULL test trg3 UPDATE NULL test t1 0 NULL
|
NULL test trg3 UPDATE NULL test t1 0 NULL
|
||||||
begin
|
begin
|
||||||
if new.j = -1 then
|
if new.j = -1 then
|
||||||
set @fired:= "Yes";
|
set @fired:= "Yes";
|
||||||
end if;
|
end if;
|
||||||
end ROW AFTER NULL NULL OLD NEW NULL
|
end ROW AFTER NULL NULL OLD NEW NULL
|
||||||
drop trigger trg1;
|
drop trigger trg1;
|
||||||
drop trigger trg2;
|
drop trigger trg2;
|
||||||
drop trigger trg3;
|
drop trigger trg3;
|
||||||
|
@ -595,3 +595,50 @@ update t1 set col2 = 4;
|
|||||||
ERROR 42000: FUNCTION test.bug5893 does not exist
|
ERROR 42000: FUNCTION test.bug5893 does not exist
|
||||||
drop trigger t1_bu;
|
drop trigger t1_bu;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
set sql_mode='ansi';
|
||||||
|
create table t1 ("t1 column" int);
|
||||||
|
create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5;
|
||||||
|
set sql_mode=default;
|
||||||
|
insert into t1 values (0);
|
||||||
|
create trigger t1_af after insert on t1 for each row set @a=10;
|
||||||
|
insert into t1 values (0);
|
||||||
|
select * from t1;
|
||||||
|
t1 column
|
||||||
|
5
|
||||||
|
5
|
||||||
|
select @a;
|
||||||
|
@a
|
||||||
|
10
|
||||||
|
show triggers;
|
||||||
|
Trigger Event Table Statement Timing Created sql_mode
|
||||||
|
t1_bi INSERT t1 set new."t1 column" = 5 BEFORE # REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
|
||||||
|
t1_af INSERT t1 set @a=10 AFTER #
|
||||||
|
select * from information_schema.triggers;
|
||||||
|
TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE
|
||||||
|
NULL test t1_bi INSERT NULL test t1 0 NULL set new."t1 column" = 5 ROW BEFORE NULL NULL OLD NEW # REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
|
||||||
|
NULL test t1_af INSERT NULL test t1 0 NULL set @a=10 ROW AFTER NULL NULL OLD NEW #
|
||||||
|
drop table t1;
|
||||||
|
set sql_mode="traditional";
|
||||||
|
create table t1 (a date);
|
||||||
|
insert into t1 values ('2004-01-00');
|
||||||
|
ERROR 22007: Incorrect date value: '2004-01-00' for column 'a' at row 1
|
||||||
|
set sql_mode="";
|
||||||
|
create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00';
|
||||||
|
set sql_mode="traditional";
|
||||||
|
insert into t1 values ('2004-01-01');
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
2004-01-00
|
||||||
|
set sql_mode=default;
|
||||||
|
show create table t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` date default NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
show triggers;
|
||||||
|
Trigger Event Table Statement Timing Created sql_mode
|
||||||
|
t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE #
|
||||||
|
select * from information_schema.triggers;
|
||||||
|
TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE
|
||||||
|
NULL test t1_bi INSERT NULL test t1 0 NULL set new.a = '2004-01-00' ROW BEFORE NULL NULL OLD NEW #
|
||||||
|
drop table t1;
|
||||||
|
@ -610,3 +610,39 @@ update t1 set col2 = 4;
|
|||||||
# This should not crash server too.
|
# This should not crash server too.
|
||||||
drop trigger t1_bu;
|
drop trigger t1_bu;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# storing and restoring parsing modes for triggers (BUG#5891)
|
||||||
|
#
|
||||||
|
set sql_mode='ansi';
|
||||||
|
create table t1 ("t1 column" int);
|
||||||
|
create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5;
|
||||||
|
set sql_mode=default;
|
||||||
|
insert into t1 values (0);
|
||||||
|
# create trigger with different sql_mode
|
||||||
|
create trigger t1_af after insert on t1 for each row set @a=10;
|
||||||
|
insert into t1 values (0);
|
||||||
|
select * from t1;
|
||||||
|
select @a;
|
||||||
|
--replace_column 6 #
|
||||||
|
show triggers;
|
||||||
|
--replace_column 17 #
|
||||||
|
select * from information_schema.triggers;
|
||||||
|
drop table t1;
|
||||||
|
# check that rigger preserve sql_mode during execution
|
||||||
|
set sql_mode="traditional";
|
||||||
|
create table t1 (a date);
|
||||||
|
-- error 1292
|
||||||
|
insert into t1 values ('2004-01-00');
|
||||||
|
set sql_mode="";
|
||||||
|
create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00';
|
||||||
|
set sql_mode="traditional";
|
||||||
|
insert into t1 values ('2004-01-01');
|
||||||
|
select * from t1;
|
||||||
|
set sql_mode=default;
|
||||||
|
show create table t1;
|
||||||
|
--replace_column 6 #
|
||||||
|
show triggers;
|
||||||
|
--replace_column 17 #
|
||||||
|
select * from information_schema.triggers;
|
||||||
|
drop table t1;
|
||||||
|
@ -220,21 +220,58 @@ extern "C" int gethostname(char *name, int namelen);
|
|||||||
/* Constants */
|
/* Constants */
|
||||||
|
|
||||||
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
|
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
|
||||||
static const char *sql_mode_names[] =
|
static const char *sql_mode_names[]=
|
||||||
{
|
{
|
||||||
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
|
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
|
||||||
"?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
|
"?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
|
||||||
"NO_DIR_IN_CREATE",
|
"NO_DIR_IN_CREATE",
|
||||||
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
|
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
|
||||||
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
|
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
|
||||||
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES",
|
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
|
||||||
"NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO",
|
"STRICT_ALL_TABLES",
|
||||||
|
"NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES",
|
||||||
|
"ERROR_FOR_DIVISION_BY_ZERO",
|
||||||
"TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
|
"TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
|
||||||
"NO_ENGINE_SUBSTITUTION",
|
"NO_ENGINE_SUBSTITUTION",
|
||||||
NullS
|
NullS
|
||||||
};
|
};
|
||||||
|
static const unsigned int sql_mode_names_len[]=
|
||||||
|
{
|
||||||
|
/*REAL_AS_FLOAT*/ 13,
|
||||||
|
/*PIPES_AS_CONCAT*/ 15,
|
||||||
|
/*ANSI_QUOTES*/ 11,
|
||||||
|
/*IGNORE_SPACE*/ 12,
|
||||||
|
/*?*/ 1,
|
||||||
|
/*ONLY_FULL_GROUP_BY*/ 18,
|
||||||
|
/*NO_UNSIGNED_SUBTRACTION*/ 23,
|
||||||
|
/*NO_DIR_IN_CREATE*/ 16,
|
||||||
|
/*POSTGRESQL*/ 10,
|
||||||
|
/*ORACLE*/ 6,
|
||||||
|
/*MSSQL*/ 5,
|
||||||
|
/*DB2*/ 3,
|
||||||
|
/*MAXDB*/ 5,
|
||||||
|
/*NO_KEY_OPTIONS*/ 14,
|
||||||
|
/*NO_TABLE_OPTIONS*/ 16,
|
||||||
|
/*NO_FIELD_OPTIONS*/ 16,
|
||||||
|
/*MYSQL323*/ 8,
|
||||||
|
/*MYSQL40*/ 7,
|
||||||
|
/*ANSI*/ 4,
|
||||||
|
/*NO_AUTO_VALUE_ON_ZERO*/ 21,
|
||||||
|
/*NO_BACKSLASH_ESCAPES*/ 20,
|
||||||
|
/*STRICT_TRANS_TABLES*/ 19,
|
||||||
|
/*STRICT_ALL_TABLES*/ 17,
|
||||||
|
/*NO_ZERO_IN_DATE*/ 15,
|
||||||
|
/*NO_ZERO_DATE*/ 12,
|
||||||
|
/*ALLOW_INVALID_DATES*/ 19,
|
||||||
|
/*ERROR_FOR_DIVISION_BY_ZERO*/ 26,
|
||||||
|
/*TRADITIONAL*/ 11,
|
||||||
|
/*NO_AUTO_CREATE_USER*/ 19,
|
||||||
|
/*HIGH_NOT_PRECEDENCE*/ 19,
|
||||||
|
/*NO_ENGINE_SUBSTITUTION*/ 22
|
||||||
|
};
|
||||||
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
|
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
|
||||||
sql_mode_names, NULL };
|
sql_mode_names,
|
||||||
|
(unsigned int *)sql_mode_names_len };
|
||||||
static const char *tc_heuristic_recover_names[]=
|
static const char *tc_heuristic_recover_names[]=
|
||||||
{
|
{
|
||||||
"COMMIT", "ROLLBACK", NullS
|
"COMMIT", "ROLLBACK", NullS
|
||||||
|
@ -166,6 +166,25 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FILE_OPTIONS_ULLLIST:
|
||||||
|
{
|
||||||
|
List_iterator_fast<ulonglong> it(*((List<ulonglong>*)
|
||||||
|
(base + parameter->offset)));
|
||||||
|
bool first= 1;
|
||||||
|
ulonglong *val;
|
||||||
|
while ((val= it++))
|
||||||
|
{
|
||||||
|
num.set(*val, &my_charset_bin);
|
||||||
|
// We need ' ' after string to detect list continuation
|
||||||
|
if ((!first && my_b_append(file, (const byte *)" ", 1)) ||
|
||||||
|
my_b_append(file, (const byte *)num.ptr(), num.length()))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
first= 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0); // never should happened
|
DBUG_ASSERT(0); // never should happened
|
||||||
}
|
}
|
||||||
@ -615,6 +634,8 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
|
|||||||
char *eol;
|
char *eol;
|
||||||
LEX_STRING *str;
|
LEX_STRING *str;
|
||||||
List<LEX_STRING> *list;
|
List<LEX_STRING> *list;
|
||||||
|
ulonglong *num;
|
||||||
|
List<ulonglong> *nlist;
|
||||||
DBUG_ENTER("File_parser::parse");
|
DBUG_ENTER("File_parser::parse");
|
||||||
|
|
||||||
while (ptr < end && found < required)
|
while (ptr < end && found < required)
|
||||||
@ -719,7 +740,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
|
|||||||
case FILE_OPTIONS_STRLIST:
|
case FILE_OPTIONS_STRLIST:
|
||||||
{
|
{
|
||||||
list= (List<LEX_STRING>*)(base + parameter->offset);
|
list= (List<LEX_STRING>*)(base + parameter->offset);
|
||||||
|
|
||||||
list->empty();
|
list->empty();
|
||||||
// list parsing
|
// list parsing
|
||||||
while (ptr < end)
|
while (ptr < end)
|
||||||
@ -741,17 +762,56 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
|
|||||||
goto list_err_w_message;
|
goto list_err_w_message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end_of_list:
|
|
||||||
|
end_of_list:
|
||||||
if (*(ptr++) != '\n')
|
if (*(ptr++) != '\n')
|
||||||
goto list_err;
|
goto list_err;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
list_err_w_message:
|
list_err_w_message:
|
||||||
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
parameter->name.str, line);
|
parameter->name.str, line);
|
||||||
list_err:
|
list_err:
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
case FILE_OPTIONS_ULLLIST:
|
||||||
|
{
|
||||||
|
nlist= (List<ulonglong>*)(base + parameter->offset);
|
||||||
|
nlist->empty();
|
||||||
|
// list parsing
|
||||||
|
while (ptr < end)
|
||||||
|
{
|
||||||
|
int not_used;
|
||||||
|
char *num_end= end;
|
||||||
|
if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||
|
||||||
|
nlist->push_back(num, mem_root))
|
||||||
|
goto nlist_err;
|
||||||
|
*num= my_strtoll10(ptr, &num_end, ¬_used);
|
||||||
|
ptr= num_end;
|
||||||
|
switch (*ptr) {
|
||||||
|
case '\n':
|
||||||
|
goto end_of_nlist;
|
||||||
|
case ' ':
|
||||||
|
// we cant go over buffer bounds, because we have \0 at the end
|
||||||
|
ptr++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto nlist_err_w_message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end_of_nlist:
|
||||||
|
if (*(ptr++) != '\n')
|
||||||
|
goto nlist_err;
|
||||||
|
break;
|
||||||
|
|
||||||
|
nlist_err_w_message:
|
||||||
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
|
parameter->name.str, line);
|
||||||
|
nlist_err:
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0); // never should happened
|
DBUG_ASSERT(0); // never should happened
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,10 @@ enum file_opt_type {
|
|||||||
FILE_OPTIONS_REV, /* Revision version number (ulonglong) */
|
FILE_OPTIONS_REV, /* Revision version number (ulonglong) */
|
||||||
FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be
|
FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be
|
||||||
allocated with length 20 (19+1) */
|
allocated with length 20 (19+1) */
|
||||||
FILE_OPTIONS_STRLIST /* list of escaped strings
|
FILE_OPTIONS_STRLIST, /* list of escaped strings
|
||||||
(List<LEX_STRING>) */
|
(List<LEX_STRING>) */
|
||||||
|
FILE_OPTIONS_ULLLIST /* list of ulonglong values
|
||||||
|
(List<ulonglong>) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct File_option
|
struct File_option
|
||||||
|
@ -3196,29 +3196,46 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var)
|
|||||||
Functions to handle sql_mode
|
Functions to handle sql_mode
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
|
/*
|
||||||
LEX_STRING *base)
|
Make string representation of mode
|
||||||
|
|
||||||
|
SINOPSYS
|
||||||
|
thd thread handler
|
||||||
|
val sql_mode value
|
||||||
|
len pointer on length of string
|
||||||
|
*/
|
||||||
|
|
||||||
|
byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd, ulong val,
|
||||||
|
ulong *len)
|
||||||
{
|
{
|
||||||
ulong val;
|
|
||||||
char buff[256];
|
char buff[256];
|
||||||
String tmp(buff, sizeof(buff), &my_charset_latin1);
|
String tmp(buff, sizeof(buff), &my_charset_latin1);
|
||||||
|
|
||||||
tmp.length(0);
|
tmp.length(0);
|
||||||
val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
|
|
||||||
thd->variables.*offset);
|
|
||||||
for (uint i= 0; val; val>>= 1, i++)
|
for (uint i= 0; val; val>>= 1, i++)
|
||||||
{
|
{
|
||||||
if (val & 1)
|
if (val & 1)
|
||||||
{
|
{
|
||||||
tmp.append(enum_names->type_names[i]);
|
tmp.append(sql_mode_typelib.type_names[i],
|
||||||
|
sql_mode_typelib.type_lengths[i]);
|
||||||
tmp.append(',');
|
tmp.append(',');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tmp.length())
|
if (tmp.length())
|
||||||
tmp.length(tmp.length() - 1);
|
tmp.length(tmp.length() - 1);
|
||||||
|
*len= tmp.length();
|
||||||
return (byte*) thd->strmake(tmp.ptr(), tmp.length());
|
return (byte*) thd->strmake(tmp.ptr(), tmp.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
|
||||||
|
LEX_STRING *base)
|
||||||
|
{
|
||||||
|
ulong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
|
||||||
|
thd->variables.*offset);
|
||||||
|
ulong length_unused;
|
||||||
|
return symbolic_mode_representation(thd, val, &length_unused);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
|
void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
|
||||||
{
|
{
|
||||||
|
@ -361,6 +361,8 @@ public:
|
|||||||
}
|
}
|
||||||
void set_default(THD *thd, enum_var_type type);
|
void set_default(THD *thd, enum_var_type type);
|
||||||
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
||||||
|
static byte *symbolic_mode_representation(THD *thd, ulong sql_mode,
|
||||||
|
ulong *length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -574,6 +574,7 @@ sp_head::execute(THD *thd)
|
|||||||
sp_rcontext *ctx;
|
sp_rcontext *ctx;
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
uint ip= 0;
|
uint ip= 0;
|
||||||
|
ulong save_sql_mode;
|
||||||
Query_arena *old_arena;
|
Query_arena *old_arena;
|
||||||
query_id_t old_query_id;
|
query_id_t old_query_id;
|
||||||
TABLE *old_derived_tables;
|
TABLE *old_derived_tables;
|
||||||
@ -626,6 +627,8 @@ sp_head::execute(THD *thd)
|
|||||||
old_query_id= thd->query_id;
|
old_query_id= thd->query_id;
|
||||||
old_derived_tables= thd->derived_tables;
|
old_derived_tables= thd->derived_tables;
|
||||||
thd->derived_tables= 0;
|
thd->derived_tables= 0;
|
||||||
|
save_sql_mode= thd->variables.sql_mode;
|
||||||
|
thd->variables.sql_mode= m_sql_mode;
|
||||||
/*
|
/*
|
||||||
It is also more efficient to save/restore current thd->lex once when
|
It is also more efficient to save/restore current thd->lex once when
|
||||||
do it in each instruction
|
do it in each instruction
|
||||||
@ -715,6 +718,7 @@ sp_head::execute(THD *thd)
|
|||||||
thd->query_id= old_query_id;
|
thd->query_id= old_query_id;
|
||||||
DBUG_ASSERT(!thd->derived_tables);
|
DBUG_ASSERT(!thd->derived_tables);
|
||||||
thd->derived_tables= old_derived_tables;
|
thd->derived_tables= old_derived_tables;
|
||||||
|
thd->variables.sql_mode= save_sql_mode;
|
||||||
|
|
||||||
thd->current_arena= old_arena;
|
thd->current_arena= old_arena;
|
||||||
state= EXECUTED;
|
state= EXECUTED;
|
||||||
@ -1245,8 +1249,6 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
String buffer(buff, sizeof(buff), system_charset_info);
|
String buffer(buff, sizeof(buff), system_charset_info);
|
||||||
int res;
|
int res;
|
||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
ulong old_sql_mode;
|
|
||||||
sys_var *sql_mode_var;
|
|
||||||
byte *sql_mode_str;
|
byte *sql_mode_str;
|
||||||
ulong sql_mode_len;
|
ulong sql_mode_len;
|
||||||
bool full_access;
|
bool full_access;
|
||||||
@ -1258,19 +1260,13 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
|
|
||||||
if (check_show_routine_access(thd, this, &full_access))
|
if (check_show_routine_access(thd, this, &full_access))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
old_sql_mode= thd->variables.sql_mode;
|
|
||||||
thd->variables.sql_mode= m_sql_mode;
|
|
||||||
sql_mode_var= find_sys_var("SQL_MODE", 8);
|
|
||||||
if (sql_mode_var)
|
|
||||||
{
|
|
||||||
sql_mode_str= sql_mode_var->value_ptr(thd, OPT_SESSION, 0);
|
|
||||||
sql_mode_len= strlen((char*) sql_mode_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
sql_mode_str=
|
||||||
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||||
|
m_sql_mode,
|
||||||
|
&sql_mode_len);
|
||||||
field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
|
field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
|
||||||
if (sql_mode_var)
|
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
||||||
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
|
||||||
// 1024 is for not to confuse old clients
|
// 1024 is for not to confuse old clients
|
||||||
field_list.push_back(new Item_empty_string("Create Procedure",
|
field_list.push_back(new Item_empty_string("Create Procedure",
|
||||||
max(buffer.length(), 1024)));
|
max(buffer.length(), 1024)));
|
||||||
@ -1282,15 +1278,13 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
}
|
}
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(m_name.str, m_name.length, system_charset_info);
|
protocol->store(m_name.str, m_name.length, system_charset_info);
|
||||||
if (sql_mode_var)
|
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
||||||
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
|
||||||
if (full_access)
|
if (full_access)
|
||||||
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
||||||
res= protocol->write();
|
res= protocol->write();
|
||||||
send_eof(thd);
|
send_eof(thd);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
thd->variables.sql_mode= old_sql_mode;
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,7 +1320,6 @@ sp_head::show_create_function(THD *thd)
|
|||||||
String buffer(buff, sizeof(buff), system_charset_info);
|
String buffer(buff, sizeof(buff), system_charset_info);
|
||||||
int res;
|
int res;
|
||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
ulong old_sql_mode;
|
|
||||||
sys_var *sql_mode_var;
|
sys_var *sql_mode_var;
|
||||||
byte *sql_mode_str;
|
byte *sql_mode_str;
|
||||||
ulong sql_mode_len;
|
ulong sql_mode_len;
|
||||||
@ -1339,15 +1332,10 @@ sp_head::show_create_function(THD *thd)
|
|||||||
if (check_show_routine_access(thd, this, &full_access))
|
if (check_show_routine_access(thd, this, &full_access))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
old_sql_mode= thd->variables.sql_mode;
|
sql_mode_str=
|
||||||
thd->variables.sql_mode= m_sql_mode;
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||||
sql_mode_var= find_sys_var("SQL_MODE", 8);
|
m_sql_mode,
|
||||||
if (sql_mode_var)
|
&sql_mode_len);
|
||||||
{
|
|
||||||
sql_mode_str= sql_mode_var->value_ptr(thd, OPT_SESSION, 0);
|
|
||||||
sql_mode_len= strlen((char*) sql_mode_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
field_list.push_back(new Item_empty_string("Function",NAME_LEN));
|
field_list.push_back(new Item_empty_string("Function",NAME_LEN));
|
||||||
if (sql_mode_var)
|
if (sql_mode_var)
|
||||||
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
||||||
@ -1361,15 +1349,13 @@ sp_head::show_create_function(THD *thd)
|
|||||||
}
|
}
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(m_name.str, m_name.length, system_charset_info);
|
protocol->store(m_name.str, m_name.length, system_charset_info);
|
||||||
if (sql_mode_var)
|
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
||||||
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
|
||||||
if (full_access)
|
if (full_access)
|
||||||
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
||||||
res= protocol->write();
|
res= protocol->write();
|
||||||
send_eof(thd);
|
send_eof(thd);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
thd->variables.sql_mode= old_sql_mode;
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ public:
|
|||||||
uchar *m_tmp_query; // Temporary pointer to sub query string
|
uchar *m_tmp_query; // Temporary pointer to sub query string
|
||||||
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
|
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
|
||||||
st_sp_chistics *m_chistics;
|
st_sp_chistics *m_chistics;
|
||||||
ulong m_sql_mode; // For SHOW CREATE
|
ulong m_sql_mode; // For SHOW CREATE and execution
|
||||||
LEX_STRING m_qname; // db.name
|
LEX_STRING m_qname; // db.name
|
||||||
LEX_STRING m_db;
|
LEX_STRING m_db;
|
||||||
LEX_STRING m_name;
|
LEX_STRING m_name;
|
||||||
|
@ -2983,9 +2983,13 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db,
|
|||||||
const char *tname, LEX_STRING *trigger_name,
|
const char *tname, LEX_STRING *trigger_name,
|
||||||
enum trg_event_type event,
|
enum trg_event_type event,
|
||||||
enum trg_action_time_type timing,
|
enum trg_action_time_type timing,
|
||||||
LEX_STRING *trigger_stmt)
|
LEX_STRING *trigger_stmt,
|
||||||
|
ulong sql_mode)
|
||||||
{
|
{
|
||||||
CHARSET_INFO *cs= system_charset_info;
|
CHARSET_INFO *cs= system_charset_info;
|
||||||
|
byte *sql_mode_str;
|
||||||
|
ulong sql_mode_len;
|
||||||
|
|
||||||
restore_record(table, s->default_values);
|
restore_record(table, s->default_values);
|
||||||
table->field[1]->store(db, strlen(db), cs);
|
table->field[1]->store(db, strlen(db), cs);
|
||||||
table->field[2]->store(trigger_name->str, trigger_name->length, cs);
|
table->field[2]->store(trigger_name->str, trigger_name->length, cs);
|
||||||
@ -2999,6 +3003,12 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db,
|
|||||||
trg_action_time_type_names[timing].length, cs);
|
trg_action_time_type_names[timing].length, cs);
|
||||||
table->field[14]->store("OLD", 3, cs);
|
table->field[14]->store("OLD", 3, cs);
|
||||||
table->field[15]->store("NEW", 3, cs);
|
table->field[15]->store("NEW", 3, cs);
|
||||||
|
|
||||||
|
sql_mode_str=
|
||||||
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||||
|
sql_mode,
|
||||||
|
&sql_mode_len);
|
||||||
|
table->field[17]->store(sql_mode_str, sql_mode_len, cs);
|
||||||
return schema_table_store_record(thd, table);
|
return schema_table_store_record(thd, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3031,13 +3041,16 @@ static int get_schema_triggers_record(THD *thd, struct st_table_list *tables,
|
|||||||
{
|
{
|
||||||
LEX_STRING trigger_name;
|
LEX_STRING trigger_name;
|
||||||
LEX_STRING trigger_stmt;
|
LEX_STRING trigger_stmt;
|
||||||
|
ulong sql_mode;
|
||||||
if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
|
if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
|
||||||
(enum trg_action_time_type)timing,
|
(enum trg_action_time_type)timing,
|
||||||
&trigger_name, &trigger_stmt))
|
&trigger_name, &trigger_stmt,
|
||||||
|
&sql_mode))
|
||||||
continue;
|
continue;
|
||||||
if (store_trigger(thd, table, base_name, file_name, &trigger_name,
|
if (store_trigger(thd, table, base_name, file_name, &trigger_name,
|
||||||
(enum trg_event_type) event,
|
(enum trg_event_type) event,
|
||||||
(enum trg_action_time_type) timing, &trigger_stmt))
|
(enum trg_action_time_type) timing, &trigger_stmt,
|
||||||
|
sql_mode))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3949,6 +3962,7 @@ ST_FIELD_INFO triggers_fields_info[]=
|
|||||||
{"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
{"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
||||||
{"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
{"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
|
||||||
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
|
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
|
||||||
|
{"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"},
|
||||||
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4003,7 +4017,7 @@ ST_SCHEMA_TABLE schema_tables[]=
|
|||||||
fill_open_tables, make_old_format, 0, -1, -1, 1},
|
fill_open_tables, make_old_format, 0, -1, -1, 1},
|
||||||
{"STATUS", variables_fields_info, create_schema_table, fill_status,
|
{"STATUS", variables_fields_info, create_schema_table, fill_status,
|
||||||
make_old_format, 0, -1, -1, 1},
|
make_old_format, 0, -1, -1, 1},
|
||||||
{"TRIGGERS", triggers_fields_info, create_schema_table,
|
{"TRIGGERS", triggers_fields_info, create_schema_table,
|
||||||
get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0},
|
get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0},
|
||||||
{"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
|
{"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
|
||||||
make_old_format, 0, -1, -1, 1},
|
make_old_format, 0, -1, -1, 1},
|
||||||
|
@ -32,8 +32,12 @@ const char * const triggers_file_ext= ".TRG";
|
|||||||
*/
|
*/
|
||||||
static File_option triggers_file_parameters[]=
|
static File_option triggers_file_parameters[]=
|
||||||
{
|
{
|
||||||
{{(char*)"triggers", 8}, offsetof(class Table_triggers_list, definitions_list),
|
{{(char*)"triggers", 8},
|
||||||
FILE_OPTIONS_STRLIST},
|
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}
|
{{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);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We do not allow creation of triggers on views or temporary tables.
|
We do not allow creation of triggers on temporary tables. We also don't
|
||||||
We have to do this check here and not in
|
allow creation of triggers on views but fulfilment of this restriction
|
||||||
Table_triggers_list::create_trigger() because we want to avoid messing
|
is guaranteed by open_ltable(). It is better to have this check here
|
||||||
with table cash for views and temporary tables.
|
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);
|
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
@ -221,6 +226,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
|
|||||||
trigname_path[FN_REFLEN];
|
trigname_path[FN_REFLEN];
|
||||||
LEX_STRING dir, file, trigname_file;
|
LEX_STRING dir, file, trigname_file;
|
||||||
LEX_STRING *trg_def, *name;
|
LEX_STRING *trg_def, *name;
|
||||||
|
ulonglong *trg_sql_mode;
|
||||||
Item_trigger_field *trg_field;
|
Item_trigger_field *trg_field;
|
||||||
struct st_trigname trigname;
|
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,
|
if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root,
|
||||||
sizeof(LEX_STRING))) ||
|
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;
|
goto err_with_cleanup;
|
||||||
|
|
||||||
trg_def->str= thd->query;
|
trg_def->str= thd->query;
|
||||||
trg_def->length= thd->query_length;
|
trg_def->length= thd->query_length;
|
||||||
|
*trg_sql_mode= thd->variables.sql_mode;
|
||||||
|
|
||||||
if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
|
if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
|
||||||
(gptr)this, triggers_file_parameters, 3))
|
(gptr)this, triggers_file_parameters, 3))
|
||||||
@ -390,11 +400,13 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
|
|||||||
LEX_STRING *name;
|
LEX_STRING *name;
|
||||||
List_iterator_fast<LEX_STRING> it_name(names_list);
|
List_iterator_fast<LEX_STRING> it_name(names_list);
|
||||||
List_iterator<LEX_STRING> it_def(definitions_list);
|
List_iterator<LEX_STRING> it_def(definitions_list);
|
||||||
|
List_iterator<ulonglong> it_mod(definition_modes_list);
|
||||||
char path[FN_REFLEN];
|
char path[FN_REFLEN];
|
||||||
|
|
||||||
while ((name= it_name++))
|
while ((name= it_name++))
|
||||||
{
|
{
|
||||||
it_def++;
|
it_def++;
|
||||||
|
it_mod++;
|
||||||
|
|
||||||
if (my_strcasecmp(system_charset_info, lex->spname->m_name.str,
|
if (my_strcasecmp(system_charset_info, lex->spname->m_name.str,
|
||||||
name->str) == 0)
|
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.
|
clean trigger removing since table will be reopened anyway.
|
||||||
*/
|
*/
|
||||||
it_def.remove();
|
it_def.remove();
|
||||||
|
it_mod.remove();
|
||||||
|
|
||||||
if (definitions_list.is_empty())
|
if (definitions_list.is_empty())
|
||||||
{
|
{
|
||||||
@ -549,10 +562,48 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||||||
if (!triggers)
|
if (!triggers)
|
||||||
DBUG_RETURN(1);
|
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,
|
if (parser->parse((gptr)triggers, &table->mem_root,
|
||||||
triggers_file_parameters, 1))
|
triggers_file_parameters, 2))
|
||||||
DBUG_RETURN(1);
|
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;
|
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))
|
if (!names_only && triggers->prepare_record1_accessors(table))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
|
|
||||||
LEX_STRING *trg_create_str, *trg_name_str;
|
|
||||||
char *trg_name_buff;
|
char *trg_name_buff;
|
||||||
|
List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
|
||||||
LEX *old_lex= thd->lex, lex;
|
LEX *old_lex= thd->lex, lex;
|
||||||
|
ulong save_sql_mode= thd->variables.sql_mode;
|
||||||
|
|
||||||
thd->lex= &lex;
|
thd->lex= &lex;
|
||||||
|
|
||||||
while ((trg_create_str= it++))
|
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);
|
lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
|
||||||
|
|
||||||
if (yyparse((void *)thd) || thd->is_fatal_error)
|
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;
|
goto err_with_lex_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lex.sphead->m_sql_mode= *trg_sql_mode;
|
||||||
triggers->bodies[lex.trg_chistics.event]
|
triggers->bodies[lex.trg_chistics.event]
|
||||||
[lex.trg_chistics.action_time]= lex.sphead;
|
[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;
|
goto err_with_lex_cleanup;
|
||||||
|
|
||||||
if (names_only)
|
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
|
in old/new versions of row in trigger to Field objects in table being
|
||||||
opened.
|
opened.
|
||||||
|
|
||||||
We ignore errors here, because if even something is wrong we still will
|
We ignore errors here, because if even something is wrong we still
|
||||||
be willing to open table to perform some operations (e.g. SELECT)...
|
will be willing to open table to perform some operations (e.g.
|
||||||
|
SELECT)...
|
||||||
Anyway some things can be checked only during trigger execution.
|
Anyway some things can be checked only during trigger execution.
|
||||||
*/
|
*/
|
||||||
for (Item_trigger_field *trg_field=
|
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);
|
lex_end(&lex);
|
||||||
}
|
}
|
||||||
thd->lex= old_lex;
|
thd->lex= old_lex;
|
||||||
|
thd->variables.sql_mode= save_sql_mode;
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
@ -631,6 +688,7 @@ err_with_lex_cleanup:
|
|||||||
// QQ: anything else ?
|
// QQ: anything else ?
|
||||||
lex_end(&lex);
|
lex_end(&lex);
|
||||||
thd->lex= old_lex;
|
thd->lex= old_lex;
|
||||||
|
thd->variables.sql_mode= save_sql_mode;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,6 +715,7 @@ err_with_lex_cleanup:
|
|||||||
time_type - trigger action time
|
time_type - trigger action time
|
||||||
name - returns name of trigger
|
name - returns name of trigger
|
||||||
stmt - returns statement of trigger
|
stmt - returns statement of trigger
|
||||||
|
sql_mode - returns sql_mode of trigger
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
False - success
|
False - success
|
||||||
@ -666,7 +725,8 @@ err_with_lex_cleanup:
|
|||||||
bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
||||||
trg_action_time_type time_type,
|
trg_action_time_type time_type,
|
||||||
LEX_STRING *trigger_name,
|
LEX_STRING *trigger_name,
|
||||||
LEX_STRING *trigger_stmt)
|
LEX_STRING *trigger_stmt,
|
||||||
|
ulong *sql_mode)
|
||||||
{
|
{
|
||||||
sp_head *body;
|
sp_head *body;
|
||||||
DBUG_ENTER("get_trigger_info");
|
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_name= body->m_name;
|
||||||
*trigger_stmt= body->m_body;
|
*trigger_stmt= body->m_body;
|
||||||
|
*sql_mode= body->m_sql_mode;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
@ -60,6 +60,10 @@ public:
|
|||||||
It have to be public because we are using it directly from parser.
|
It have to be public because we are using it directly from parser.
|
||||||
*/
|
*/
|
||||||
List<LEX_STRING> definitions_list;
|
List<LEX_STRING> definitions_list;
|
||||||
|
/*
|
||||||
|
List of sql modes for triggers
|
||||||
|
*/
|
||||||
|
List<ulonglong> definition_modes_list;
|
||||||
|
|
||||||
Table_triggers_list(TABLE *table_arg):
|
Table_triggers_list(TABLE *table_arg):
|
||||||
record1_field(0), table(table_arg)
|
record1_field(0), table(table_arg)
|
||||||
@ -123,7 +127,8 @@ public:
|
|||||||
}
|
}
|
||||||
bool get_trigger_info(THD *thd, trg_event_type event,
|
bool get_trigger_info(THD *thd, trg_event_type event,
|
||||||
trg_action_time_type time_type,
|
trg_action_time_type time_type,
|
||||||
LEX_STRING *trigger_name, LEX_STRING *trigger_stmt);
|
LEX_STRING *trigger_name, LEX_STRING *trigger_stmt,
|
||||||
|
ulong *sql_mode);
|
||||||
|
|
||||||
static bool check_n_load(THD *thd, const char *db, const char *table_name,
|
static bool check_n_load(THD *thd, const char *db, const char *table_name,
|
||||||
TABLE *table, bool names_only);
|
TABLE *table, bool names_only);
|
||||||
|
@ -691,7 +691,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
view_select= &lex->select_lex;
|
view_select= &lex->select_lex;
|
||||||
view_select->select_number= ++thd->select_number;
|
view_select->select_number= ++thd->select_number;
|
||||||
{
|
{
|
||||||
ulong options= thd->options;
|
ulong save_mode= thd->variables.sql_mode;
|
||||||
/* switch off modes which can prevent normal parsing of VIEW
|
/* switch off modes which can prevent normal parsing of VIEW
|
||||||
- MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing
|
- MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing
|
||||||
+ MODE_PIPES_AS_CONCAT affect expression parsing
|
+ MODE_PIPES_AS_CONCAT affect expression parsing
|
||||||
@ -716,13 +716,13 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs
|
? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs
|
||||||
+ MODE_NO_BACKSLASH_ESCAPES affect expression parsing
|
+ MODE_NO_BACKSLASH_ESCAPES affect expression parsing
|
||||||
*/
|
*/
|
||||||
thd->options&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
|
thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
|
||||||
MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
|
MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
|
||||||
CHARSET_INFO *save_cs= thd->variables.character_set_client;
|
CHARSET_INFO *save_cs= thd->variables.character_set_client;
|
||||||
thd->variables.character_set_client= system_charset_info;
|
thd->variables.character_set_client= system_charset_info;
|
||||||
res= yyparse((void *)thd);
|
res= yyparse((void *)thd);
|
||||||
thd->variables.character_set_client= save_cs;
|
thd->variables.character_set_client= save_cs;
|
||||||
thd->options= options;
|
thd->variables.sql_mode= save_mode;
|
||||||
}
|
}
|
||||||
if (!res && !thd->is_fatal_error)
|
if (!res && !thd->is_fatal_error)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user