mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge adventure.(none):/home/thek/Development/cpp/bug29929/my50-bug29929
into adventure.(none):/home/thek/Development/cpp/bug29929/my51-bug29929 mysql-test/r/sp-prelocking.result: Auto merged mysql-test/t/sp-prelocking.test: Auto merged sql/sql_lex.cc: Auto merged sql/table.cc: Auto merged sql/table.h: SCCS merged
This commit is contained in:
135
sql/sql_lex.cc
135
sql/sql_lex.cc
@@ -2367,12 +2367,131 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl)
|
||||
|
||||
|
||||
/**
|
||||
Update the parsed tree with information about triggers that
|
||||
may be fired when executing this statement.
|
||||
@brief Set the initial purpose of this TABLE_LIST object in the list of used
|
||||
tables.
|
||||
|
||||
We need to track this information on table-by-table basis, since when this
|
||||
table becomes an element of the pre-locked list, it's impossible to identify
|
||||
which SQL sub-statement it has been originally used in.
|
||||
|
||||
E.g.:
|
||||
|
||||
User request: SELECT * FROM t1 WHERE f1();
|
||||
FUNCTION f1(): DELETE FROM t2; RETURN 1;
|
||||
BEFORE DELETE trigger on t2: INSERT INTO t3 VALUES (old.a);
|
||||
|
||||
For this user request, the pre-locked list will contain t1, t2, t3
|
||||
table elements, each needed for different DML.
|
||||
|
||||
The trigger event map is updated to reflect INSERT, UPDATE, DELETE,
|
||||
REPLACE, LOAD DATA, CREATE TABLE .. SELECT, CREATE TABLE ..
|
||||
REPLACE SELECT statements, and additionally ON DUPLICATE KEY UPDATE
|
||||
clause.
|
||||
*/
|
||||
|
||||
void st_lex::set_trg_event_type_for_tables()
|
||||
{
|
||||
enum trg_event_type trg_event;
|
||||
|
||||
uint8 new_trg_event_map= 0;
|
||||
|
||||
/*
|
||||
Some auxiliary operations
|
||||
(e.g. GRANT processing) create TABLE_LIST instances outside
|
||||
the parser. Additionally, some commands (e.g. OPTIMIZE) change
|
||||
the lock type for a table only after parsing is done. Luckily,
|
||||
these do not fire triggers and do not need to pre-load them.
|
||||
For these TABLE_LISTs set_trg_event_type is never called, and
|
||||
trg_event_map is always empty. That means that the pre-locking
|
||||
algorithm will ignore triggers defined on these tables, if
|
||||
any, and the execution will either fail with an assert in
|
||||
sql_trigger.cc or with an error that a used table was not
|
||||
pre-locked, in case of a production build.
|
||||
|
||||
TODO: this usage pattern creates unnecessary module dependencies
|
||||
and should be rewritten to go through the parser.
|
||||
Table list instances created outside the parser in most cases
|
||||
refer to mysql.* system tables. It is not allowed to have
|
||||
a trigger on a system table, but keeping track of
|
||||
initialization provides extra safety in case this limitation
|
||||
is circumvented.
|
||||
*/
|
||||
|
||||
switch (sql_command) {
|
||||
case SQLCOM_LOCK_TABLES:
|
||||
/*
|
||||
On a LOCK TABLE, all triggers must be pre-loaded for this TABLE_LIST
|
||||
when opening an associated TABLE.
|
||||
*/
|
||||
new_trg_event_map= static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_INSERT)) |
|
||||
static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_UPDATE)) |
|
||||
static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_DELETE));
|
||||
break;
|
||||
/*
|
||||
Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE
|
||||
clause, it will be handled later in this method.
|
||||
*/
|
||||
case SQLCOM_INSERT: /* fall through */
|
||||
case SQLCOM_INSERT_SELECT:
|
||||
/*
|
||||
LOAD DATA ... INFILE is expected to fire BEFORE/AFTER INSERT
|
||||
triggers.
|
||||
If the statement also has REPLACE clause, it will be
|
||||
handled later in this method.
|
||||
*/
|
||||
case SQLCOM_LOAD: /* fall through */
|
||||
/*
|
||||
REPLACE is semantically equivalent to INSERT. In case
|
||||
of a primary or unique key conflict, it deletes the old
|
||||
record and inserts a new one. So we also may need to
|
||||
fire ON DELETE triggers. This functionality is handled
|
||||
later in this method.
|
||||
*/
|
||||
case SQLCOM_REPLACE: /* fall through */
|
||||
case SQLCOM_REPLACE_SELECT:
|
||||
/*
|
||||
CREATE TABLE ... SELECT defaults to INSERT if the table or
|
||||
view already exists. REPLACE option of CREATE TABLE ...
|
||||
REPLACE SELECT is handled later in this method.
|
||||
*/
|
||||
case SQLCOM_CREATE_TABLE:
|
||||
new_trg_event_map|= static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_INSERT));
|
||||
break;
|
||||
/* Basic update and multi-update */
|
||||
case SQLCOM_UPDATE: /* fall through */
|
||||
case SQLCOM_UPDATE_MULTI:
|
||||
new_trg_event_map|= static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_UPDATE));
|
||||
break;
|
||||
/* Basic delete and multi-delete */
|
||||
case SQLCOM_DELETE: /* fall through */
|
||||
case SQLCOM_DELETE_MULTI:
|
||||
new_trg_event_map|= static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_DELETE));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (duplicates) {
|
||||
case DUP_UPDATE:
|
||||
new_trg_event_map|= static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_UPDATE));
|
||||
break;
|
||||
case DUP_REPLACE:
|
||||
new_trg_event_map|= static_cast<uint8>
|
||||
(1 << static_cast<int>(TRG_EVENT_DELETE));
|
||||
break;
|
||||
case DUP_ERROR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Do not iterate over sub-selects, only the tables in the outermost
|
||||
SELECT_LEX can be modified, if any.
|
||||
@@ -2381,7 +2500,17 @@ void st_lex::set_trg_event_type_for_tables()
|
||||
|
||||
while (tables)
|
||||
{
|
||||
tables->set_trg_event_type(this);
|
||||
/*
|
||||
This is a fast check to filter out statements that do
|
||||
not change data, or tables on the right side, in case of
|
||||
INSERT .. SELECT, CREATE TABLE .. SELECT and so on.
|
||||
Here we also filter out OPTIMIZE statement and non-updateable
|
||||
views, for which lock_type is TL_UNLOCK or TL_READ after
|
||||
parsing.
|
||||
*/
|
||||
if (static_cast<int>(tables->lock_type) >=
|
||||
static_cast<int>(TL_WRITE_ALLOW_WRITE))
|
||||
tables->trg_event_map= new_trg_event_map;
|
||||
tables= tables->next_local;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user