Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
d098bfff
Commit
d098bfff
authored
Jun 14, 2007
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Merge malff@bk-internal.mysql.com:/home/bk/mysql-5.1-runtime
into weblab.(none):/home/marcsql/TREE/mysql-5.1-27857
parents
8b8b2888
83de46bc
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
535 additions
and
338 deletions
+535
-338
include/my_sys.h
include/my_sys.h
+8
-0
mysql-test/t/events_restart_phase3.test
mysql-test/t/events_restart_phase3.test
+1
-0
mysys/charset.c
mysys/charset.c
+64
-0
sql/event_data_objects.cc
sql/event_data_objects.cc
+56
-105
sql/event_data_objects.h
sql/event_data_objects.h
+5
-9
sql/event_db_repository.cc
sql/event_db_repository.cc
+21
-7
sql/handler.cc
sql/handler.cc
+2
-2
sql/mysql_priv.h
sql/mysql_priv.h
+12
-4
sql/sp.cc
sql/sp.cc
+20
-20
sql/sp_head.cc
sql/sp_head.cc
+65
-19
sql/sp_head.h
sql/sp_head.h
+4
-2
sql/sql_class.cc
sql/sql_class.cc
+2
-1
sql/sql_db.cc
sql/sql_db.cc
+36
-13
sql/sql_parse.cc
sql/sql_parse.cc
+36
-8
sql/sql_partition.cc
sql/sql_partition.cc
+1
-2
sql/sql_prepare.cc
sql/sql_prepare.cc
+3
-4
sql/sql_trigger.cc
sql/sql_trigger.cc
+180
-130
sql/sql_trigger.h
sql/sql_trigger.h
+15
-4
sql/sql_view.cc
sql/sql_view.cc
+3
-4
sql/sql_yacc.yy
sql/sql_yacc.yy
+1
-4
No files found.
include/my_sys.h
View file @
d098bfff
...
...
@@ -904,6 +904,14 @@ extern CHARSET_INFO *get_charset(uint cs_number, myf flags);
extern
CHARSET_INFO
*
get_charset_by_name
(
const
char
*
cs_name
,
myf
flags
);
extern
CHARSET_INFO
*
get_charset_by_csname
(
const
char
*
cs_name
,
uint
cs_flags
,
myf
my_flags
);
extern
bool
resolve_charset
(
CHARSET_INFO
**
cs
,
const
char
*
cs_name
,
CHARSET_INFO
*
default_cs
);
extern
bool
resolve_collation
(
CHARSET_INFO
**
cl
,
const
char
*
cl_name
,
CHARSET_INFO
*
default_cl
);
extern
void
free_charsets
(
void
);
extern
char
*
get_charsets_dir
(
char
*
buf
);
extern
my_bool
my_charset_same
(
CHARSET_INFO
*
cs1
,
CHARSET_INFO
*
cs2
);
...
...
mysql-test/t/events_restart_phase3.test
View file @
d098bfff
...
...
@@ -18,3 +18,4 @@ drop database events_test;
let
$wait_condition
=
select
count
(
*
)
=
0
from
information_schema
.
processlist
where
db
=
'events_test'
and
command
=
'Connect'
and
user
=
current_user
();
--
source
include
/
wait_condition
.
inc
mysys/charset.c
View file @
d098bfff
...
...
@@ -573,6 +573,70 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
}
/**
Resolve character set by the character set name (utf8, latin1, ...).
The function tries to resolve character set by the specified name. If
there is character set with the given name, it is assigned to the "cs"
parameter and FALSE is returned. If there is no such character set,
"default_cs" is assigned to the "cs" and TRUE is returned.
@param[out] cs Variable to store character set.
@param[in] cs_name Character set name.
@param[in] default_cs Default character set.
@return FALSE if character set was resolved successfully; TRUE if there
is no character set with given name.
*/
bool
resolve_charset
(
CHARSET_INFO
**
cs
,
const
char
*
cs_name
,
CHARSET_INFO
*
default_cs
)
{
*
cs
=
get_charset_by_csname
(
cs_name
,
MY_CS_PRIMARY
,
MYF
(
0
));
if
(
*
cs
==
NULL
)
{
*
cs
=
default_cs
;
return
TRUE
;
}
return
FALSE
;
}
/**
Resolve collation by the collation name (utf8_general_ci, ...).
The function tries to resolve collation by the specified name. If there
is collation with the given name, it is assigned to the "cl" parameter
and FALSE is returned. If there is no such collation, "default_cl" is
assigned to the "cl" and TRUE is returned.
@param[out] cl Variable to store collation.
@param[in] cl_name Collation name.
@param[in] default_cl Default collation.
@return FALSE if collation was resolved successfully; TRUE if there is no
collation with given name.
*/
bool
resolve_collation
(
CHARSET_INFO
**
cl
,
const
char
*
cl_name
,
CHARSET_INFO
*
default_cl
)
{
*
cl
=
get_charset_by_name
(
cl_name
,
MYF
(
0
));
if
(
*
cl
==
NULL
)
{
*
cl
=
default_cl
;
return
TRUE
;
}
return
FALSE
;
}
/*
Escape string with backslashes (\)
...
...
sql/event_data_objects.cc
View file @
d098bfff
...
...
@@ -94,6 +94,7 @@ Event_parse_data::Event_parse_data()
:
on_completion
(
Event_basic
::
ON_COMPLETION_DROP
),
status
(
Event_basic
::
ENABLED
),
do_not_create
(
FALSE
),
body_changed
(
FALSE
),
item_starts
(
NULL
),
item_ends
(
NULL
),
item_execute_at
(
NULL
),
starts_null
(
TRUE
),
ends_null
(
TRUE
),
execute_at_null
(
TRUE
),
item_expression
(
NULL
),
expression
(
0
)
...
...
@@ -103,8 +104,8 @@ Event_parse_data::Event_parse_data()
/* Actually in the parser STARTS is always set */
starts
=
ends
=
execute_at
=
0
;
body
.
str
=
comment
.
str
=
NULL
;
body
.
length
=
comment
.
length
=
0
;
comment
.
str
=
NULL
;
comment
.
length
=
0
;
DBUG_VOID_RETURN
;
}
...
...
@@ -137,36 +138,6 @@ Event_parse_data::init_name(THD *thd, sp_name *spn)
}
/*
Set body of the event - what should be executed.
SYNOPSIS
Event_parse_data::init_body()
thd THD
NOTE
The body is extracted by copying all data between the
start of the body set by another method and the current pointer in Lex.
See related code in sp_head::init_strings().
*/
void
Event_parse_data
::
init_body
(
THD
*
thd
)
{
DBUG_ENTER
(
"Event_parse_data::init_body"
);
/* This method is called from within the parser, from sql_yacc.yy */
DBUG_ASSERT
(
thd
->
m_lip
!=
NULL
);
body
.
length
=
thd
->
m_lip
->
get_cpp_ptr
()
-
body_begin
;
body
.
str
=
thd
->
strmake
(
body_begin
,
body
.
length
);
trim_whitespace
(
thd
->
charset
(),
&
body
);
DBUG_VOID_RETURN
;
}
/*
This function is called on CREATE EVENT or ALTER EVENT. When either
ENDS or AT is in the past, we are trying to create an event that
...
...
@@ -788,36 +759,32 @@ Event_timed::init()
}
/*
Loads an event's body from a row from mysql.event
SYNOPSIS
Event_job_data::load_from_row(THD *thd, TABLE *table)
RETURN VALUE
0 OK
EVEX_GET_FIELD_FAILED Error
NOTES
This method is silent on errors and should behave like that. Callers
should handle throwing of error messages. The reason is that the class
should not know about how to deal with communication.
/**
Load an event's body from a row from mysql.event.
@details This method is silent on errors and should behave like that.
Callers should handle throwing of error messages. The reason is that the
class should not know about how to deal with communication.
@return Operation status
@retval FALSE OK
@retval TRUE Error
*/
int
bool
Event_job_data
::
load_from_row
(
THD
*
thd
,
TABLE
*
table
)
{
char
*
ptr
;
uint
len
;
LEX_STRING
tz_name
;
DBUG_ENTER
(
"Event_job_data::load_from_row"
);
if
(
!
table
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
if
(
table
->
s
->
fields
<
ET_FIELD_COUNT
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
LEX_STRING
tz_name
;
if
(
load_string_fields
(
table
->
field
,
ET_FIELD_DB
,
&
dbname
,
ET_FIELD_NAME
,
&
name
,
...
...
@@ -825,10 +792,10 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
ET_FIELD_DEFINER
,
&
definer
,
ET_FIELD_TIME_ZONE
,
&
tz_name
,
ET_FIELD_COUNT
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
if
(
load_time_zone
(
thd
,
tz_name
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
ptr
=
strchr
(
definer
.
str
,
'@'
);
...
...
@@ -845,29 +812,23 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
sql_mode
=
(
ulong
)
table
->
field
[
ET_FIELD_SQL_MODE
]
->
val_int
();
DBUG_RETURN
(
0
);
error:
DBUG_RETURN
(
EVEX_GET_FIELD_FAILED
);
DBUG_RETURN
(
FALSE
);
}
/*
Loads an event from a row from mysql.event
SYNOPSIS
Event_queue_element::load_from_row(THD *thd, TABLE *table)
/**
Load an event's body from a row from mysql.event.
RETURN VALUE
0 OK
EVEX_GET_FIELD_FAILED Error
@details This method is silent on errors and should behave like that.
Callers should handle throwing of error messages. The reason is that the
class should not know about how to deal with communication.
NOTES
This method is silent on errors and should behave like that. Callers
should handle throwing of error messages. The reason is that the class
should not know about how to deal with communication.
@return Operation status
@retval FALSE OK
@retval TRUE Error
*/
int
bool
Event_queue_element
::
load_from_row
(
THD
*
thd
,
TABLE
*
table
)
{
char
*
ptr
;
...
...
@@ -877,10 +838,10 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
DBUG_ENTER
(
"Event_queue_element::load_from_row"
);
if
(
!
table
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
if
(
table
->
s
->
fields
<
ET_FIELD_COUNT
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
if
(
load_string_fields
(
table
->
field
,
ET_FIELD_DB
,
&
dbname
,
...
...
@@ -888,10 +849,10 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
ET_FIELD_DEFINER
,
&
definer
,
ET_FIELD_TIME_ZONE
,
&
tz_name
,
ET_FIELD_COUNT
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
if
(
load_time_zone
(
thd
,
tz_name
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
starts_null
=
table
->
field
[
ET_FIELD_STARTS
]
->
is_null
();
if
(
!
starts_null
)
...
...
@@ -921,7 +882,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
{
if
(
table
->
field
[
ET_FIELD_EXECUTE_AT
]
->
get_date
(
&
time
,
TIME_NO_ZERO_DATE
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
execute_at
=
sec_since_epoch_TIME
(
&
time
);
}
...
...
@@ -940,13 +901,13 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
table
->
field
[
ET_FIELD_TRANSIENT_INTERVAL
]
->
val_str
(
&
str
);
if
(
!
(
tmp
.
length
=
str
.
length
()))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
tmp
.
str
=
str
.
c_ptr_safe
();
i
=
find_string_in_array
(
interval_type_to_name
,
&
tmp
,
system_charset_info
);
if
(
i
<
0
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
interval
=
(
interval_type
)
i
;
}
...
...
@@ -959,7 +920,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
last_executed_changed
=
FALSE
;
if
((
ptr
=
get_field
(
&
mem_root
,
table
->
field
[
ET_FIELD_STATUS
]))
==
NullS
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
DBUG_PRINT
(
"load_from_row"
,
(
"Event [%s] is [%s]"
,
name
.
str
,
ptr
));
...
...
@@ -978,40 +939,34 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
break
;
}
if
((
ptr
=
get_field
(
&
mem_root
,
table
->
field
[
ET_FIELD_ORIGINATOR
]))
==
NullS
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
originator
=
table
->
field
[
ET_FIELD_ORIGINATOR
]
->
val_int
();
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if
((
ptr
=
get_field
(
&
mem_root
,
table
->
field
[
ET_FIELD_ON_COMPLETION
]))
==
NullS
)
goto
error
;
DBUG_RETURN
(
TRUE
)
;
on_completion
=
(
ptr
[
0
]
==
'D'
?
Event_queue_element
::
ON_COMPLETION_DROP
:
Event_queue_element
::
ON_COMPLETION_PRESERVE
);
DBUG_RETURN
(
0
);
error:
DBUG_RETURN
(
EVEX_GET_FIELD_FAILED
);
DBUG_RETURN
(
FALSE
);
}
/*
Loads an event from a row from mysql.event
SYNOPSIS
Event_timed::load_from_row(THD *thd, TABLE *table)
/**
Load an event's body from a row from mysql.event.
RETURN VALUE
0 OK
EVEX_GET_FIELD_FAILED Error
@details This method is silent on errors and should behave like that.
Callers should handle throwing of error messages. The reason is that the
class should not know about how to deal with communication.
NOTES
This method is silent on errors and should behave like that. Callers
should handle throwing of error messages. The reason is that the class
should not know about how to deal with communication.
@return Operation status
@retval FALSE OK
@retval TRUE Error
*/
int
bool
Event_timed
::
load_from_row
(
THD
*
thd
,
TABLE
*
table
)
{
char
*
ptr
;
...
...
@@ -1020,12 +975,12 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
DBUG_ENTER
(
"Event_timed::load_from_row"
);
if
(
Event_queue_element
::
load_from_row
(
thd
,
table
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
if
(
load_string_fields
(
table
->
field
,
ET_FIELD_BODY
,
&
body
,
ET_FIELD_COUNT
))
goto
error
;
DBUG_RETURN
(
TRUE
)
;
ptr
=
strchr
(
definer
.
str
,
'@'
);
...
...
@@ -1052,9 +1007,7 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
sql_mode
=
(
ulong
)
table
->
field
[
ET_FIELD_SQL_MODE
]
->
val_int
();
DBUG_RETURN
(
0
);
error:
DBUG_RETURN
(
EVEX_GET_FIELD_FAILED
);
DBUG_RETURN
(
FALSE
);
}
...
...
@@ -1875,11 +1828,9 @@ Event_job_data::execute(THD *thd, bool drop)
{
Lex_input_stream
lip
(
thd
,
thd
->
query
,
thd
->
query_length
);
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
int
err
=
MYSQLparse
(
thd
);
if
(
err
||
thd
->
is_fatal_error
)
if
(
parse_sql
(
thd
,
&
lip
)
)
{
sql_print_error
(
"Event Scheduler: "
"%serror during compilation of %s.%s"
,
...
...
sql/event_data_objects.h
View file @
d098bfff
...
...
@@ -77,7 +77,7 @@ public:
Event_basic
();
virtual
~
Event_basic
();
virtual
int
virtual
bool
load_from_row
(
THD
*
thd
,
TABLE
*
table
)
=
0
;
protected:
...
...
@@ -119,7 +119,7 @@ public:
Event_queue_element
();
virtual
~
Event_queue_element
();
virtual
int
virtual
bool
load_from_row
(
THD
*
thd
,
TABLE
*
table
);
bool
...
...
@@ -157,7 +157,7 @@ public:
void
init
();
virtual
int
virtual
bool
load_from_row
(
THD
*
thd
,
TABLE
*
table
);
int
...
...
@@ -176,7 +176,7 @@ public:
Event_job_data
();
virtual
int
virtual
bool
load_from_row
(
THD
*
thd
,
TABLE
*
table
);
bool
...
...
@@ -205,12 +205,11 @@ public:
*/
bool
do_not_create
;
const
char
*
body_begin
;
bool
body_changed
;
LEX_STRING
dbname
;
LEX_STRING
name
;
LEX_STRING
definer
;
// combination of user and host
LEX_STRING
body
;
LEX_STRING
comment
;
Item
*
item_starts
;
...
...
@@ -235,9 +234,6 @@ public:
bool
check_parse_data
(
THD
*
thd
);
void
init_body
(
THD
*
thd
);
private:
void
...
...
sql/event_db_repository.cc
View file @
d098bfff
...
...
@@ -15,6 +15,7 @@
#include "mysql_priv.h"
#include "event_db_repository.h"
#include "sp_head.h"
#include "event_data_objects.h"
#include "events.h"
#include "sql_show.h"
...
...
@@ -141,7 +142,10 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
*/
static
bool
mysql_event_fill_row
(
THD
*
thd
,
TABLE
*
table
,
Event_parse_data
*
et
,
mysql_event_fill_row
(
THD
*
thd
,
TABLE
*
table
,
Event_parse_data
*
et
,
sp_head
*
sp
,
my_bool
is_update
)
{
CHARSET_INFO
*
scs
=
system_charset_info
;
...
...
@@ -152,7 +156,6 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
DBUG_PRINT
(
"info"
,
(
"dbname=[%s]"
,
et
->
dbname
.
str
));
DBUG_PRINT
(
"info"
,
(
"name =[%s]"
,
et
->
name
.
str
));
DBUG_PRINT
(
"info"
,
(
"body =[%s]"
,
et
->
body
.
str
));
if
(
table
->
s
->
fields
<
ET_FIELD_COUNT
)
{
...
...
@@ -187,12 +190,19 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
always during CREATE EVENT.
*/
if
(
et
->
body
.
str
)
if
(
et
->
body
_changed
)
{
DBUG_ASSERT
(
sp
->
m_body
.
str
);
fields
[
ET_FIELD_SQL_MODE
]
->
store
((
longlong
)
thd
->
variables
.
sql_mode
,
TRUE
);
if
(
fields
[
f_num
=
ET_FIELD_BODY
]
->
store
(
et
->
body
.
str
,
et
->
body
.
length
,
scs
))
if
(
fields
[
f_num
=
ET_FIELD_BODY
]
->
store
(
sp
->
m_body
.
str
,
sp
->
m_body
.
length
,
scs
))
{
goto
err_truncate
;
}
}
if
(
et
->
expression
)
{
...
...
@@ -513,10 +523,12 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
{
int
ret
=
1
;
TABLE
*
table
=
NULL
;
sp_head
*
sp
=
thd
->
lex
->
sphead
;
DBUG_ENTER
(
"Event_db_repository::create_event"
);
DBUG_PRINT
(
"info"
,
(
"open mysql.event for update"
));
DBUG_ASSERT
(
sp
);
if
(
open_event_table
(
thd
,
TL_WRITE
,
&
table
))
goto
end
;
...
...
@@ -561,7 +573,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
goto
end
;
}
if
(
parse_data
->
body
.
length
>
table
->
field
[
ET_FIELD_BODY
]
->
field_length
)
if
(
sp
->
m_
body
.
length
>
table
->
field
[
ET_FIELD_BODY
]
->
field_length
)
{
my_error
(
ER_TOO_LONG_BODY
,
MYF
(
0
),
parse_data
->
name
.
str
);
goto
end
;
...
...
@@ -573,7 +585,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
mysql_event_fill_row() calls my_error() in case of error so no need to
handle it here
*/
if
(
mysql_event_fill_row
(
thd
,
table
,
parse_data
,
FALSE
))
if
(
mysql_event_fill_row
(
thd
,
table
,
parse_data
,
sp
,
FALSE
))
goto
end
;
table
->
field
[
ET_FIELD_STATUS
]
->
store
((
longlong
)
parse_data
->
status
,
TRUE
);
...
...
@@ -617,7 +629,9 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
{
CHARSET_INFO
*
scs
=
system_charset_info
;
TABLE
*
table
=
NULL
;
sp_head
*
sp
=
thd
->
lex
->
sphead
;
int
ret
=
1
;
DBUG_ENTER
(
"Event_db_repository::update_event"
);
/* None or both must be set */
...
...
@@ -661,7 +675,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
mysql_event_fill_row() calls my_error() in case of error so no need to
handle it here
*/
if
(
mysql_event_fill_row
(
thd
,
table
,
parse_data
,
TRUE
))
if
(
mysql_event_fill_row
(
thd
,
table
,
parse_data
,
sp
,
TRUE
))
goto
end
;
if
(
new_dbname
)
...
...
sql/handler.cc
View file @
d098bfff
...
...
@@ -3376,8 +3376,8 @@ TYPELIB *ha_known_exts(void)
const
char
**
ext
,
*
old_ext
;
known_extensions_id
=
mysys_usage_id
;
found_exts
.
push_back
((
char
*
)
triggers_file_ext
);
found_exts
.
push_back
((
char
*
)
trigname_file_ext
);
found_exts
.
push_back
((
char
*
)
TRG_EXT
);
found_exts
.
push_back
((
char
*
)
TRN_EXT
);
plugin_foreach
(
NULL
,
exts_handlerton
,
MYSQL_STORAGE_ENGINE_PLUGIN
,
&
found_exts
);
...
...
sql/mysql_priv.h
View file @
d098bfff
...
...
@@ -101,7 +101,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
(Old), (Ver), (New)); \
else \
sql_print_warning("The syntax
%s is deprecated and will be removed "
\
sql_print_warning("The syntax
'%s' is deprecated and will be removed "
\
"in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
} while(0)
...
...
@@ -618,6 +618,8 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg,
uint
max_char_length
,
CHARSET_INFO
*
cs
,
bool
no_error
);
bool
parse_sql
(
THD
*
thd
,
class
Lex_input_stream
*
lip
);
enum
enum_mysql_completiontype
{
ROLLBACK_RELEASE
=-
2
,
ROLLBACK
=
1
,
ROLLBACK_AND_CHAIN
=
7
,
COMMIT_RELEASE
=-
1
,
COMMIT
=
0
,
COMMIT_AND_CHAIN
=
6
...
...
@@ -1588,6 +1590,7 @@ bool check_db_dir_existence(const char *db_name);
bool
load_db_opt
(
THD
*
thd
,
const
char
*
path
,
HA_CREATE_INFO
*
create
);
bool
load_db_opt_by_name
(
THD
*
thd
,
const
char
*
db_name
,
HA_CREATE_INFO
*
db_create_info
);
CHARSET_INFO
*
get_default_db_collation
(
THD
*
thd
,
const
char
*
db_name
);
bool
my_dbopt_init
(
void
);
void
my_dbopt_cleanup
(
void
);
extern
int
creating_database
;
// How many database locks are made
...
...
@@ -1608,8 +1611,8 @@ extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword;
extern
const
char
**
errmesg
;
/* Error messages */
extern
const
char
*
myisam_recover_options_str
;
extern
const
char
*
in_left_expr_name
,
*
in_additional_cond
,
*
in_having_cond
;
extern
const
char
*
const
triggers_file_ext
;
extern
const
char
*
const
trigname_file_ext
;
extern
const
char
*
const
TRG_EXT
;
extern
const
char
*
const
TRN_EXT
;
extern
Eq_creator
eq_creator
;
extern
Ne_creator
ne_creator
;
extern
Gt_creator
gt_creator
;
...
...
@@ -1953,7 +1956,6 @@ void free_list(I_List <i_string_pair> *list);
void
free_list
(
I_List
<
i_string
>
*
list
);
/* sql_yacc.cc */
extern
int
MYSQLparse
(
void
*
thd
);
#ifndef DBUG_OFF
extern
void
turn_parser_debug_on
();
#endif
...
...
@@ -2145,6 +2147,12 @@ bool schema_table_store_record(THD *thd, TABLE *table);
int
item_create_init
();
void
item_create_cleanup
();
inline
void
lex_string_set
(
LEX_STRING
*
lex_str
,
const
char
*
c_str
)
{
lex_str
->
str
=
(
char
*
)
c_str
;
lex_str
->
length
=
strlen
(
c_str
);
}
#endif
/* MYSQL_SERVER */
#endif
/* MYSQL_CLIENT */
...
...
sql/sp.cc
View file @
d098bfff
...
...
@@ -384,15 +384,13 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
if
((
ret
=
sp_use_new_db
(
thd
,
name
->
m_db
,
&
old_db
,
1
,
&
dbchanged
)))
goto
end
;
thd
->
spcont
=
NULL
;
{
Lex_input_stream
lip
(
thd
,
defstr
.
c_ptr
(),
defstr
.
length
());
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
ret
=
MYSQLparse
(
thd
);
}
thd
->
spcont
=
0
;
if
(
ret
||
thd
->
is_fatal_error
||
newlex
.
sphead
==
NULL
)
if
(
parse_sql
(
thd
,
&
lip
)
||
newlex
.
sphead
==
NULL
)
{
sp_head
*
sp
=
newlex
.
sphead
;
...
...
@@ -410,6 +408,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
(
*
sphp
)
->
set_info
(
created
,
modified
,
&
chistics
,
sql_mode
);
(
*
sphp
)
->
optimize
();
}
}
end:
lex_end
(
thd
->
lex
);
thd
->
spcont
=
old_spcont
;
...
...
sql/sp_head.cc
View file @
d098bfff
...
...
@@ -1268,30 +1268,31 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
#endif // ! NO_EMBEDDED_ACCESS_CHECKS
/*
/**
Execute trigger stored program.
Execute a trigger:
- changes security context for triggers
- switch to new memroot
- call sp_head::execute
- restore old memroot
- restores security context
- changes security context for triggers
;
- switch to new memroot
;
- call sp_head::execute
;
- restore old memroot
;
- restores security context
.
SYNOPSIS
sp_head::execute_trigger()
thd Thread handle
db database name
table table name
grant_info GRANT_INFO structure to be filled with
information about definer's privileges
on subject table
@param thd Thread context.
@param db_name Database name.
@param table_name Table name.
@param grant_info GRANT_INFO structure to be filled with information
about definer's privileges on subject table.
RETURN
FALSE on success
TRUE on error
@return Error status.
@retval FALSE on success.
@retval TRUE on error.
*/
bool
sp_head
::
execute_trigger
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table
,
sp_head
::
execute_trigger
(
THD
*
thd
,
const
LEX_STRING
*
db_name
,
const
LEX_STRING
*
table_name
,
GRANT_INFO
*
grant_info
)
{
sp_rcontext
*
octx
=
thd
->
spcont
;
...
...
@@ -1304,6 +1305,46 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table,
DBUG_ENTER
(
"sp_head::execute_trigger"
);
DBUG_PRINT
(
"info"
,
(
"trigger %s"
,
m_name
.
str
));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Security_context
*
save_ctx
=
NULL
;
if
(
m_chistics
->
suid
!=
SP_IS_NOT_SUID
&&
m_security_ctx
.
change_security_context
(
thd
,
&
m_definer_user
,
&
m_definer_host
,
&
m_db
,
&
save_ctx
))
DBUG_RETURN
(
TRUE
);
/*
Fetch information about table-level privileges for subject table into
GRANT_INFO instance. The access check itself will happen in
Item_trigger_field, where this information will be used along with
information about column-level privileges.
*/
fill_effective_table_privileges
(
thd
,
grant_info
,
db_name
->
str
,
table_name
->
str
);
/* Check that the definer has TRIGGER privilege on the subject table. */
if
(
!
(
grant_info
->
privilege
&
TRIGGER_ACL
))
{
char
priv_desc
[
128
];
get_privilege_desc
(
priv_desc
,
sizeof
(
priv_desc
),
TRIGGER_ACL
);
my_error
(
ER_TABLEACCESS_DENIED_ERROR
,
MYF
(
0
),
priv_desc
,
thd
->
security_ctx
->
priv_user
,
thd
->
security_ctx
->
host_or_ip
,
table_name
->
str
);
m_security_ctx
.
restore_security_context
(
thd
,
save_ctx
);
DBUG_RETURN
(
TRUE
);
}
#endif // NO_EMBEDDED_ACCESS_CHECKS
/*
Prepare arena and memroot for objects which lifetime is whole
duration of trigger call (sp_rcontext, it's tables and items,
...
...
@@ -1336,6 +1377,11 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table,
err_with_cleanup:
thd
->
restore_active_arena
(
&
call_arena
,
&
backup_arena
);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
m_security_ctx
.
restore_security_context
(
thd
,
save_ctx
);
#endif // NO_EMBEDDED_ACCESS_CHECKS
delete
nctx
;
call_arena
.
free_items
();
free_root
(
&
call_mem_root
,
MYF
(
0
));
...
...
sql/sp_head.h
View file @
d098bfff
...
...
@@ -216,8 +216,10 @@ public:
destroy
();
bool
execute_trigger
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table
,
GRANT_INFO
*
grant_onfo
);
execute_trigger
(
THD
*
thd
,
const
LEX_STRING
*
db_name
,
const
LEX_STRING
*
table_name
,
GRANT_INFO
*
grant_info
);
bool
execute_function
(
THD
*
thd
,
Item
**
args
,
uint
argcount
,
Field
*
return_fld
);
...
...
sql/sql_class.cc
View file @
d098bfff
...
...
@@ -342,7 +342,8 @@ THD::THD()
in_lock_tables
(
0
),
bootstrap
(
0
),
derived_tables_processing
(
FALSE
),
spcont
(
NULL
)
spcont
(
NULL
),
m_lip
(
NULL
)
{
ulong
tmp
;
...
...
sql/sql_db.cc
View file @
d098bfff
...
...
@@ -538,6 +538,37 @@ bool load_db_opt_by_name(THD *thd, const char *db_name,
}
/**
Return default database collation.
@param thd Thread context.
@param db_name Database name.
@return CHARSET_INFO object. The operation always return valid character
set, even if the database does not exist.
*/
CHARSET_INFO
*
get_default_db_collation
(
THD
*
thd
,
const
char
*
db_name
)
{
HA_CREATE_INFO
db_info
;
if
(
thd
->
db
!=
NULL
&&
strcmp
(
db_name
,
thd
->
db
)
==
0
)
return
thd
->
db_charset
;
load_db_opt_by_name
(
thd
,
db_name
,
&
db_info
);
/*
NOTE: even if load_db_opt_by_name() fails,
db_info.default_table_charset contains valid character set
(collation_server). We should not fail if load_db_opt_by_name() fails,
because it is valid case. If a database has been created just by
"mkdir", it does not contain db.opt file, but it is valid database.
*/
return
db_info
.
default_table_charset
;
}
/*
Create a database
...
...
@@ -751,10 +782,8 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
if
((
error
=
write_db_opt
(
thd
,
path
,
create_info
)))
goto
exit
;
/*
Change options if current database is being altered
TODO: Delete this code
*/
/* Change options if current database is being altered. */
if
(
thd
->
db
&&
!
strcmp
(
thd
->
db
,
db
))
{
thd
->
db_charset
=
create_info
->
default_table_charset
?
...
...
@@ -1358,6 +1387,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
Security_context
*
sctx
=
thd
->
security_ctx
;
ulong
db_access
=
sctx
->
db_access
;
CHARSET_INFO
*
db_default_cl
;
DBUG_ENTER
(
"mysql_change_db"
);
DBUG_PRINT
(
"enter"
,(
"name: '%s'"
,
new_db_name
->
str
));
...
...
@@ -1487,16 +1517,9 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
attributes and will be freed in THD::~THD().
*/
{
HA_CREATE_INFO
db_options
;
db_default_cl
=
get_default_db_collation
(
thd
,
new_db_file_name
.
str
);
load_db_opt_by_name
(
thd
,
new_db_name
->
str
,
&
db_options
);
mysql_change_db_impl
(
thd
,
&
new_db_file_name
,
db_access
,
db_options
.
default_table_charset
?
db_options
.
default_table_charset
:
thd
->
variables
.
collation_server
);
}
mysql_change_db_impl
(
thd
,
&
new_db_file_name
,
db_access
,
db_default_cl
);
DBUG_RETURN
(
FALSE
);
}
...
...
sql/sql_parse.cc
View file @
d098bfff
...
...
@@ -5343,12 +5343,11 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
sp_cache_flush_obsolete
(
&
thd
->
sp_func_cache
);
Lex_input_stream
lip
(
thd
,
inBuf
,
length
);
thd
->
m_lip
=
&
lip
;
int
err
=
MYSQLparse
(
thd
);
bool
err
=
parse_sql
(
thd
,
&
lip
);
*
found_semicolon
=
lip
.
found_semicolon
;
if
(
!
err
&&
!
thd
->
is_fatal_error
)
if
(
!
err
)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
mqh_used
&&
thd
->
user_connect
&&
...
...
@@ -5371,8 +5370,8 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
PROCESSLIST.
Note that we don't need LOCK_thread_count to modify query_length.
*/
if
(
lip
.
found_semicolon
&&
(
thd
->
query_length
=
(
ulong
)(
lip
.
found_semicolon
-
thd
->
query
)))
if
(
*
found_semicolon
&&
(
thd
->
query_length
=
(
ulong
)(
*
found_semicolon
-
thd
->
query
)))
thd
->
query_length
--
;
/* Actually execute the query */
mysql_execute_command
(
thd
);
...
...
@@ -5426,12 +5425,10 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
DBUG_ENTER
(
"mysql_test_parse_for_slave"
);
Lex_input_stream
lip
(
thd
,
inBuf
,
length
);
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
mysql_reset_thd_for_next_command
(
thd
);
int
err
=
MYSQLparse
((
void
*
)
thd
);
if
(
!
err
&&
!
thd
->
is_fatal_error
&&
if
(
!
parse_sql
(
thd
,
&
lip
)
&&
all_tables_not_ok
(
thd
,(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
))
error
=
1
;
/* Ignore question */
thd
->
end_statement
();
...
...
@@ -7123,3 +7120,34 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg,
my_error
(
ER_WRONG_STRING_LENGTH
,
MYF
(
0
),
str
->
str
,
err_msg
,
max_char_length
);
return
TRUE
;
}
extern
int
MYSQLparse
(
void
*
thd
);
// from sql_yacc.cc
/**
This is a wrapper of MYSQLparse(). All the code should call parse_sql()
instead of MYSQLparse().
@param thd Thread context.
@param lip Lexer context.
@return Error status.
@retval FALSE on success.
@retval TRUE on parsing error.
*/
bool
parse_sql
(
THD
*
thd
,
Lex_input_stream
*
lip
)
{
bool
err_status
;
DBUG_ASSERT
(
thd
->
m_lip
==
NULL
);
thd
->
m_lip
=
lip
;
err_status
=
MYSQLparse
(
thd
)
!=
0
||
thd
->
is_fatal_error
;
thd
->
m_lip
=
NULL
;
return
err_status
;
}
sql/sql_partition.cc
View file @
d098bfff
...
...
@@ -3696,7 +3696,6 @@ bool mysql_unpack_partition(THD *thd,
thd
->
variables
.
character_set_client
=
system_charset_info
;
Lex_input_stream
lip
(
thd
,
part_buf
,
part_info_len
);
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
/*
...
...
@@ -3725,7 +3724,7 @@ bool mysql_unpack_partition(THD *thd,
lex
.
part_info
->
part_state
=
part_state
;
lex
.
part_info
->
part_state_len
=
part_state_len
;
DBUG_PRINT
(
"info"
,
(
"Parse: %s"
,
part_buf
));
if
(
MYSQLparse
((
void
*
)
thd
)
||
thd
->
is_fatal_error
)
if
(
parse_sql
(
thd
,
&
lip
)
)
{
thd
->
free_items
();
goto
end
;
...
...
sql/sql_prepare.cc
View file @
d098bfff
...
...
@@ -2858,12 +2858,11 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
Lex_input_stream
lip
(
thd
,
thd
->
query
,
thd
->
query_length
);
lip
.
stmt_prepare_mode
=
TRUE
;
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
int
err
=
MYSQLparse
((
void
*
)
thd
);
error
=
err
||
thd
->
is_fatal_error
||
thd
->
net
.
report_error
||
init_param_array
(
this
);
error
=
parse_sql
(
thd
,
&
lip
)
||
thd
->
net
.
report_error
||
init_param_array
(
this
);
/*
While doing context analysis of the query (in check_prepared_statement)
...
...
sql/sql_trigger.cc
View file @
d098bfff
...
...
@@ -23,7 +23,7 @@
static
const
LEX_STRING
triggers_file_type
=
{
C_STRING_WITH_LEN
(
"TRIGGERS"
)
};
const
char
*
const
triggers_file_ext
=
".TRG"
;
const
char
*
const
TRG_EXT
=
".TRG"
;
/*
Table of .TRG file field descriptors.
...
...
@@ -79,7 +79,7 @@ struct st_trigname
static
const
LEX_STRING
trigname_file_type
=
{
C_STRING_WITH_LEN
(
"TRIGGERNAME"
)
};
const
char
*
const
trigname_file_ext
=
".TRN"
;
const
char
*
const
TRN_EXT
=
".TRN"
;
static
File_option
trigname_file_parameters
[]
=
{
...
...
@@ -132,6 +132,7 @@ private:
LEX_STRING
*
trigger_table_value
;
};
/*
Create or drop trigger for table.
...
...
@@ -463,14 +464,14 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
sql_create_definition_file() files handles renaming and backup of older
versions
*/
file
.
length
=
build_table_filename
(
file_buff
,
FN_REFLEN
-
1
,
file
.
length
=
build_table_filename
(
file_buff
,
FN_REFLEN
-
1
,
tables
->
db
,
tables
->
table_name
,
triggers_file_ext
,
0
);
TRG_EXT
,
0
);
file
.
str
=
file_buff
;
trigname_file
.
length
=
build_table_filename
(
trigname_buff
,
FN_REFLEN
-
1
,
tables
->
db
,
lex
->
spname
->
m_name
.
str
,
trigname_file_ext
,
0
);
TRN_EXT
,
0
);
trigname_file
.
str
=
trigname_buff
;
/* Use the filesystem to enforce trigger namespace constraints. */
...
...
@@ -604,7 +605,7 @@ err_with_cleanup:
static
bool
rm_trigger_file
(
char
*
path
,
const
char
*
db
,
const
char
*
table_name
)
{
build_table_filename
(
path
,
FN_REFLEN
-
1
,
db
,
table_name
,
triggers_file_ext
,
0
);
build_table_filename
(
path
,
FN_REFLEN
-
1
,
db
,
table_name
,
TRG_EXT
,
0
);
return
my_delete
(
path
,
MYF
(
MY_WME
));
}
...
...
@@ -627,8 +628,7 @@ static bool rm_trigger_file(char *path, const char *db,
static
bool
rm_trigname_file
(
char
*
path
,
const
char
*
db
,
const
char
*
trigger_name
)
{
build_table_filename
(
path
,
FN_REFLEN
-
1
,
db
,
trigger_name
,
trigname_file_ext
,
0
);
build_table_filename
(
path
,
FN_REFLEN
-
1
,
db
,
trigger_name
,
TRN_EXT
,
0
);
return
my_delete
(
path
,
MYF
(
MY_WME
));
}
...
...
@@ -653,8 +653,8 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db,
char
file_buff
[
FN_REFLEN
];
LEX_STRING
file
;
file
.
length
=
build_table_filename
(
file_buff
,
FN_REFLEN
-
1
,
db
,
table_name
,
triggers_file_ext
,
0
);
file
.
length
=
build_table_filename
(
file_buff
,
FN_REFLEN
-
1
,
db
,
table_name
,
TRG_EXT
,
0
);
file
.
str
=
file_buff
;
return
sql_create_definition_file
(
NULL
,
&
file
,
&
triggers_file_type
,
(
uchar
*
)
triggers
,
triggers_file_parameters
,
...
...
@@ -834,8 +834,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
DBUG_ENTER
(
"Table_triggers_list::check_n_load"
);
path
.
length
=
build_table_filename
(
path_buff
,
FN_REFLEN
-
1
,
db
,
table_name
,
triggers_file_ext
,
0
);
path
.
length
=
build_table_filename
(
path_buff
,
FN_REFLEN
-
1
,
db
,
table_name
,
TRG_EXT
,
0
);
path
.
str
=
path_buff
;
// QQ: should we analyze errno somehow ?
...
...
@@ -981,12 +981,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd
->
variables
.
sql_mode
=
(
ulong
)
*
trg_sql_mode
;
Lex_input_stream
lip
(
thd
,
trg_create_str
->
str
,
trg_create_str
->
length
);
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
thd
->
spcont
=
0
;
int
err
=
MYSQLparse
((
void
*
)
thd
);
if
(
err
||
thd
->
is_fatal_error
)
if
(
parse_sql
(
thd
,
&
lip
)
)
{
/* Currently sphead is always deleted in case of a parse error */
DBUG_ASSERT
(
lex
.
sphead
==
0
);
...
...
@@ -1108,7 +1106,7 @@ err_with_lex_cleanup:
be merged into .FRM anyway.
*/
my_error
(
ER_WRONG_OBJECT
,
MYF
(
0
),
table_name
,
triggers_file_ext
+
1
,
"TRIGGER"
);
table_name
,
TRG_EXT
+
1
,
"TRIGGER"
);
DBUG_RETURN
(
1
);
}
...
...
@@ -1168,43 +1166,38 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
}
/*
/*
*
Find trigger's table from trigger identifier and add it to
the statement table list.
SYNOPSIS
mysql_table_for_trigger()
thd - current thread context
trig - identifier for trigger
if_exists - treat a not existing trigger as a warning if TRUE
table - pointer to TABLE_LIST object for the table trigger (output)
RETURN VALUE
0 Success
1 Error
@param[in] thd Thread context.
@param[in] trg_name Trigger name.
@param[in] if_exists TRUE if SQL statement contains "IF EXISTS" clause.
That means a warning instead of error should be
thrown if trigger with given name does not exist.
@param[out] table Pointer to TABLE_LIST object for the
table trigger.
@return Operation status
@retval FALSE On success.
@retval TRUE Otherwise.
*/
int
add_table_for_trigger
(
THD
*
thd
,
sp_name
*
trig
,
bool
if_exists
,
bool
add_table_for_trigger
(
THD
*
thd
,
sp_name
*
trg_name
,
bool
if_exists
,
TABLE_LIST
**
table
)
{
LEX
*
lex
=
thd
->
lex
;
char
path_buff
[
FN_REFLEN
];
LEX_STRING
path
;
File_parser
*
parser
;
struct
st_trigname
trigname
;
Handle_old_incorrect_trigger_table_hook
trigger_table_hook
(
path_buff
,
&
trigname
.
trigger_table
);
char
trn_path_buff
[
FN_REFLEN
];
LEX_STRING
trn_path
=
{
trn_path_buff
,
0
};
LEX_STRING
tbl_name
;
DBUG_ENTER
(
"add_table_for_trigger"
);
DBUG_ASSERT
(
table
!=
NULL
);
path
.
length
=
build_table_filename
(
path_buff
,
FN_REFLEN
-
1
,
trig
->
m_db
.
str
,
trig
->
m_name
.
str
,
trigname_file_ext
,
0
);
path
.
str
=
path_buff
;
build_trn_path
(
thd
,
trg_name
,
&
trn_path
);
if
(
access
(
path_buff
,
F_OK
))
if
(
check_trn_exists
(
&
trn_path
))
{
if
(
if_exists
)
{
...
...
@@ -1212,39 +1205,27 @@ add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
MYSQL_ERROR
::
WARN_LEVEL_NOTE
,
ER_TRG_DOES_NOT_EXIST
,
ER
(
ER_TRG_DOES_NOT_EXIST
));
*
table
=
NULL
;
DBUG_RETURN
(
0
);
}
my_error
(
ER_TRG_DOES_NOT_EXIST
,
MYF
(
0
));
DBUG_RETURN
(
1
);
DBUG_RETURN
(
FALSE
);
}
if
(
!
(
parser
=
sql_parse_prepare
(
&
path
,
thd
->
mem_root
,
1
)))
DBUG_RETURN
(
1
);
if
(
!
is_equal
(
&
trigname_file_type
,
parser
->
type
()))
{
my_error
(
ER_WRONG_OBJECT
,
MYF
(
0
),
trig
->
m_name
.
str
,
trigname_file_ext
+
1
,
"TRIGGERNAME"
);
DBUG_RETURN
(
1
);
my_error
(
ER_TRG_DOES_NOT_EXIST
,
MYF
(
0
));
DBUG_RETURN
(
TRUE
);
}
if
(
parser
->
parse
((
uchar
*
)
&
trigname
,
thd
->
mem_root
,
trigname_file_parameters
,
1
,
&
trigger_table_hook
))
DBUG_RETURN
(
1
);
if
(
load_table_name_for_trigger
(
thd
,
trg_name
,
&
trn_path
,
&
tbl_name
))
DBUG_RETURN
(
TRUE
);
/* We need to reset statement table list to be PS/SP friendly. */
lex
->
query_tables
=
0
;
lex
->
query_tables_last
=
&
lex
->
query_tables
;
*
table
=
sp_add_to_query_tables
(
thd
,
lex
,
trig
->
m_db
.
str
,
trigname
.
trigger_table
.
str
,
TL_IGNORE
);
if
(
!
*
table
)
DBUG_RETURN
(
1
);
*
table
=
sp_add_to_query_tables
(
thd
,
lex
,
trg_name
->
m_db
.
str
,
tbl_name
.
str
,
TL_IGNORE
);
DBUG_RETURN
(
0
);
DBUG_RETURN
(
*
table
?
FALSE
:
TRUE
);
}
...
...
@@ -1428,7 +1409,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name,
{
trigname_file
.
length
=
build_table_filename
(
trigname_buff
,
FN_REFLEN
-
1
,
db_name
,
trigger
->
str
,
trigname_file_ext
,
0
);
TRN_EXT
,
0
);
trigname_file
.
str
=
trigname_buff
;
trigname
.
trigger_table
=
*
new_table_name
;
...
...
@@ -1537,17 +1518,33 @@ end:
}
bool
Table_triggers_list
::
process_triggers
(
THD
*
thd
,
trg_event_type
event
,
/**
Execute trigger for given (event, time) pair.
The operation executes trigger for the specified event (insert, update,
delete) and time (after, before) if it is set.
@param thd
@param event
@param time_type,
@param old_row_is_record1
@return Error status.
@retval FALSE on success.
@retval TRUE on error.
*/
bool
Table_triggers_list
::
process_triggers
(
THD
*
thd
,
trg_event_type
event
,
trg_action_time_type
time_type
,
bool
old_row_is_record1
)
{
bool
err_status
=
FALSE
;
sp_head
*
sp_trigger
=
bodies
[
event
][
time_type
];
if
(
sp_trigger
)
{
bool
err_status
;
Sub_statement_state
statement_state
;
if
(
!
bodies
[
event
][
time_type
])
return
FALSE
;
if
(
old_row_is_record1
)
{
old_field
=
record1_field
;
...
...
@@ -1558,56 +1555,17 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
new_field
=
record1_field
;
old_field
=
trigger_table
->
field
;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Security_context
*
sctx
=
&
sp_trigger
->
m_security_ctx
;
Security_context
*
save_ctx
=
NULL
;
if
(
sp_trigger
->
m_chistics
->
suid
!=
SP_IS_NOT_SUID
&&
sctx
->
change_security_context
(
thd
,
&
sp_trigger
->
m_definer_user
,
&
sp_trigger
->
m_definer_host
,
&
sp_trigger
->
m_db
,
&
save_ctx
))
return
TRUE
;
/*
Fetch information about table-level privileges to GRANT_INFO structure for
subject table. Check of privileges that will use it and information about
column-level privileges will happen in Item_trigger_field::fix_fields().
*/
fill_effective_table_privileges
(
thd
,
&
subject_table_grants
[
event
][
time_type
],
trigger_table
->
s
->
db
.
str
,
trigger_table
->
s
->
table_name
.
str
);
/* Check that the definer has TRIGGER privilege on the subject table. */
if
(
!
(
subject_table_grants
[
event
][
time_type
].
privilege
&
TRIGGER_ACL
))
{
char
priv_desc
[
128
];
get_privilege_desc
(
priv_desc
,
sizeof
(
priv_desc
),
TRIGGER_ACL
);
my_error
(
ER_TABLEACCESS_DENIED_ERROR
,
MYF
(
0
),
priv_desc
,
thd
->
security_ctx
->
priv_user
,
thd
->
security_ctx
->
host_or_ip
,
trigger_table
->
s
->
table_name
.
str
);
sctx
->
restore_security_context
(
thd
,
save_ctx
);
return
TRUE
;
}
#endif // NO_EMBEDDED_ACCESS_CHECKS
thd
->
reset_sub_statement_state
(
&
statement_state
,
SUB_STMT_TRIGGER
);
err_status
=
sp_trigger
->
execute_trigger
(
thd
,
trigger_table
->
s
->
db
.
str
,
trigger_table
->
s
->
table_name
.
str
,
err_status
=
bodies
[
event
][
time_type
]
->
execute_trigger
(
thd
,
&
trigger_table
->
s
->
db
,
&
trigger_table
->
s
->
table_name
,
&
subject_table_grants
[
event
][
time_type
]);
thd
->
restore_sub_statement_state
(
&
statement_state
);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
sctx
->
restore_security_context
(
thd
,
save_ctx
);
#endif // NO_EMBEDDED_ACCESS_CHECKS
}
thd
->
restore_sub_statement_state
(
&
statement_state
);
return
err_status
;
}
...
...
@@ -1749,3 +1707,95 @@ process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root,
}
DBUG_RETURN
(
FALSE
);
}
/**
Contruct path to TRN-file.
@param thd[in] Thread context.
@param trg_name[in] Trigger name.
@param trn_path[out] Variable to store constructed path
*/
void
build_trn_path
(
THD
*
thd
,
const
sp_name
*
trg_name
,
LEX_STRING
*
trn_path
)
{
/* Construct path to the TRN-file. */
trn_path
->
length
=
build_table_filename
(
trn_path
->
str
,
FN_REFLEN
-
1
,
trg_name
->
m_db
.
str
,
trg_name
->
m_name
.
str
,
TRN_EXT
,
0
);
}
/**
Check if TRN-file exists.
@return
@retval TRUE if TRN-file does not exist.
@retval FALSE if TRN-file exists.
*/
bool
check_trn_exists
(
const
LEX_STRING
*
trn_path
)
{
return
access
(
trn_path
->
str
,
F_OK
)
!=
0
;
}
/**
Retrieve table name for given trigger.
@param thd[in] Thread context.
@param trg_name[in] Trigger name.
@param trn_path[in] Path to the corresponding TRN-file.
@param tbl_name[out] Variable to store retrieved table name.
@return Error status.
@retval FALSE on success.
@retval TRUE if table name could not be retrieved.
*/
bool
load_table_name_for_trigger
(
THD
*
thd
,
const
sp_name
*
trg_name
,
const
LEX_STRING
*
trn_path
,
LEX_STRING
*
tbl_name
)
{
File_parser
*
parser
;
struct
st_trigname
trn_data
;
Handle_old_incorrect_trigger_table_hook
trigger_table_hook
(
trn_path
->
str
,
&
trn_data
.
trigger_table
);
DBUG_ENTER
(
"load_table_name_for_trigger"
);
/* Parse the TRN-file. */
if
(
!
(
parser
=
sql_parse_prepare
(
trn_path
,
thd
->
mem_root
,
TRUE
)))
DBUG_RETURN
(
TRUE
);
if
(
!
is_equal
(
&
trigname_file_type
,
parser
->
type
()))
{
my_error
(
ER_WRONG_OBJECT
,
MYF
(
0
),
trg_name
->
m_name
.
str
,
TRN_EXT
+
1
,
"TRIGGERNAME"
);
DBUG_RETURN
(
TRUE
);
}
if
(
parser
->
parse
((
uchar
*
)
&
trn_data
,
thd
->
mem_root
,
trigname_file_parameters
,
1
,
&
trigger_table_hook
))
DBUG_RETURN
(
TRUE
);
/* Copy trigger table name. */
*
tbl_name
=
trn_data
.
trigger_table
;
/* That's all. */
DBUG_RETURN
(
FALSE
);
}
sql/sql_trigger.h
View file @
d098bfff
...
...
@@ -17,7 +17,7 @@
/*
This class holds all information about triggers of table.
QQ: Will it be merged into TABLE in future ?
QQ: Will it be merged into TABLE in
the
future ?
*/
class
Table_triggers_list
:
public
Sql_alloc
...
...
@@ -143,6 +143,17 @@ private:
extern
const
LEX_STRING
trg_action_time_type_names
[];
extern
const
LEX_STRING
trg_event_type_names
[];
int
add_table_for_trigger
(
THD
*
thd
,
sp_name
*
trig
,
bool
if_exists
,
bool
add_table_for_trigger
(
THD
*
thd
,
sp_name
*
trg_name
,
bool
continue_if_not_exist
,
TABLE_LIST
**
table
);
void
build_trn_path
(
THD
*
thd
,
const
sp_name
*
trg_name
,
LEX_STRING
*
trn_path
);
bool
check_trn_exists
(
const
LEX_STRING
*
trn_path
);
bool
load_table_name_for_trigger
(
THD
*
thd
,
const
sp_name
*
trg_name
,
const
LEX_STRING
*
trn_path
,
LEX_STRING
*
tbl_name
);
sql/sql_view.cc
View file @
d098bfff
...
...
@@ -893,7 +893,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
LEX
*
old_lex
,
*
lex
;
Query_arena
*
arena
,
backup
;
TABLE_LIST
*
top_view
=
table
->
top_table
();
int
res
;
bool
res
;
bool
result
,
view_is_mergeable
;
TABLE_LIST
*
view_main_select_tables
;
DBUG_ENTER
(
"mysql_make_view"
);
...
...
@@ -1005,7 +1005,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
{
Lex_input_stream
lip
(
thd
,
table
->
query
.
str
,
table
->
query
.
length
);
thd
->
m_lip
=
&
lip
;
lex_start
(
thd
);
view_select
=
&
lex
->
select_lex
;
view_select
->
select_number
=
++
thd
->
select_number
;
...
...
@@ -1039,7 +1038,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
MODE_IGNORE_SPACE
|
MODE_NO_BACKSLASH_ESCAPES
);
CHARSET_INFO
*
save_cs
=
thd
->
variables
.
character_set_client
;
thd
->
variables
.
character_set_client
=
system_charset_info
;
res
=
MYSQLparse
((
void
*
)
thd
);
res
=
parse_sql
(
thd
,
&
lip
);
if
((
old_lex
->
sql_command
==
SQLCOM_SHOW_FIELDS
)
||
(
old_lex
->
sql_command
==
SQLCOM_SHOW_CREATE
))
...
...
@@ -1048,7 +1047,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
thd
->
variables
.
character_set_client
=
save_cs
;
thd
->
variables
.
sql_mode
=
save_mode
;
}
if
(
!
res
&&
!
thd
->
is_fatal_error
)
if
(
!
res
)
{
TABLE_LIST
*
view_tables
=
lex
->
query_tables
;
TABLE_LIST
*
view_tables_tail
=
0
;
...
...
sql/sql_yacc.yy
View file @
d098bfff
...
...
@@ -1873,9 +1873,6 @@ ev_sql_stmt:
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lip->get_cpp_ptr();
lex->event_parse_data->body_begin= lip->get_cpp_ptr();
}
ev_sql_stmt_inner
{
...
...
@@ -1888,7 +1885,7 @@ ev_sql_stmt:
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
lex->event_parse_data->
init_body(thd)
;
lex->event_parse_data->
body_changed= TRUE
;
}
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment