2005-07-09 19:51:59 +02:00
|
|
|
/* Copyright (C) 2004-2005 MySQL AB
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2005-07-09 19:51:59 +02:00
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
|
|
|
2006-03-10 01:44:08 +01:00
|
|
|
#define MYSQL_LEX 1
|
2004-09-07 14:29:46 +02:00
|
|
|
#include "mysql_priv.h"
|
|
|
|
#include "sp_head.h"
|
|
|
|
#include "sql_trigger.h"
|
|
|
|
#include "parse_file.h"
|
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline T *alloc_type(MEM_ROOT *m)
|
|
|
|
{
|
|
|
|
return (T *) alloc_root(m, sizeof (T));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
NOTE: Since alloc_type() is declared as inline, alloc_root() calls should
|
|
|
|
be inlined by the compiler. So, implementation of alloc_root() is not
|
|
|
|
needed. However, let's put the implementation in object file just in case
|
|
|
|
of stupid MS or other old compilers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template LEX_STRING *alloc_type<LEX_STRING>(MEM_ROOT *m);
|
|
|
|
template ulonglong *alloc_type<ulonglong>(MEM_ROOT *m);
|
|
|
|
|
|
|
|
inline LEX_STRING *alloc_lex_string(MEM_ROOT *m)
|
|
|
|
{
|
|
|
|
return alloc_type<LEX_STRING>(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/**
|
|
|
|
Trigger_creation_ctx -- creation context of triggers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Trigger_creation_ctx : public Stored_program_creation_ctx,
|
|
|
|
public Sql_alloc
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static Trigger_creation_ctx *create(THD *thd,
|
|
|
|
const char *db_name,
|
|
|
|
const char *table_name,
|
|
|
|
const LEX_STRING *client_cs_name,
|
|
|
|
const LEX_STRING *connection_cl_name,
|
|
|
|
const LEX_STRING *db_cl_name);
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual Stored_program_creation_ctx *clone(MEM_ROOT *mem_root)
|
|
|
|
{
|
|
|
|
return new (mem_root) Trigger_creation_ctx(m_client_cs,
|
|
|
|
m_connection_cl,
|
|
|
|
m_db_cl);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual Object_creation_ctx *create_backup_ctx(THD *thd) const
|
|
|
|
{
|
|
|
|
return new Trigger_creation_ctx(thd);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Trigger_creation_ctx(THD *thd)
|
|
|
|
:Stored_program_creation_ctx(thd)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Trigger_creation_ctx(CHARSET_INFO *client_cs,
|
|
|
|
CHARSET_INFO *connection_cl,
|
|
|
|
CHARSET_INFO *db_cl)
|
|
|
|
:Stored_program_creation_ctx(client_cs, connection_cl, db_cl)
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
Trigger_creation_ctx implementation.
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
Trigger_creation_ctx *
|
|
|
|
Trigger_creation_ctx::create(THD *thd,
|
|
|
|
const char *db_name,
|
|
|
|
const char *table_name,
|
|
|
|
const LEX_STRING *client_cs_name,
|
|
|
|
const LEX_STRING *connection_cl_name,
|
|
|
|
const LEX_STRING *db_cl_name)
|
|
|
|
{
|
|
|
|
CHARSET_INFO *client_cs;
|
|
|
|
CHARSET_INFO *connection_cl;
|
|
|
|
CHARSET_INFO *db_cl;
|
|
|
|
|
|
|
|
bool invalid_creation_ctx= FALSE;
|
|
|
|
|
|
|
|
if (resolve_charset(client_cs_name->str,
|
|
|
|
thd->variables.character_set_client,
|
|
|
|
&client_cs))
|
|
|
|
{
|
|
|
|
sql_print_warning("Trigger for table '%s'.'%s': "
|
|
|
|
"invalid character_set_client value (%s).",
|
|
|
|
(const char *) db_name,
|
|
|
|
(const char *) table_name,
|
|
|
|
(const char *) client_cs_name->str);
|
|
|
|
|
|
|
|
invalid_creation_ctx= TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resolve_collation(connection_cl_name->str,
|
|
|
|
thd->variables.collation_connection,
|
|
|
|
&connection_cl))
|
|
|
|
{
|
|
|
|
sql_print_warning("Trigger for table '%s'.'%s': "
|
|
|
|
"invalid collation_connection value (%s).",
|
|
|
|
(const char *) db_name,
|
|
|
|
(const char *) table_name,
|
|
|
|
(const char *) connection_cl_name->str);
|
|
|
|
|
|
|
|
invalid_creation_ctx= TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resolve_collation(db_cl_name->str, NULL, &db_cl))
|
|
|
|
{
|
|
|
|
sql_print_warning("Trigger for table '%s'.'%s': "
|
|
|
|
"invalid database_collation value (%s).",
|
|
|
|
(const char *) db_name,
|
|
|
|
(const char *) table_name,
|
|
|
|
(const char *) db_cl_name->str);
|
|
|
|
|
|
|
|
invalid_creation_ctx= TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (invalid_creation_ctx)
|
|
|
|
{
|
|
|
|
push_warning_printf(thd,
|
|
|
|
MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_TRG_INVALID_CREATION_CTX,
|
|
|
|
ER(ER_TRG_INVALID_CREATION_CTX),
|
|
|
|
(const char *) db_name,
|
|
|
|
(const char *) table_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
If we failed to resolve the database collation, load the default one
|
|
|
|
from the disk.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!db_cl)
|
|
|
|
db_cl= get_default_db_collation(thd, db_name);
|
|
|
|
|
|
|
|
return new Trigger_creation_ctx(client_cs, connection_cl, db_cl);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
static const LEX_STRING triggers_file_type=
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("TRIGGERS") };
|
2005-03-27 14:15:21 +02:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
const char * const TRG_EXT= ".TRG";
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Table of .TRG file field descriptors.
|
|
|
|
We have here only one field now because in nearest future .TRG
|
|
|
|
files will be merged into .FRM files (so we don't need something
|
|
|
|
like md5 or created fields).
|
|
|
|
*/
|
|
|
|
static File_option triggers_file_parameters[]=
|
|
|
|
{
|
2005-11-10 20:25:03 +01:00
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("triggers") },
|
2006-10-20 13:47:52 +02:00
|
|
|
my_offsetof(class Table_triggers_list, definitions_list),
|
2005-11-10 20:25:03 +01:00
|
|
|
FILE_OPTIONS_STRLIST
|
|
|
|
},
|
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("sql_modes") },
|
2006-10-20 13:47:52 +02:00
|
|
|
my_offsetof(class Table_triggers_list, definition_modes_list),
|
2005-11-10 20:25:03 +01:00
|
|
|
FILE_OPTIONS_ULLLIST
|
|
|
|
},
|
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("definers") },
|
2006-10-20 13:47:52 +02:00
|
|
|
my_offsetof(class Table_triggers_list, definers_list),
|
2005-11-10 20:25:03 +01:00
|
|
|
FILE_OPTIONS_STRLIST
|
|
|
|
},
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
{
|
|
|
|
{ C_STRING_WITH_LEN("client_cs_names") },
|
|
|
|
my_offsetof(class Table_triggers_list, client_cs_names),
|
|
|
|
FILE_OPTIONS_STRLIST
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ C_STRING_WITH_LEN("connection_cl_names") },
|
|
|
|
my_offsetof(class Table_triggers_list, connection_cl_names),
|
|
|
|
FILE_OPTIONS_STRLIST
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{ C_STRING_WITH_LEN("db_cl_names") },
|
|
|
|
my_offsetof(class Table_triggers_list, db_cl_names),
|
|
|
|
FILE_OPTIONS_STRLIST
|
|
|
|
},
|
2005-11-10 20:25:03 +01:00
|
|
|
{ { 0, 0 }, 0, FILE_OPTIONS_STRING }
|
2004-09-07 14:29:46 +02:00
|
|
|
};
|
|
|
|
|
2006-01-05 23:47:49 +01:00
|
|
|
File_option sql_modes_parameters=
|
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("sql_modes") },
|
2006-10-20 13:47:52 +02:00
|
|
|
my_offsetof(class Table_triggers_list, definition_modes_list),
|
2006-01-05 23:47:49 +01:00
|
|
|
FILE_OPTIONS_ULLLIST
|
|
|
|
};
|
|
|
|
|
2005-11-10 20:25:03 +01:00
|
|
|
/*
|
|
|
|
This must be kept up to date whenever a new option is added to the list
|
|
|
|
above, as it specifies the number of required parameters of the trigger in
|
|
|
|
.trg file.
|
|
|
|
*/
|
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
static const int TRG_NUM_REQUIRED_PARAMETERS= 6;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
/*
|
|
|
|
Structure representing contents of .TRN file which are used to support
|
|
|
|
database wide trigger namespace.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct st_trigname
|
|
|
|
{
|
|
|
|
LEX_STRING trigger_table;
|
|
|
|
};
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
static const LEX_STRING trigname_file_type=
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("TRIGGERNAME") };
|
2005-07-19 18:06:49 +02:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
const char * const TRN_EXT= ".TRN";
|
2005-07-19 18:06:49 +02:00
|
|
|
|
|
|
|
static File_option trigname_file_parameters[]=
|
|
|
|
{
|
2005-11-10 20:25:03 +01:00
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("trigger_table")},
|
2005-11-10 20:25:03 +01:00
|
|
|
offsetof(struct st_trigname, trigger_table),
|
2006-03-27 23:01:51 +02:00
|
|
|
FILE_OPTIONS_ESTRING
|
2005-11-10 20:25:03 +01:00
|
|
|
},
|
|
|
|
{ { 0, 0 }, 0, FILE_OPTIONS_STRING }
|
2005-07-19 18:06:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const LEX_STRING trg_action_time_type_names[]=
|
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("BEFORE") },
|
|
|
|
{ C_STRING_WITH_LEN("AFTER") }
|
2005-07-19 18:06:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const LEX_STRING trg_event_type_names[]=
|
|
|
|
{
|
2006-08-17 18:13:45 +02:00
|
|
|
{ C_STRING_WITH_LEN("INSERT") },
|
|
|
|
{ C_STRING_WITH_LEN("UPDATE") },
|
|
|
|
{ C_STRING_WITH_LEN("DELETE") }
|
2005-07-19 18:06:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
char *path;
|
|
|
|
public:
|
|
|
|
Handle_old_incorrect_sql_modes_hook(char *file_path)
|
|
|
|
:path(file_path)
|
|
|
|
{};
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
virtual bool process_unknown_string(char *&unknown_key, uchar* base,
|
2005-11-20 19:47:07 +01:00
|
|
|
MEM_ROOT *mem_root, char *end);
|
|
|
|
};
|
2005-07-19 18:06:49 +02:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
|
2006-03-27 23:01:51 +02:00
|
|
|
class Handle_old_incorrect_trigger_table_hook: public Unknown_key_hook
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Handle_old_incorrect_trigger_table_hook(char *file_path,
|
|
|
|
LEX_STRING *trigger_table_arg)
|
|
|
|
:path(file_path), trigger_table_value(trigger_table_arg)
|
|
|
|
{};
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
virtual bool process_unknown_string(char *&unknown_key, uchar* base,
|
2006-03-27 23:01:51 +02:00
|
|
|
MEM_ROOT *mem_root, char *end);
|
|
|
|
private:
|
|
|
|
char *path;
|
|
|
|
LEX_STRING *trigger_table_value;
|
|
|
|
};
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
/*
|
|
|
|
Create or drop trigger for table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
mysql_create_or_drop_trigger()
|
|
|
|
thd - current thread context (including trigger definition in LEX)
|
|
|
|
tables - table list containing one table for which trigger is created.
|
2005-05-06 10:39:30 +02:00
|
|
|
create - whenever we create (TRUE) or drop (FALSE) trigger
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
NOTE
|
|
|
|
This function is mainly responsible for opening and locking of table and
|
|
|
|
invalidation of all its instances in table cache after trigger creation.
|
|
|
|
Real work on trigger creation/dropping is done inside Table_triggers_list
|
|
|
|
methods.
|
|
|
|
|
|
|
|
RETURN VALUE
|
2004-10-20 03:04:37 +02:00
|
|
|
FALSE Success
|
|
|
|
TRUE error
|
2004-09-07 14:29:46 +02:00
|
|
|
*/
|
2004-10-20 03:04:37 +02:00
|
|
|
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
/*
|
|
|
|
FIXME: The code below takes too many different paths depending on the
|
|
|
|
'create' flag, so that the justification for a single function
|
|
|
|
'mysql_create_or_drop_trigger', compared to two separate functions
|
|
|
|
'mysql_create_trigger' and 'mysql_drop_trigger' is not apparent.
|
|
|
|
This is a good candidate for a minor refactoring.
|
|
|
|
*/
|
2004-09-07 14:29:46 +02:00
|
|
|
TABLE *table;
|
2005-10-17 20:37:24 +02:00
|
|
|
bool result= TRUE;
|
2006-08-24 16:48:26 +02:00
|
|
|
String stmt_query;
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_ENTER("mysql_create_or_drop_trigger");
|
|
|
|
|
2006-08-24 16:48:26 +02:00
|
|
|
/* Charset of the buffer for statement must be system one. */
|
|
|
|
stmt_query.set_charset(system_charset_info);
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
/*
|
|
|
|
QQ: This function could be merged in mysql_alter_table() function
|
|
|
|
But do we want this ?
|
|
|
|
*/
|
|
|
|
|
2005-12-11 13:26:15 +01:00
|
|
|
/*
|
|
|
|
Note that once we will have check for TRIGGER privilege in place we won't
|
|
|
|
need second part of condition below, since check_access() function also
|
|
|
|
checks that db is specified.
|
|
|
|
*/
|
|
|
|
if (!thd->lex->spname->m_db.length || create && !tables->db_length)
|
|
|
|
{
|
|
|
|
my_error(ER_NO_DB_ERROR, MYF(0));
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
|
2006-06-28 02:16:02 +02:00
|
|
|
/*
|
|
|
|
We don't allow creating triggers on tables in the 'mysql' schema
|
|
|
|
*/
|
|
|
|
if (create && !my_strcasecmp(system_charset_info, "mysql", tables->db))
|
|
|
|
{
|
|
|
|
my_error(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA, MYF(0));
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
/*
|
2005-10-17 20:37:24 +02:00
|
|
|
There is no DETERMINISTIC clause for triggers, so can't check it.
|
|
|
|
But a trigger can in theory be used to do nasty things (if it supported
|
|
|
|
DROP for example) so we do the check for privileges. For now there is
|
|
|
|
already a stronger test right above; but when this stronger test will
|
2005-11-10 17:50:51 +01:00
|
|
|
be removed, the test below will hold. Because triggers have the same
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
nature as functions regarding binlogging: their body is implicitly
|
2005-11-10 17:50:51 +01:00
|
|
|
binlogged, so they share the same danger, so trust_function_creators
|
|
|
|
applies to them too.
|
2004-09-07 14:29:46 +02:00
|
|
|
*/
|
2005-11-10 17:50:51 +01:00
|
|
|
if (!trust_function_creators && mysql_bin_log.is_open() &&
|
2005-10-17 20:37:24 +02:00
|
|
|
!(thd->security_ctx->master_access & SUPER_ACL))
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
2005-10-17 20:37:24 +02:00
|
|
|
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2004-09-07 14:29:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
We don't want perform our operations while global read lock is held
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
so we have to wait until its end and then prevent it from occurring
|
2004-09-07 14:29:46 +02:00
|
|
|
again until we are done. (Acquiring LOCK_open is not enough because
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
global read lock is held without holding LOCK_open).
|
2004-09-07 14:29:46 +02:00
|
|
|
*/
|
2005-10-17 20:37:24 +02:00
|
|
|
if (wait_if_global_read_lock(thd, 0, 1))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-10-17 20:37:24 +02:00
|
|
|
VOID(pthread_mutex_lock(&LOCK_open));
|
|
|
|
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
if (!create)
|
|
|
|
{
|
|
|
|
bool if_exists= thd->lex->drop_if_exists;
|
|
|
|
|
|
|
|
if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables))
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if (!tables)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(if_exists);
|
|
|
|
/*
|
|
|
|
Since the trigger does not exist, there is no associated table,
|
|
|
|
and therefore :
|
|
|
|
- no TRIGGER privileges to check,
|
|
|
|
- no trigger to drop,
|
|
|
|
- no table to lock/modify,
|
|
|
|
so the drop statement is successful.
|
|
|
|
*/
|
|
|
|
result= FALSE;
|
|
|
|
/* Still, we need to log the query ... */
|
|
|
|
stmt_query.append(thd->query, thd->query_length);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-30 01:34:10 +01:00
|
|
|
/*
|
|
|
|
Check that the user has TRIGGER privilege on the subject table.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
bool err_status;
|
|
|
|
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
|
|
|
|
thd->lex->query_tables_own_last= 0;
|
|
|
|
|
|
|
|
err_status= check_table_access(thd, TRIGGER_ACL, tables, 0);
|
|
|
|
|
|
|
|
thd->lex->query_tables_own_last= save_query_tables_own_last;
|
|
|
|
|
|
|
|
if (err_status)
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
/* We should have only one table in table list. */
|
|
|
|
DBUG_ASSERT(tables->next_global == 0);
|
|
|
|
|
|
|
|
/* We do not allow creation of triggers on temporary tables. */
|
|
|
|
if (create && find_temporary_table(thd, tables->db, tables->table_name))
|
|
|
|
{
|
|
|
|
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2005-10-17 20:37:24 +02:00
|
|
|
if (lock_table_names(thd, tables))
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
/* We also don't allow creation of triggers on views. */
|
|
|
|
tables->required_type= FRMTYPE_TABLE;
|
|
|
|
|
2007-05-11 19:51:03 +02:00
|
|
|
if (reopen_name_locked_table(thd, tables, TRUE))
|
2005-05-06 18:52:19 +02:00
|
|
|
{
|
2005-10-17 20:37:24 +02:00
|
|
|
unlock_table_name(thd, tables);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
table= tables->table;
|
|
|
|
|
|
|
|
if (!table->triggers)
|
|
|
|
{
|
|
|
|
if (!create)
|
|
|
|
{
|
|
|
|
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table)))
|
|
|
|
goto end;
|
2005-05-06 18:52:19 +02:00
|
|
|
}
|
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
result= (create ?
|
2006-08-24 16:48:26 +02:00
|
|
|
table->triggers->create_trigger(thd, tables, &stmt_query):
|
|
|
|
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-10-17 20:37:24 +02:00
|
|
|
end:
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
if (!result)
|
2005-11-10 20:25:03 +01:00
|
|
|
{
|
2007-06-19 13:27:53 +02:00
|
|
|
write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length());
|
2006-10-03 19:38:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
|
|
|
start_waiting_global_read_lock(thd);
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2006-10-03 19:38:25 +02:00
|
|
|
if (!result)
|
2005-11-10 20:25:03 +01:00
|
|
|
send_ok(thd);
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_RETURN(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Create trigger for table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
create_trigger()
|
2005-11-10 20:25:03 +01:00
|
|
|
thd - current thread context (including trigger definition in
|
|
|
|
LEX)
|
|
|
|
tables - table list containing one open table for which the
|
|
|
|
trigger is created.
|
2006-08-24 16:48:26 +02:00
|
|
|
stmt_query - [OUT] after successful return, this string contains
|
2007-02-11 13:23:23 +01:00
|
|
|
well-formed statement for creating this trigger.
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-12-11 13:26:15 +01:00
|
|
|
NOTE
|
2006-03-01 12:13:07 +01:00
|
|
|
- Assumes that trigger name is fully qualified.
|
|
|
|
- NULL-string means the following LEX_STRING instance:
|
|
|
|
{ str = 0; length = 0 }.
|
|
|
|
- In other words, definer_user and definer_host should contain
|
|
|
|
simultaneously NULL-strings (non-SUID/old trigger) or valid strings
|
|
|
|
(SUID/new trigger).
|
2005-12-11 13:26:15 +01:00
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
2005-11-10 20:25:03 +01:00
|
|
|
bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
2006-08-24 16:48:26 +02:00
|
|
|
String *stmt_query)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
|
|
|
LEX *lex= thd->lex;
|
|
|
|
TABLE *table= tables->table;
|
2006-02-27 18:00:07 +01:00
|
|
|
char file_buff[FN_REFLEN], trigname_buff[FN_REFLEN];
|
2005-12-31 06:01:26 +01:00
|
|
|
LEX_STRING file, trigname_file;
|
2006-11-30 02:40:42 +01:00
|
|
|
LEX_STRING *trg_def;
|
2006-08-24 16:48:26 +02:00
|
|
|
LEX_STRING definer_user;
|
|
|
|
LEX_STRING definer_host;
|
2005-07-28 21:39:11 +02:00
|
|
|
ulonglong *trg_sql_mode;
|
2006-01-11 00:07:40 +01:00
|
|
|
char trg_definer_holder[USER_HOST_BUFF_SIZE];
|
2005-11-10 20:25:03 +01:00
|
|
|
LEX_STRING *trg_definer;
|
2004-11-24 10:24:02 +01:00
|
|
|
Item_trigger_field *trg_field;
|
2005-07-19 18:06:49 +02:00
|
|
|
struct st_trigname trigname;
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
LEX_STRING *trg_client_cs_name;
|
|
|
|
LEX_STRING *trg_connection_cl_name;
|
|
|
|
LEX_STRING *trg_db_cl_name;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
|
|
|
|
/* Trigger must be in the same schema as target table. */
|
2005-11-23 21:45:02 +01:00
|
|
|
if (my_strcasecmp(table_alias_charset, table->s->db.str,
|
2005-12-24 18:13:51 +01:00
|
|
|
lex->spname->m_db.str))
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
2005-07-19 18:06:49 +02:00
|
|
|
my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0));
|
2004-09-07 14:29:46 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
/* We don't allow creation of several triggers of the same type yet */
|
2007-02-11 13:23:23 +01:00
|
|
|
if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time] != 0)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
2006-06-28 21:50:50 +02:00
|
|
|
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
|
|
|
|
"multiple triggers with the same action time"
|
|
|
|
" and event for one table");
|
2005-07-19 18:06:49 +02:00
|
|
|
return 1;
|
2004-09-07 14:29:46 +02:00
|
|
|
}
|
|
|
|
|
2006-03-01 12:13:07 +01:00
|
|
|
if (!lex->definer)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
DEFINER-clause is missing.
|
|
|
|
|
|
|
|
If we are in slave thread, this means that we received CREATE TRIGGER
|
|
|
|
from the master, that does not support definer in triggers. So, we
|
|
|
|
should mark this trigger as non-SUID. Note that this does not happen
|
|
|
|
when we parse triggers' definitions during opening .TRG file.
|
|
|
|
LEX::definer is ignored in that case.
|
|
|
|
|
|
|
|
Otherwise, we should use CURRENT_USER() as definer.
|
|
|
|
|
|
|
|
NOTE: when CREATE TRIGGER statement is allowed to be executed in PS/SP,
|
|
|
|
it will be required to create the definer below in persistent MEM_ROOT
|
|
|
|
of PS/SP.
|
|
|
|
*/
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2006-03-01 12:13:07 +01:00
|
|
|
if (!thd->slave_thread)
|
|
|
|
{
|
|
|
|
if (!(lex->definer= create_default_definer(thd)))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2005-11-10 20:25:03 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
If the specified definer differs from the current user, we should check
|
|
|
|
that the current user has SUPER privilege (in order to create trigger
|
|
|
|
under another user one must have SUPER privilege).
|
|
|
|
*/
|
|
|
|
|
2006-03-01 12:13:07 +01:00
|
|
|
if (lex->definer &&
|
|
|
|
(strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
|
|
|
my_strcasecmp(system_charset_info,
|
|
|
|
lex->definer->host.str,
|
|
|
|
thd->security_ctx->priv_host)))
|
2005-11-10 20:25:03 +01:00
|
|
|
{
|
|
|
|
if (check_global_access(thd, SUPER_ACL))
|
|
|
|
{
|
|
|
|
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-24 10:24:02 +01:00
|
|
|
/*
|
|
|
|
Let us check if all references to fields in old/new versions of row in
|
|
|
|
this trigger are ok.
|
|
|
|
|
|
|
|
NOTE: We do it here more from ease of use standpoint. We still have to
|
|
|
|
do some checks on each execution. E.g. we can catch privilege changes
|
|
|
|
only during execution. Also in near future, when we will allow access
|
|
|
|
to other tables from trigger we won't be able to catch changes in other
|
|
|
|
tables...
|
|
|
|
|
2005-05-24 20:19:33 +02:00
|
|
|
Since we don't plan to access to contents of the fields it does not
|
|
|
|
matter that we choose for both OLD and NEW values the same versions
|
|
|
|
of Field objects here.
|
2004-11-24 10:24:02 +01:00
|
|
|
*/
|
2005-05-24 20:19:33 +02:00
|
|
|
old_field= new_field= table->field;
|
2004-11-24 10:24:02 +01:00
|
|
|
|
|
|
|
for (trg_field= (Item_trigger_field *)(lex->trg_table_fields.first);
|
|
|
|
trg_field; trg_field= trg_field->next_trg_field)
|
|
|
|
{
|
2006-01-24 18:15:12 +01:00
|
|
|
/*
|
|
|
|
NOTE: now we do not check privileges at CREATE TRIGGER time. This will
|
|
|
|
be changed in the future.
|
|
|
|
*/
|
|
|
|
trg_field->setup_field(thd, table, NULL);
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
if (!trg_field->fixed &&
|
2005-07-01 06:05:42 +02:00
|
|
|
trg_field->fix_fields(thd, (Item **)0))
|
2004-11-24 10:24:02 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
/*
|
|
|
|
Here we are creating file with triggers and save all triggers in it.
|
|
|
|
sql_create_definition_file() files handles renaming and backup of older
|
|
|
|
versions
|
|
|
|
*/
|
2007-06-14 17:23:55 +02:00
|
|
|
file.length= build_table_filename(file_buff, FN_REFLEN - 1,
|
2005-12-31 06:01:26 +01:00
|
|
|
tables->db, tables->table_name,
|
2007-06-14 17:23:55 +02:00
|
|
|
TRG_EXT, 0);
|
2004-09-07 14:29:46 +02:00
|
|
|
file.str= file_buff;
|
2005-12-31 06:01:26 +01:00
|
|
|
trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
|
|
|
|
tables->db,
|
|
|
|
lex->spname->m_name.str,
|
2007-06-14 17:23:55 +02:00
|
|
|
TRN_EXT, 0);
|
2005-07-19 18:06:49 +02:00
|
|
|
trigname_file.str= trigname_buff;
|
|
|
|
|
|
|
|
/* Use the filesystem to enforce trigger namespace constraints. */
|
2005-12-31 06:01:26 +01:00
|
|
|
if (!access(trigname_buff, F_OK))
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
|
|
|
my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
trigname.trigger_table.str= tables->table_name;
|
|
|
|
trigname.trigger_table.length= tables->table_name_length;
|
|
|
|
|
2005-12-31 06:01:26 +01:00
|
|
|
if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
(uchar*)&trigname, trigname_file_parameters, 0))
|
2005-07-19 18:06:49 +02:00
|
|
|
return 1;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Soon we will invalidate table object and thus Table_triggers_list object
|
|
|
|
so don't care about place to which trg_def->ptr points and other
|
|
|
|
invariants (e.g. we don't bother to update names_list)
|
|
|
|
|
|
|
|
QQ: Hmm... probably we should not care about setting up active thread
|
|
|
|
mem_root too.
|
|
|
|
*/
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (!(trg_def= alloc_lex_string(&table->mem_root)) ||
|
2005-07-28 21:39:11 +02:00
|
|
|
definitions_list.push_back(trg_def, &table->mem_root) ||
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
|
|
|
|
!(trg_sql_mode= alloc_type<ulonglong>(&table->mem_root)) ||
|
2005-11-10 20:25:03 +01:00
|
|
|
definition_modes_list.push_back(trg_sql_mode, &table->mem_root) ||
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
|
|
|
|
!(trg_definer= alloc_lex_string(&table->mem_root)) ||
|
|
|
|
definers_list.push_back(trg_definer, &table->mem_root) ||
|
|
|
|
|
|
|
|
!(trg_client_cs_name= alloc_lex_string(&table->mem_root)) ||
|
|
|
|
client_cs_names.push_back(trg_client_cs_name, &table->mem_root) ||
|
|
|
|
|
|
|
|
!(trg_connection_cl_name= alloc_lex_string(&table->mem_root)) ||
|
|
|
|
connection_cl_names.push_back(trg_connection_cl_name, &table->mem_root) ||
|
|
|
|
|
|
|
|
!(trg_db_cl_name= alloc_lex_string(&table->mem_root)) ||
|
|
|
|
db_cl_names.push_back(trg_db_cl_name, &table->mem_root))
|
|
|
|
{
|
2005-07-19 18:06:49 +02:00
|
|
|
goto err_with_cleanup;
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
}
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
*trg_sql_mode= thd->variables.sql_mode;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-11-10 20:25:03 +01:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2006-03-01 12:13:07 +01:00
|
|
|
if (lex->definer && !is_acl_user(lex->definer->host.str,
|
|
|
|
lex->definer->user.str))
|
2005-11-10 20:25:03 +01:00
|
|
|
{
|
|
|
|
push_warning_printf(thd,
|
|
|
|
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
|
|
|
ER_NO_SUCH_USER,
|
|
|
|
ER(ER_NO_SUCH_USER),
|
|
|
|
lex->definer->user.str,
|
|
|
|
lex->definer->host.str);
|
|
|
|
}
|
|
|
|
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
|
|
|
|
2006-03-01 12:13:07 +01:00
|
|
|
if (lex->definer)
|
|
|
|
{
|
|
|
|
/* SUID trigger. */
|
|
|
|
|
2006-08-24 16:48:26 +02:00
|
|
|
definer_user= lex->definer->user;
|
|
|
|
definer_host= lex->definer->host;
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2006-03-01 12:13:07 +01:00
|
|
|
trg_definer->str= trg_definer_holder;
|
2006-08-24 16:48:26 +02:00
|
|
|
trg_definer->length= strxmov(trg_definer->str, definer_user.str, "@",
|
|
|
|
definer_host.str, NullS) - trg_definer->str;
|
2006-03-01 12:13:07 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* non-SUID trigger. */
|
|
|
|
|
2006-08-24 16:48:26 +02:00
|
|
|
definer_user.str= 0;
|
|
|
|
definer_user.length= 0;
|
2006-03-01 12:13:07 +01:00
|
|
|
|
2006-08-24 16:48:26 +02:00
|
|
|
definer_host.str= 0;
|
|
|
|
definer_host.length= 0;
|
2006-03-01 12:13:07 +01:00
|
|
|
|
|
|
|
trg_definer->str= (char*) "";
|
|
|
|
trg_definer->length= 0;
|
|
|
|
}
|
2005-11-10 20:25:03 +01:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
/*
|
|
|
|
Fill character set information:
|
|
|
|
- client character set contains charset info only;
|
|
|
|
- connection collation contains pair {character set, collation};
|
|
|
|
- database collation contains pair {character set, collation};
|
|
|
|
*/
|
|
|
|
|
|
|
|
lex_string_set(trg_client_cs_name, thd->charset()->csname);
|
|
|
|
|
|
|
|
lex_string_set(trg_connection_cl_name,
|
|
|
|
thd->variables.collation_connection->name);
|
|
|
|
|
|
|
|
lex_string_set(trg_db_cl_name,
|
|
|
|
get_default_db_collation(thd, tables->db)->name);
|
|
|
|
|
2006-08-24 16:48:26 +02:00
|
|
|
/*
|
|
|
|
Create well-formed trigger definition query. Original query is not
|
|
|
|
appropriated, because definer-clause can be not truncated.
|
|
|
|
*/
|
|
|
|
|
|
|
|
stmt_query->append(STRING_WITH_LEN("CREATE "));
|
|
|
|
|
|
|
|
if (trg_definer)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Append definer-clause if the trigger is SUID (a usual trigger in
|
|
|
|
new MySQL versions).
|
|
|
|
*/
|
|
|
|
|
|
|
|
append_definer(thd, stmt_query, &definer_user, &definer_host);
|
|
|
|
}
|
|
|
|
|
Bug#25411 (trigger code truncated), PART II
Bug 28127 (Some valid identifiers names are not parsed correctly)
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
This patch is the second part of a major cleanup, required to fix
Bug 25411 (trigger code truncated).
The root cause of the issue stems from the function skip_rear_comments,
which was a work around to remove "extra" "*/" characters from the query
text, when parsing a query and reusing the text fragments to represent a
view, trigger, function or stored procedure.
The reason for this work around is that "special comments",
like /*!50002 XXX */, were not parsed properly, so that a query like:
AAA /*!50002 BBB */ CCC
would be seen by the parser as "AAA BBB */ CCC" when the current version
is greater or equal to 5.0.2
The root cause of this stems from how special comments are parsed.
Special comments are really out-of-bound text that appear inside a query,
that affects how the parser behave.
In nature, /*!50002 XXX */ in MySQL is similar to the C concept
of preprocessing :
#if VERSION >= 50002
XXX
#endif
Depending on the current VERSION of the server, either the special comment
should be expanded or it should be ignored, but in all cases the "text" of
the query should be re-written to strip the "/*!50002" and "*/" markers,
which does not belong to the SQL language itself.
Prior to this fix, these markers would leak into :
- the storage format for VIEW,
- the storage format for FUNCTION,
- the storage format for FUNCTION parameters, in mysql.proc (param_list),
- the storage format for PROCEDURE,
- the storage format for PROCEDURE parameters, in mysql.proc (param_list),
- the storage format for TRIGGER,
- the binary log used for replication.
In all cases, not only this cause format corruption, but also provide a vector
for dormant security issues, by allowing to tunnel code that will be activated
after an upgrade.
The proper solution is to deal with special comments strictly during parsing,
when accepting a query from the outside world.
Once a query is parsed and an object is created with a persistant
representation, this object should not arbitrarily mutate after an upgrade.
In short, special comments are a useful but limited feature for MYSQLdump,
when used at an *interface* level to facilitate import/export,
but bloating the server *internal* storage format is *not* the proper way
to deal with configuration management of the user logic.
With this fix:
- the Lex_input_stream class now acts as a comment pre-processor,
and either expands or ignore special comments on the fly.
- MYSQLlex and sql_yacc.yy have been cleaned up to strictly use the
public interface of Lex_input_stream. In particular, how the input stream
accepts or rejects a character is private to Lex_input_stream, and the
internal buffer pointers of that class are strictly private, and should not
be tempered with during parsing.
This caused many changes mostly in sql_lex.cc.
During the code cleanup in case MY_LEX_NUMBER_IDENT,
Bug 28127 (Some valid identifiers names are not parsed correctly)
was found and fixed.
By parsing special comments properly, and removing the function
'skip_rear_comments' [sic],
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
has been fixed as well.
2007-06-12 23:23:58 +02:00
|
|
|
LEX_STRING stmt_definition;
|
|
|
|
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
|
|
|
|
stmt_definition.length= thd->lex->stmt_definition_end
|
|
|
|
- thd->lex->stmt_definition_begin;
|
|
|
|
trim_whitespace(thd->charset(), & stmt_definition);
|
|
|
|
|
|
|
|
stmt_query->append(stmt_definition.str, stmt_definition.length);
|
2006-08-24 16:48:26 +02:00
|
|
|
|
|
|
|
trg_def->str= stmt_query->c_ptr();
|
|
|
|
trg_def->length= stmt_query->length();
|
|
|
|
|
|
|
|
/* Create trigger definition file. */
|
|
|
|
|
2005-12-31 06:01:26 +01:00
|
|
|
if (!sql_create_definition_file(NULL, &file, &triggers_file_type,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
(uchar*)this, triggers_file_parameters, 0))
|
2005-07-19 18:06:49 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_with_cleanup:
|
2006-02-27 18:00:07 +01:00
|
|
|
my_delete(trigname_buff, MYF(MY_WME));
|
2005-07-19 18:06:49 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Deletes the .TRG file for a table
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
rm_trigger_file()
|
|
|
|
path - char buffer of size FN_REFLEN to be used
|
|
|
|
for constructing path to .TRG file.
|
|
|
|
db - table's database name
|
|
|
|
table_name - table's name
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
static bool rm_trigger_file(char *path, const char *db,
|
|
|
|
const char *table_name)
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
2007-06-14 17:23:55 +02:00
|
|
|
build_table_filename(path, FN_REFLEN-1, db, table_name, TRG_EXT, 0);
|
2005-07-19 18:06:49 +02:00
|
|
|
return my_delete(path, MYF(MY_WME));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Deletes the .TRN file for a trigger
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
rm_trigname_file()
|
|
|
|
path - char buffer of size FN_REFLEN to be used
|
|
|
|
for constructing path to .TRN file.
|
|
|
|
db - trigger's database name
|
|
|
|
table_name - trigger's name
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
static bool rm_trigname_file(char *path, const char *db,
|
|
|
|
const char *trigger_name)
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
2007-06-14 17:23:55 +02:00
|
|
|
build_table_filename(path, FN_REFLEN - 1, db, trigger_name, TRN_EXT, 0);
|
2005-07-19 18:06:49 +02:00
|
|
|
return my_delete(path, MYF(MY_WME));
|
2004-09-07 14:29:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
/*
|
|
|
|
Helper function that saves .TRG file for Table_triggers_list object.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
save_trigger_file()
|
|
|
|
triggers Table_triggers_list object for which file should be saved
|
|
|
|
db Name of database for subject table
|
|
|
|
table_name Name of subject table
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
FALSE Success
|
|
|
|
TRUE Error
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool save_trigger_file(Table_triggers_list *triggers, const char *db,
|
|
|
|
const char *table_name)
|
|
|
|
{
|
2006-02-27 18:00:07 +01:00
|
|
|
char file_buff[FN_REFLEN];
|
|
|
|
LEX_STRING file;
|
2006-02-24 21:50:36 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
file.length= build_table_filename(file_buff, FN_REFLEN - 1, db, table_name,
|
|
|
|
TRG_EXT, 0);
|
2006-02-27 18:00:07 +01:00
|
|
|
file.str= file_buff;
|
|
|
|
return sql_create_definition_file(NULL, &file, &triggers_file_type,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
(uchar*)triggers, triggers_file_parameters,
|
2006-02-27 18:00:07 +01:00
|
|
|
0);
|
2006-02-24 21:50:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
/*
|
|
|
|
Drop trigger for table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
drop_trigger()
|
2006-08-24 16:48:26 +02:00
|
|
|
thd - current thread context
|
|
|
|
(including trigger definition in LEX)
|
|
|
|
tables - table list containing one open table for which trigger
|
|
|
|
is dropped.
|
|
|
|
stmt_query - [OUT] after successful return, this string contains
|
2007-02-11 13:23:23 +01:00
|
|
|
well-formed statement for deleting this trigger.
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
2006-08-24 16:48:26 +02:00
|
|
|
bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
|
|
|
|
String *stmt_query)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
const char *sp_name= thd->lex->spname->m_name.str; // alias
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
LEX_STRING *name;
|
2005-07-19 18:06:49 +02:00
|
|
|
char path[FN_REFLEN];
|
2004-09-07 14:29:46 +02:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
List_iterator_fast<LEX_STRING> it_name(names_list);
|
|
|
|
|
|
|
|
List_iterator<ulonglong> it_mod(definition_modes_list);
|
|
|
|
List_iterator<LEX_STRING> it_def(definitions_list);
|
|
|
|
List_iterator<LEX_STRING> it_definer(definers_list);
|
|
|
|
List_iterator<LEX_STRING> it_client_cs_name(client_cs_names);
|
|
|
|
List_iterator<LEX_STRING> it_connection_cl_name(connection_cl_names);
|
|
|
|
List_iterator<LEX_STRING> it_db_cl_name(db_cl_names);
|
|
|
|
|
2006-08-24 16:48:26 +02:00
|
|
|
stmt_query->append(thd->query, thd->query_length);
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
while ((name= it_name++))
|
|
|
|
{
|
|
|
|
it_def++;
|
2005-07-28 21:39:11 +02:00
|
|
|
it_mod++;
|
2005-11-10 20:25:03 +01:00
|
|
|
it_definer++;
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
it_client_cs_name++;
|
|
|
|
it_connection_cl_name++;
|
|
|
|
it_db_cl_name++;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (my_strcasecmp(table_alias_charset, sp_name, name->str) == 0)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Again we don't care much about other things required for
|
|
|
|
clean trigger removing since table will be reopened anyway.
|
|
|
|
*/
|
|
|
|
it_def.remove();
|
2005-07-28 21:39:11 +02:00
|
|
|
it_mod.remove();
|
2005-11-10 20:25:03 +01:00
|
|
|
it_definer.remove();
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
it_client_cs_name.remove();
|
|
|
|
it_connection_cl_name.remove();
|
|
|
|
it_db_cl_name.remove();
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
if (definitions_list.is_empty())
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
TODO: Probably instead of removing .TRG file we should move
|
|
|
|
to archive directory but this should be done as part of
|
|
|
|
parse_file.cc functionality (because we will need it
|
|
|
|
elsewhere).
|
|
|
|
*/
|
2005-07-19 18:06:49 +02:00
|
|
|
if (rm_trigger_file(path, tables->db, tables->table_name))
|
|
|
|
return 1;
|
2004-09-07 14:29:46 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-02-24 21:50:36 +01:00
|
|
|
if (save_trigger_file(this, tables->db, tables->table_name))
|
2005-07-19 18:06:49 +02:00
|
|
|
return 1;
|
2004-09-07 14:29:46 +02:00
|
|
|
}
|
2005-07-19 18:06:49 +02:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (rm_trigname_file(path, tables->db, sp_name))
|
2005-07-19 18:06:49 +02:00
|
|
|
return 1;
|
|
|
|
return 0;
|
2004-09-07 14:29:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0));
|
2004-09-07 14:29:46 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Table_triggers_list::~Table_triggers_list()
|
|
|
|
{
|
2005-07-19 18:06:49 +02:00
|
|
|
for (int i= 0; i < (int)TRG_EVENT_MAX; i++)
|
|
|
|
for (int j= 0; j < (int)TRG_ACTION_MAX; j++)
|
2004-09-07 14:29:46 +02:00
|
|
|
delete bodies[i][j];
|
|
|
|
|
2005-05-24 20:19:33 +02:00
|
|
|
if (record1_field)
|
|
|
|
for (Field **fld_ptr= record1_field; *fld_ptr; fld_ptr++)
|
2004-09-07 14:29:46 +02:00
|
|
|
delete *fld_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-24 10:24:02 +01:00
|
|
|
/*
|
2005-05-24 20:19:33 +02:00
|
|
|
Prepare array of Field objects referencing to TABLE::record[1] instead
|
|
|
|
of record[0] (they will represent OLD.* row values in ON UPDATE trigger
|
|
|
|
and in ON DELETE trigger which will be called during REPLACE execution).
|
2004-11-24 10:24:02 +01:00
|
|
|
|
|
|
|
SYNOPSIS
|
2005-05-24 20:19:33 +02:00
|
|
|
prepare_record1_accessors()
|
2004-11-24 10:24:02 +01:00
|
|
|
table - pointer to TABLE object for which we are creating fields.
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
2005-05-24 20:19:33 +02:00
|
|
|
bool Table_triggers_list::prepare_record1_accessors(TABLE *table)
|
2004-11-24 10:24:02 +01:00
|
|
|
{
|
|
|
|
Field **fld, **old_fld;
|
|
|
|
|
2005-05-24 20:19:33 +02:00
|
|
|
if (!(record1_field= (Field **)alloc_root(&table->mem_root,
|
|
|
|
(table->s->fields + 1) *
|
|
|
|
sizeof(Field*))))
|
2004-11-24 10:24:02 +01:00
|
|
|
return 1;
|
|
|
|
|
2005-05-24 20:19:33 +02:00
|
|
|
for (fld= table->field, old_fld= record1_field; *fld; fld++, old_fld++)
|
2004-11-24 10:24:02 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
QQ: it is supposed that it is ok to use this function for field
|
|
|
|
cloning...
|
|
|
|
*/
|
2006-06-26 20:57:18 +02:00
|
|
|
if (!(*old_fld= (*fld)->new_field(&table->mem_root, table,
|
|
|
|
table == (*fld)->table)))
|
2004-11-24 10:24:02 +01:00
|
|
|
return 1;
|
2005-11-23 21:45:02 +01:00
|
|
|
(*old_fld)->move_field_offset((my_ptrdiff_t)(table->record[1] -
|
2007-01-27 02:46:45 +01:00
|
|
|
table->record[0]));
|
2004-11-24 10:24:02 +01:00
|
|
|
}
|
|
|
|
*old_fld= 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-15 01:56:09 +02:00
|
|
|
/*
|
|
|
|
Adjust Table_triggers_list with new TABLE pointer.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
set_table()
|
|
|
|
new_table - new pointer to TABLE instance
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Table_triggers_list::set_table(TABLE *new_table)
|
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
trigger_table= new_table;
|
|
|
|
for (Field **field= new_table->triggers->record1_field ; *field ; field++)
|
2005-09-15 01:56:09 +02:00
|
|
|
{
|
|
|
|
(*field)->table= (*field)->orig_table= new_table;
|
|
|
|
(*field)->table_name= &new_table->alias;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
/*
|
|
|
|
Check whenever .TRG file for table exist and load all triggers it contains.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
check_n_load()
|
|
|
|
thd - current thread context
|
|
|
|
db - table's database name
|
|
|
|
table_name - table's name
|
|
|
|
table - pointer to table object
|
2005-07-19 18:06:49 +02:00
|
|
|
names_only - stop after loading trigger names
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
2005-07-19 18:06:49 +02:00
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
2005-07-19 18:06:49 +02:00
|
|
|
const char *table_name, TABLE *table,
|
|
|
|
bool names_only)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
|
|
|
char path_buff[FN_REFLEN];
|
|
|
|
LEX_STRING path;
|
|
|
|
File_parser *parser;
|
2005-07-27 13:17:05 +02:00
|
|
|
LEX_STRING save_db;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
DBUG_ENTER("Table_triggers_list::check_n_load");
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
path.length= build_table_filename(path_buff, FN_REFLEN - 1,
|
|
|
|
db, table_name, TRG_EXT, 0);
|
2004-09-07 14:29:46 +02:00
|
|
|
path.str= path_buff;
|
|
|
|
|
|
|
|
// QQ: should we analyze errno somehow ?
|
|
|
|
if (access(path_buff, F_OK))
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
|
|
|
/*
|
2005-11-10 20:25:03 +01:00
|
|
|
File exists so we got to load triggers.
|
2004-09-07 14:29:46 +02:00
|
|
|
FIXME: A lot of things to do here e.g. how about other funcs and being
|
|
|
|
more paranoical ?
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((parser= sql_parse_prepare(&path, &table->mem_root, 1)))
|
|
|
|
{
|
2005-07-31 11:49:55 +02:00
|
|
|
if (is_equal(&triggers_file_type, parser->type()))
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
2004-09-08 22:46:01 +02:00
|
|
|
Table_triggers_list *triggers=
|
2005-05-24 20:19:33 +02:00
|
|
|
new (&table->mem_root) Table_triggers_list(table);
|
2005-11-20 19:47:07 +01:00
|
|
|
Handle_old_incorrect_sql_modes_hook sql_modes_hook(path.str);
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2004-09-08 22:46:01 +02:00
|
|
|
if (!triggers)
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
/*
|
2005-11-10 20:25:03 +01:00
|
|
|
We don't have the following attributes in old versions of .TRG file, so
|
|
|
|
we should initialize the list for safety:
|
|
|
|
- sql_modes;
|
|
|
|
- definers;
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
- character sets (client, connection, database);
|
2005-07-28 21:39:11 +02:00
|
|
|
*/
|
|
|
|
triggers->definition_modes_list.empty();
|
2005-11-10 20:25:03 +01:00
|
|
|
triggers->definers_list.empty();
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
triggers->client_cs_names.empty();
|
|
|
|
triggers->connection_cl_names.empty();
|
|
|
|
triggers->db_cl_names.empty();
|
2005-07-28 21:39:11 +02:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (parser->parse((uchar*)triggers, &table->mem_root,
|
2005-11-20 19:47:07 +01:00
|
|
|
triggers_file_parameters,
|
|
|
|
TRG_NUM_REQUIRED_PARAMETERS,
|
|
|
|
&sql_modes_hook))
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
|
2006-11-30 02:40:42 +01:00
|
|
|
LEX_STRING *trg_create_str;
|
2005-07-28 21:39:11 +02:00
|
|
|
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.
|
|
|
|
*/
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (!(trg_sql_mode= alloc_type<ulonglong>(&table->mem_root)))
|
2005-07-28 21:39:11 +02:00
|
|
|
{
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
*trg_sql_mode= global_system_variables.sql_mode;
|
2005-11-10 20:25:03 +01:00
|
|
|
while (it++)
|
2005-07-28 21:39:11 +02:00
|
|
|
{
|
|
|
|
if (triggers->definition_modes_list.push_back(trg_sql_mode,
|
|
|
|
&table->mem_root))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
}
|
|
|
|
it.rewind();
|
|
|
|
}
|
|
|
|
|
2005-11-10 20:25:03 +01:00
|
|
|
if (triggers->definers_list.is_empty() &&
|
|
|
|
!triggers->definitions_list.is_empty())
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
It is old file format => we should fill list of definers.
|
|
|
|
|
|
|
|
If there is no definer information, we should not switch context to
|
|
|
|
definer when checking privileges. I.e. privileges for such triggers
|
|
|
|
are checked for "invoker" rather than for "definer".
|
|
|
|
*/
|
|
|
|
|
|
|
|
LEX_STRING *trg_definer;
|
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (!(trg_definer= alloc_lex_string(&table->mem_root)))
|
2005-11-10 20:25:03 +01:00
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
|
2005-11-23 21:45:02 +01:00
|
|
|
trg_definer->str= (char*) "";
|
2005-11-10 20:25:03 +01:00
|
|
|
trg_definer->length= 0;
|
|
|
|
|
|
|
|
while (it++)
|
|
|
|
{
|
|
|
|
if (triggers->definers_list.push_back(trg_definer,
|
|
|
|
&table->mem_root))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
it.rewind();
|
|
|
|
}
|
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (!triggers->definitions_list.is_empty() &&
|
|
|
|
(triggers->client_cs_names.is_empty() ||
|
|
|
|
triggers->connection_cl_names.is_empty() ||
|
|
|
|
triggers->db_cl_names.is_empty()))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
It is old file format => we should fill lists of character sets.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LEX_STRING *trg_client_cs_name;
|
|
|
|
LEX_STRING *trg_connection_cl_name;
|
|
|
|
LEX_STRING *trg_db_cl_name;
|
|
|
|
|
|
|
|
if (!triggers->client_cs_names.is_empty() ||
|
|
|
|
!triggers->connection_cl_names.is_empty() ||
|
|
|
|
!triggers->db_cl_names.is_empty())
|
|
|
|
{
|
|
|
|
my_error(ER_TRG_CORRUPTED_FILE, MYF(0),
|
|
|
|
(const char *) db,
|
|
|
|
(const char *) table_name);
|
|
|
|
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
|
|
|
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_TRG_NO_CREATION_CTX,
|
|
|
|
ER(ER_TRG_NO_CREATION_CTX),
|
|
|
|
(const char*) db,
|
|
|
|
(const char*) table_name);
|
|
|
|
|
|
|
|
if (!(trg_client_cs_name= alloc_lex_string(&table->mem_root)) ||
|
|
|
|
!(trg_connection_cl_name= alloc_lex_string(&table->mem_root)) ||
|
|
|
|
!(trg_db_cl_name= alloc_lex_string(&table->mem_root)))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Backward compatibility: assume that the query is in the current
|
|
|
|
character set.
|
|
|
|
*/
|
|
|
|
|
|
|
|
lex_string_set(trg_client_cs_name,
|
|
|
|
thd->variables.character_set_client->csname);
|
|
|
|
|
|
|
|
lex_string_set(trg_connection_cl_name,
|
|
|
|
thd->variables.collation_connection->name);
|
|
|
|
|
|
|
|
lex_string_set(trg_db_cl_name,
|
|
|
|
thd->variables.collation_database->name);
|
|
|
|
|
|
|
|
while (it++)
|
|
|
|
{
|
|
|
|
if (triggers->client_cs_names.push_back(trg_client_cs_name,
|
|
|
|
&table->mem_root) ||
|
|
|
|
|
|
|
|
triggers->connection_cl_names.push_back(trg_connection_cl_name,
|
|
|
|
&table->mem_root) ||
|
|
|
|
|
|
|
|
triggers->db_cl_names.push_back(trg_db_cl_name,
|
|
|
|
&table->mem_root))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
it.rewind();
|
|
|
|
}
|
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
DBUG_ASSERT(triggers->definition_modes_list.elements ==
|
|
|
|
triggers->definitions_list.elements);
|
2005-11-10 20:25:03 +01:00
|
|
|
DBUG_ASSERT(triggers->definers_list.elements ==
|
|
|
|
triggers->definitions_list.elements);
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
DBUG_ASSERT(triggers->client_cs_names.elements ==
|
|
|
|
triggers->definitions_list.elements);
|
|
|
|
DBUG_ASSERT(triggers->connection_cl_names.elements ==
|
|
|
|
triggers->definitions_list.elements);
|
|
|
|
DBUG_ASSERT(triggers->db_cl_names.elements ==
|
|
|
|
triggers->definitions_list.elements);
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2004-09-08 22:46:01 +02:00
|
|
|
table->triggers= triggers;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2005-05-24 20:19:33 +02:00
|
|
|
/*
|
|
|
|
TODO: This could be avoided if there is no triggers
|
|
|
|
for UPDATE and DELETE.
|
|
|
|
*/
|
2005-07-19 18:06:49 +02:00
|
|
|
if (!names_only && triggers->prepare_record1_accessors(table))
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
|
2006-01-24 18:15:12 +01:00
|
|
|
List_iterator_fast<LEX_STRING> it_definer(triggers->definers_list);
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
List_iterator_fast<LEX_STRING> it_client_cs_name(triggers->client_cs_names);
|
|
|
|
List_iterator_fast<LEX_STRING> it_connection_cl_name(triggers->connection_cl_names);
|
|
|
|
List_iterator_fast<LEX_STRING> it_db_cl_name(triggers->db_cl_names);
|
2004-09-07 14:29:46 +02:00
|
|
|
LEX *old_lex= thd->lex, lex;
|
2005-11-22 23:50:37 +01:00
|
|
|
sp_rcontext *save_spcont= thd->spcont;
|
2005-07-28 21:39:11 +02:00
|
|
|
ulong save_sql_mode= thd->variables.sql_mode;
|
2006-02-24 21:50:36 +01:00
|
|
|
LEX_STRING *on_table_name;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
thd->lex= &lex;
|
|
|
|
|
2005-07-27 13:17:05 +02:00
|
|
|
save_db.str= thd->db;
|
|
|
|
save_db.length= thd->db_length;
|
A fix and a test case for
Bug#19022 "Memory bug when switching db during trigger execution"
Bug#17199 "Problem when view calls function from another database."
Bug#18444 "Fully qualified stored function names don't work correctly in
SELECT statements"
Documentation note: this patch introduces a change in behaviour of prepared
statements.
This patch adds a few new invariants with regard to how THD::db should
be used. These invariants should be preserved in future:
- one should never refer to THD::db by pointer and always make a deep copy
(strmake, strdup)
- one should never compare two databases by pointer, but use strncmp or
my_strncasecmp
- TABLE_LIST object table->db should be always initialized in the parser or
by creator of the object.
For prepared statements it means that if the current database is changed
after a statement is prepared, the database that was current at prepare
remains active. This also means that you can not prepare a statement that
implicitly refers to the current database if the latter is not set.
This is not documented, and therefore needs documentation. This is NOT a
change in behavior for almost all SQL statements except:
- ALTER TABLE t1 RENAME t2
- OPTIMIZE TABLE t1
- ANALYZE TABLE t1
- TRUNCATE TABLE t1 --
until this patch t1 or t2 could be evaluated at the first execution of
prepared statement.
CURRENT_DATABASE() still works OK and is evaluated at every execution
of prepared statement.
Note, that in stored routines this is not an issue as the default
database is the database of the stored procedure and "use" statement
is prohibited in stored routines.
This patch makes obsolete the use of check_db_used (it was never used in the
old code too) and all other places that check for table->db and assign it
from THD::db if it's NULL, except the parser.
How this patch was created: THD::{db,db_length} were replaced with a
LEX_STRING, THD::db. All the places that refer to THD::{db,db_length} were
manually checked and:
- if the place uses thd->db by pointer, it was fixed to make a deep copy
- if a place compared two db pointers, it was fixed to compare them by value
(via strcmp/my_strcasecmp, whatever was approproate)
Then this intermediate patch was used to write a smaller patch that does the
same thing but without a rename.
TODO in 5.1:
- remove check_db_used
- deploy THD::set_db in mysql_change_db
See also comments to individual files.
2006-06-26 22:47:52 +02:00
|
|
|
thd->reset_db((char*) db, strlen(db));
|
2004-09-07 14:29:46 +02:00
|
|
|
while ((trg_create_str= it++))
|
|
|
|
{
|
2005-07-28 21:39:11 +02:00
|
|
|
trg_sql_mode= itm++;
|
2005-11-10 20:25:03 +01:00
|
|
|
LEX_STRING *trg_definer= it_definer++;
|
2006-01-24 18:15:12 +01:00
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
thd->variables.sql_mode= (ulong)*trg_sql_mode;
|
2004-11-24 10:24:02 +01:00
|
|
|
|
2007-04-26 05:38:12 +02:00
|
|
|
Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
|
|
|
|
Trigger_creation_ctx *creation_ctx=
|
|
|
|
Trigger_creation_ctx::create(thd,
|
|
|
|
db,
|
|
|
|
table_name,
|
|
|
|
it_client_cs_name++,
|
|
|
|
it_connection_cl_name++,
|
|
|
|
it_db_cl_name++);
|
|
|
|
|
2007-04-26 05:38:12 +02:00
|
|
|
lex_start(thd);
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
thd->spcont= NULL;
|
2007-04-26 05:38:12 +02:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (parse_sql(thd, &lip, creation_ctx))
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
/* Currently sphead is always deleted in case of a parse error */
|
|
|
|
DBUG_ASSERT(lex.sphead == 0);
|
2004-09-07 14:29:46 +02:00
|
|
|
goto err_with_lex_cleanup;
|
|
|
|
}
|
A fix and a test case for Bug#26141 mixing table types in trigger
causes full table lock on innodb table.
Also fixes Bug#28502 Triggers that update another innodb table
will block on X lock unnecessarily (duplciate).
Code review fixes.
Both bugs' synopses are misleading: InnoDB table is
not X locked. The statements, however, cannot proceed concurrently,
but this happens due to lock conflicts for tables used in triggers,
not for the InnoDB table.
If a user had an InnoDB table, and two triggers, AFTER UPDATE and
AFTER INSERT, competing for different resources (e.g. two distinct
MyISAM tables), then these two triggers would not be able to execute
concurrently. Moreover, INSERTS/UPDATES of the InnoDB table would
not be able to run concurrently.
The problem had other side-effects (see respective bug reports).
This behavior was a consequence of a shortcoming of the pre-locking
algorithm, which would not distinguish between different DML operations
(e.g. INSERT and DELETE) and pre-lock all the tables
that are used by any trigger defined on the subject table.
The idea of the fix is to extend the pre-locking algorithm to keep track,
for each table, what DML operation it is used for and not
load triggers that are known to never be fired.
2007-07-12 20:26:41 +02:00
|
|
|
/*
|
|
|
|
Not strictly necessary to invoke this method here, since we know
|
|
|
|
that we've parsed CREATE TRIGGER and not an
|
|
|
|
UPDATE/DELETE/INSERT/REPLACE/LOAD/CREATE TABLE, but we try to
|
|
|
|
maintain the invariant that this method is called for each
|
|
|
|
distinct statement, in case its logic is extended with other
|
|
|
|
types of analyses in future.
|
|
|
|
*/
|
|
|
|
lex.set_trg_event_type_for_tables();
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2006-11-30 02:40:42 +01:00
|
|
|
lex.sphead->set_info(0, 0, &lex.sp_chistics, (ulong) *trg_sql_mode);
|
2005-11-10 20:25:03 +01:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
int event= lex.trg_chistics.event;
|
|
|
|
int action_time= lex.trg_chistics.action_time;
|
|
|
|
|
|
|
|
lex.sphead->set_creation_ctx(creation_ctx);
|
|
|
|
triggers->bodies[event][action_time]= lex.sphead;
|
2005-11-10 20:25:03 +01:00
|
|
|
|
|
|
|
if (!trg_definer->length)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
This trigger was created/imported from the previous version of
|
|
|
|
MySQL, which does not support triggers definers. We should emit
|
|
|
|
warning here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_TRG_NO_DEFINER, ER(ER_TRG_NO_DEFINER),
|
|
|
|
(const char*) db,
|
|
|
|
(const char*) lex.sphead->m_name.str);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Set definer to the '' to correct displaying in the information
|
|
|
|
schema.
|
|
|
|
*/
|
|
|
|
|
2005-11-23 21:45:02 +01:00
|
|
|
lex.sphead->set_definer((char*) "", 0);
|
2005-11-10 20:25:03 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Triggers without definer information are executed under the
|
|
|
|
authorization of the invoker.
|
|
|
|
*/
|
|
|
|
|
|
|
|
lex.sphead->m_chistics->suid= SP_IS_NOT_SUID;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lex.sphead->set_definer(trg_definer->str, trg_definer->length);
|
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
if (triggers->names_list.push_back(&lex.sphead->m_name,
|
|
|
|
&table->mem_root))
|
2005-07-19 18:06:49 +02:00
|
|
|
goto err_with_lex_cleanup;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
if (!(on_table_name= alloc_lex_string(&table->mem_root)))
|
2006-02-24 21:50:36 +01:00
|
|
|
goto err_with_lex_cleanup;
|
Bug#25411 (trigger code truncated), PART II
Bug 28127 (Some valid identifiers names are not parsed correctly)
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
This patch is the second part of a major cleanup, required to fix
Bug 25411 (trigger code truncated).
The root cause of the issue stems from the function skip_rear_comments,
which was a work around to remove "extra" "*/" characters from the query
text, when parsing a query and reusing the text fragments to represent a
view, trigger, function or stored procedure.
The reason for this work around is that "special comments",
like /*!50002 XXX */, were not parsed properly, so that a query like:
AAA /*!50002 BBB */ CCC
would be seen by the parser as "AAA BBB */ CCC" when the current version
is greater or equal to 5.0.2
The root cause of this stems from how special comments are parsed.
Special comments are really out-of-bound text that appear inside a query,
that affects how the parser behave.
In nature, /*!50002 XXX */ in MySQL is similar to the C concept
of preprocessing :
#if VERSION >= 50002
XXX
#endif
Depending on the current VERSION of the server, either the special comment
should be expanded or it should be ignored, but in all cases the "text" of
the query should be re-written to strip the "/*!50002" and "*/" markers,
which does not belong to the SQL language itself.
Prior to this fix, these markers would leak into :
- the storage format for VIEW,
- the storage format for FUNCTION,
- the storage format for FUNCTION parameters, in mysql.proc (param_list),
- the storage format for PROCEDURE,
- the storage format for PROCEDURE parameters, in mysql.proc (param_list),
- the storage format for TRIGGER,
- the binary log used for replication.
In all cases, not only this cause format corruption, but also provide a vector
for dormant security issues, by allowing to tunnel code that will be activated
after an upgrade.
The proper solution is to deal with special comments strictly during parsing,
when accepting a query from the outside world.
Once a query is parsed and an object is created with a persistant
representation, this object should not arbitrarily mutate after an upgrade.
In short, special comments are a useful but limited feature for MYSQLdump,
when used at an *interface* level to facilitate import/export,
but bloating the server *internal* storage format is *not* the proper way
to deal with configuration management of the user logic.
With this fix:
- the Lex_input_stream class now acts as a comment pre-processor,
and either expands or ignore special comments on the fly.
- MYSQLlex and sql_yacc.yy have been cleaned up to strictly use the
public interface of Lex_input_stream. In particular, how the input stream
accepts or rejects a character is private to Lex_input_stream, and the
internal buffer pointers of that class are strictly private, and should not
be tempered with during parsing.
This caused many changes mostly in sql_lex.cc.
During the code cleanup in case MY_LEX_NUMBER_IDENT,
Bug 28127 (Some valid identifiers names are not parsed correctly)
was found and fixed.
By parsing special comments properly, and removing the function
'skip_rear_comments' [sic],
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
has been fixed as well.
2007-06-12 23:23:58 +02:00
|
|
|
|
|
|
|
on_table_name->str= (char*) lex.raw_trg_on_table_name_begin;
|
|
|
|
on_table_name->length= lex.raw_trg_on_table_name_end
|
|
|
|
- lex.raw_trg_on_table_name_begin;
|
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root))
|
|
|
|
goto err_with_lex_cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Let us check that we correctly update trigger definitions when we
|
|
|
|
rename tables with triggers.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) &&
|
|
|
|
!my_strcasecmp(table_alias_charset, lex.query_tables->table_name,
|
|
|
|
table_name));
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
if (names_only)
|
|
|
|
{
|
|
|
|
lex_end(&lex);
|
|
|
|
continue;
|
|
|
|
}
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2004-11-24 10:24:02 +01:00
|
|
|
/*
|
2006-07-01 23:51:10 +02:00
|
|
|
Gather all Item_trigger_field objects representing access to fields
|
|
|
|
in old/new versions of row in trigger into lists containing all such
|
|
|
|
objects for the triggers with same action and timing.
|
|
|
|
*/
|
|
|
|
triggers->trigger_fields[lex.trg_chistics.event]
|
|
|
|
[lex.trg_chistics.action_time]=
|
|
|
|
(Item_trigger_field *)(lex.trg_table_fields.first);
|
|
|
|
/*
|
|
|
|
Also let us bind these objects to Field objects in table being
|
2004-11-24 10:24:02 +01:00
|
|
|
opened.
|
|
|
|
|
2005-07-28 21:39:11 +02:00
|
|
|
We ignore errors here, because if even something is wrong we still
|
|
|
|
will be willing to open table to perform some operations (e.g.
|
|
|
|
SELECT)...
|
2004-11-24 10:24:02 +01:00
|
|
|
Anyway some things can be checked only during trigger execution.
|
|
|
|
*/
|
|
|
|
for (Item_trigger_field *trg_field=
|
|
|
|
(Item_trigger_field *)(lex.trg_table_fields.first);
|
|
|
|
trg_field;
|
|
|
|
trg_field= trg_field->next_trg_field)
|
2006-01-24 18:15:12 +01:00
|
|
|
{
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
trg_field->setup_field(thd, table,
|
2006-01-24 18:15:12 +01:00
|
|
|
&triggers->subject_table_grants[lex.trg_chistics.event]
|
|
|
|
[lex.trg_chistics.action_time]);
|
|
|
|
}
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2004-09-07 14:29:46 +02:00
|
|
|
lex_end(&lex);
|
|
|
|
}
|
A fix and a test case for
Bug#19022 "Memory bug when switching db during trigger execution"
Bug#17199 "Problem when view calls function from another database."
Bug#18444 "Fully qualified stored function names don't work correctly in
SELECT statements"
Documentation note: this patch introduces a change in behaviour of prepared
statements.
This patch adds a few new invariants with regard to how THD::db should
be used. These invariants should be preserved in future:
- one should never refer to THD::db by pointer and always make a deep copy
(strmake, strdup)
- one should never compare two databases by pointer, but use strncmp or
my_strncasecmp
- TABLE_LIST object table->db should be always initialized in the parser or
by creator of the object.
For prepared statements it means that if the current database is changed
after a statement is prepared, the database that was current at prepare
remains active. This also means that you can not prepare a statement that
implicitly refers to the current database if the latter is not set.
This is not documented, and therefore needs documentation. This is NOT a
change in behavior for almost all SQL statements except:
- ALTER TABLE t1 RENAME t2
- OPTIMIZE TABLE t1
- ANALYZE TABLE t1
- TRUNCATE TABLE t1 --
until this patch t1 or t2 could be evaluated at the first execution of
prepared statement.
CURRENT_DATABASE() still works OK and is evaluated at every execution
of prepared statement.
Note, that in stored routines this is not an issue as the default
database is the database of the stored procedure and "use" statement
is prohibited in stored routines.
This patch makes obsolete the use of check_db_used (it was never used in the
old code too) and all other places that check for table->db and assign it
from THD::db if it's NULL, except the parser.
How this patch was created: THD::{db,db_length} were replaced with a
LEX_STRING, THD::db. All the places that refer to THD::{db,db_length} were
manually checked and:
- if the place uses thd->db by pointer, it was fixed to make a deep copy
- if a place compared two db pointers, it was fixed to compare them by value
(via strcmp/my_strcasecmp, whatever was approproate)
Then this intermediate patch was used to write a smaller patch that does the
same thing but without a rename.
TODO in 5.1:
- remove check_db_used
- deploy THD::set_db in mysql_change_db
See also comments to individual files.
2006-06-26 22:47:52 +02:00
|
|
|
thd->reset_db(save_db.str, save_db.length);
|
2004-09-07 14:29:46 +02:00
|
|
|
thd->lex= old_lex;
|
2005-11-23 01:49:44 +01:00
|
|
|
thd->spcont= save_spcont;
|
2005-07-28 21:39:11 +02:00
|
|
|
thd->variables.sql_mode= save_sql_mode;
|
2004-09-07 14:29:46 +02:00
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
|
|
|
err_with_lex_cleanup:
|
|
|
|
// QQ: anything else ?
|
|
|
|
lex_end(&lex);
|
|
|
|
thd->lex= old_lex;
|
2005-11-22 23:50:37 +01:00
|
|
|
thd->spcont= save_spcont;
|
2005-07-28 21:39:11 +02:00
|
|
|
thd->variables.sql_mode= save_sql_mode;
|
A fix and a test case for
Bug#19022 "Memory bug when switching db during trigger execution"
Bug#17199 "Problem when view calls function from another database."
Bug#18444 "Fully qualified stored function names don't work correctly in
SELECT statements"
Documentation note: this patch introduces a change in behaviour of prepared
statements.
This patch adds a few new invariants with regard to how THD::db should
be used. These invariants should be preserved in future:
- one should never refer to THD::db by pointer and always make a deep copy
(strmake, strdup)
- one should never compare two databases by pointer, but use strncmp or
my_strncasecmp
- TABLE_LIST object table->db should be always initialized in the parser or
by creator of the object.
For prepared statements it means that if the current database is changed
after a statement is prepared, the database that was current at prepare
remains active. This also means that you can not prepare a statement that
implicitly refers to the current database if the latter is not set.
This is not documented, and therefore needs documentation. This is NOT a
change in behavior for almost all SQL statements except:
- ALTER TABLE t1 RENAME t2
- OPTIMIZE TABLE t1
- ANALYZE TABLE t1
- TRUNCATE TABLE t1 --
until this patch t1 or t2 could be evaluated at the first execution of
prepared statement.
CURRENT_DATABASE() still works OK and is evaluated at every execution
of prepared statement.
Note, that in stored routines this is not an issue as the default
database is the database of the stored procedure and "use" statement
is prohibited in stored routines.
This patch makes obsolete the use of check_db_used (it was never used in the
old code too) and all other places that check for table->db and assign it
from THD::db if it's NULL, except the parser.
How this patch was created: THD::{db,db_length} were replaced with a
LEX_STRING, THD::db. All the places that refer to THD::{db,db_length} were
manually checked and:
- if the place uses thd->db by pointer, it was fixed to make a deep copy
- if a place compared two db pointers, it was fixed to compare them by value
(via strcmp/my_strcasecmp, whatever was approproate)
Then this intermediate patch was used to write a smaller patch that does the
same thing but without a rename.
TODO in 5.1:
- remove check_db_used
- deploy THD::set_db in mysql_change_db
See also comments to individual files.
2006-06-26 22:47:52 +02:00
|
|
|
thd->reset_db(save_db.str, save_db.length);
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
We don't care about this error message much because .TRG files will
|
|
|
|
be merged into .FRM anyway.
|
|
|
|
*/
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_WRONG_OBJECT, MYF(0),
|
2007-06-14 17:23:55 +02:00
|
|
|
table_name, TRG_EXT + 1, "TRIGGER");
|
2004-09-07 14:29:46 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2005-07-19 18:06:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Obtains and returns trigger metadata
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
get_trigger_info()
|
|
|
|
thd - current thread context
|
|
|
|
event - trigger event type
|
|
|
|
time_type - trigger action time
|
|
|
|
name - returns name of trigger
|
|
|
|
stmt - returns statement of trigger
|
2005-07-28 21:39:11 +02:00
|
|
|
sql_mode - returns sql_mode of trigger
|
2005-11-10 20:25:03 +01:00
|
|
|
definer_user - returns definer/creator of trigger. The caller is
|
|
|
|
responsible to allocate enough space for storing definer
|
|
|
|
information.
|
2005-07-19 18:06:49 +02:00
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
|
|
|
trg_action_time_type time_type,
|
|
|
|
LEX_STRING *trigger_name,
|
2005-07-28 21:39:11 +02:00
|
|
|
LEX_STRING *trigger_stmt,
|
2005-11-10 20:25:03 +01:00
|
|
|
ulong *sql_mode,
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
LEX_STRING *definer,
|
|
|
|
LEX_STRING *client_cs_name,
|
|
|
|
LEX_STRING *connection_cl_name,
|
|
|
|
LEX_STRING *db_cl_name)
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
|
|
|
sp_head *body;
|
|
|
|
DBUG_ENTER("get_trigger_info");
|
|
|
|
if ((body= bodies[event][time_type]))
|
|
|
|
{
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
Stored_program_creation_ctx *creation_ctx=
|
|
|
|
bodies[event][time_type]->get_creation_ctx();
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
*trigger_name= body->m_name;
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
*trigger_stmt= body->m_body_utf8;
|
2005-07-28 21:39:11 +02:00
|
|
|
*sql_mode= body->m_sql_mode;
|
2005-11-10 20:25:03 +01:00
|
|
|
|
|
|
|
if (body->m_chistics->suid == SP_IS_NOT_SUID)
|
|
|
|
{
|
|
|
|
definer->str[0]= 0;
|
|
|
|
definer->length= 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
definer->length= strxmov(definer->str, body->m_definer_user.str, "@",
|
|
|
|
body->m_definer_host.str, NullS) - definer->str;
|
|
|
|
}
|
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
lex_string_set(client_cs_name,
|
|
|
|
creation_ctx->get_client_cs()->csname);
|
|
|
|
|
|
|
|
lex_string_set(connection_cl_name,
|
|
|
|
creation_ctx->get_connection_cl()->name);
|
|
|
|
|
|
|
|
lex_string_set(db_cl_name,
|
|
|
|
creation_ctx->get_db_cl()->name);
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
void Table_triggers_list::get_trigger_info(THD *thd,
|
|
|
|
int trigger_idx,
|
|
|
|
LEX_STRING *trigger_name,
|
|
|
|
ulonglong *sql_mode,
|
|
|
|
LEX_STRING *sql_original_stmt,
|
|
|
|
LEX_STRING *client_cs_name,
|
|
|
|
LEX_STRING *connection_cl_name,
|
|
|
|
LEX_STRING *db_cl_name)
|
|
|
|
{
|
|
|
|
List_iterator_fast<LEX_STRING> it_trigger_name(names_list);
|
|
|
|
List_iterator_fast<ulonglong> it_sql_mode(definition_modes_list);
|
|
|
|
List_iterator_fast<LEX_STRING> it_sql_orig_stmt(definitions_list);
|
|
|
|
List_iterator_fast<LEX_STRING> it_client_cs_name(client_cs_names);
|
|
|
|
List_iterator_fast<LEX_STRING> it_connection_cl_name(connection_cl_names);
|
|
|
|
List_iterator_fast<LEX_STRING> it_db_cl_name(db_cl_names);
|
|
|
|
|
|
|
|
for (int i = 0; i < trigger_idx; ++i)
|
|
|
|
{
|
|
|
|
it_trigger_name.next_fast();
|
|
|
|
it_sql_mode.next_fast();
|
|
|
|
it_sql_orig_stmt.next_fast();
|
|
|
|
|
|
|
|
it_client_cs_name.next_fast();
|
|
|
|
it_connection_cl_name.next_fast();
|
|
|
|
it_db_cl_name.next_fast();
|
|
|
|
}
|
|
|
|
|
|
|
|
*trigger_name= *(it_trigger_name++);
|
|
|
|
*sql_mode= *(it_sql_mode++);
|
|
|
|
*sql_original_stmt= *(it_sql_orig_stmt++);
|
|
|
|
|
|
|
|
*client_cs_name= *(it_client_cs_name++);
|
|
|
|
*connection_cl_name= *(it_connection_cl_name++);
|
|
|
|
*db_cl_name= *(it_db_cl_name++);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Table_triggers_list::find_trigger_by_name(const LEX_STRING *trg_name)
|
|
|
|
{
|
|
|
|
List_iterator_fast<LEX_STRING> it(names_list);
|
|
|
|
|
|
|
|
for (int i = 0; ; ++i)
|
|
|
|
{
|
|
|
|
LEX_STRING *cur_name= it++;
|
|
|
|
|
|
|
|
if (!cur_name)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (strcmp(cur_name->str, trg_name->str) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
/**
|
2005-07-19 18:06:49 +02:00
|
|
|
Find trigger's table from trigger identifier and add it to
|
|
|
|
the statement table list.
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
@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.
|
2005-07-19 18:06:49 +02:00
|
|
|
*/
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
bool add_table_for_trigger(THD *thd,
|
Patch for the following bugs:
- BUG#11986: Stored routines and triggers can fail if the code
has a non-ascii symbol
- BUG#16291: mysqldump corrupts string-constants with non-ascii-chars
- BUG#19443: INFORMATION_SCHEMA does not support charsets properly
- BUG#21249: Character set of SP-var can be ignored
- BUG#25212: Character set of string constant is ignored (stored routines)
- BUG#25221: Character set of string constant is ignored (triggers)
There were a few general problems that caused these bugs:
1. Character set information of the original (definition) query for views,
triggers, stored routines and events was lost.
2. mysqldump output query in client character set, which can be
inappropriate to encode definition-query.
3. INFORMATION_SCHEMA used strings with mixed encodings to display object
definition;
1. No query-definition-character set.
In order to compile query into execution code, some extra data (such as
environment variables or the database character set) is used. The problem
here was that this context was not preserved. So, on the next load it can
differ from the original one, thus the result will be different.
The context contains the following data:
- client character set;
- connection collation (character set and collation);
- collation of the owner database;
The fix is to store this context and use it each time we parse (compile)
and execute the object (stored routine, trigger, ...).
2. Wrong mysqldump-output.
The original query can contain several encodings (by means of character set
introducers). The problem here was that we tried to convert original query
to the mysqldump-client character set.
Moreover, we stored queries in different character sets for different
objects (views, for one, used UTF8, triggers used original character set).
The solution is
- to store definition queries in the original character set;
- to change SHOW CREATE statement to output definition query in the
binary character set (i.e. without any conversion);
- introduce SHOW CREATE TRIGGER statement;
- to dump special statements to switch the context to the original one
before dumping and restore it afterwards.
Note, in order to preserve the database collation at the creation time,
additional ALTER DATABASE might be used (to temporary switch the database
collation back to the original value). In this case, ALTER DATABASE
privilege will be required. This is a backward-incompatible change.
3. INFORMATION_SCHEMA showed non-UTF8 strings
The fix is to generate UTF8-query during the parsing, store it in the object
and show it in the INFORMATION_SCHEMA.
Basically, the idea is to create a copy of the original query convert it to
UTF8. Character set introducers are removed and all text literals are
converted to UTF8.
This UTF8 query is intended to provide user-readable output. It must not be
used to recreate the object. Specialized SHOW CREATE statements should be
used for this.
The reason for this limitation is the following: the original query can
contain symbols from several character sets (by means of character set
introducers).
Example:
- original query:
CREATE VIEW v1 AS SELECT _cp1251 'Hello' AS c1;
- UTF8 query (for INFORMATION_SCHEMA):
CREATE VIEW v1 AS SELECT 'Hello' AS c1;
2007-06-28 19:34:54 +02:00
|
|
|
const sp_name *trg_name,
|
2007-06-14 17:23:55 +02:00
|
|
|
bool if_exists,
|
|
|
|
TABLE_LIST **table)
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
|
|
|
LEX *lex= thd->lex;
|
2007-06-14 17:23:55 +02:00
|
|
|
char trn_path_buff[FN_REFLEN];
|
|
|
|
LEX_STRING trn_path= { trn_path_buff, 0 };
|
|
|
|
LEX_STRING tbl_name;
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
DBUG_ENTER("add_table_for_trigger");
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
build_trn_path(thd, trg_name, &trn_path);
|
2005-07-19 18:06:49 +02:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
if (check_trn_exists(&trn_path))
|
2005-07-19 18:06:49 +02:00
|
|
|
{
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
if (if_exists)
|
|
|
|
{
|
|
|
|
push_warning_printf(thd,
|
2007-06-14 17:23:55 +02:00
|
|
|
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
|
|
|
ER_TRG_DOES_NOT_EXIST,
|
|
|
|
ER(ER_TRG_DOES_NOT_EXIST));
|
|
|
|
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
*table= NULL;
|
2007-06-14 17:23:55 +02:00
|
|
|
|
|
|
|
DBUG_RETURN(FALSE);
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
}
|
|
|
|
|
2005-07-19 18:06:49 +02:00
|
|
|
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
2007-06-14 17:23:55 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2005-07-19 18:06:49 +02:00
|
|
|
}
|
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
|
|
|
|
DBUG_RETURN(TRUE);
|
2005-07-19 18:06:49 +02:00
|
|
|
|
|
|
|
/* We need to reset statement table list to be PS/SP friendly. */
|
|
|
|
lex->query_tables= 0;
|
|
|
|
lex->query_tables_last= &lex->query_tables;
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
*table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str,
|
|
|
|
tbl_name.str, TL_IGNORE);
|
Bug#23703 (DROP TRIGGER needs an IF EXISTS)
This change set implements the DROP TRIGGER IF EXISTS functionality.
This fix is considered a bug and not a feature, because without it,
there is no known method to write a database creation script that can create
a trigger without failing, when executed on a database that may or may not
contain already a trigger of the same name.
Implementing this functionality closes an orthogonality gap between triggers
and stored procedures / stored functions (which do support the DROP IF
EXISTS syntax).
In sql_trigger.cc, in mysql_create_or_drop_trigger,
the code has been reordered to:
- perform the tests that do not depend on the file system (access()),
- get the locks (wait_if_global_read_lock, LOCK_open)
- call access()
- perform the operation
- write to the binlog
- unlock (LOCK_open, start_waiting_global_read_lock)
This is to ensure that all the code that depends on the presence of the
trigger file is executed in the same critical section,
and prevents race conditions similar to the case fixed by Bug 14262 :
- thread 1 executes DROP TRIGGER IF EXISTS, access() returns a failure
- thread 2 executes CREATE TRIGGER
- thread 2 logs CREATE TRIGGER
- thread 1 logs DROP TRIGGER IF EXISTS
The patch itself is based on code contributed by the MySQL community,
under the terms of the Contributor License Agreement (See Bug 18161).
2006-11-13 23:40:22 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
DBUG_RETURN(*table ? FALSE : TRUE);
|
2005-07-19 18:06:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Drop all triggers for table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
drop_all_triggers()
|
|
|
|
thd - current thread context
|
|
|
|
db - schema for table
|
|
|
|
name - name for table
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
The calling thread should hold the LOCK_open mutex;
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
False - success
|
|
|
|
True - error
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name)
|
|
|
|
{
|
|
|
|
TABLE table;
|
|
|
|
char path[FN_REFLEN];
|
|
|
|
bool result= 0;
|
|
|
|
DBUG_ENTER("drop_all_triggers");
|
|
|
|
|
|
|
|
bzero(&table, sizeof(table));
|
|
|
|
init_alloc_root(&table.mem_root, 8192, 0);
|
|
|
|
|
|
|
|
if (Table_triggers_list::check_n_load(thd, db, name, &table, 1))
|
|
|
|
{
|
|
|
|
result= 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (table.triggers)
|
|
|
|
{
|
|
|
|
LEX_STRING *trigger;
|
|
|
|
List_iterator_fast<LEX_STRING> it_name(table.triggers->names_list);
|
|
|
|
|
|
|
|
while ((trigger= it_name++))
|
|
|
|
{
|
|
|
|
if (rm_trigname_file(path, db, trigger->str))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Instead of immediately bailing out with error if we were unable
|
|
|
|
to remove .TRN file we will try to drop other files.
|
|
|
|
*/
|
|
|
|
result= 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rm_trigger_file(path, db, name))
|
|
|
|
{
|
|
|
|
result= 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
if (table.triggers)
|
|
|
|
delete table.triggers;
|
|
|
|
free_root(&table.mem_root, MYF(0));
|
|
|
|
DBUG_RETURN(result);
|
|
|
|
}
|
2005-08-15 17:15:12 +02:00
|
|
|
|
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
/*
|
|
|
|
Update .TRG file after renaming triggers' subject table
|
|
|
|
(change name of table in triggers' definitions).
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
change_table_name_in_triggers()
|
|
|
|
thd Thread context
|
|
|
|
db_name Database of subject table
|
|
|
|
old_table_name Old subject table's name
|
|
|
|
new_table_name New subject table's name
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
FALSE Success
|
|
|
|
TRUE Failure
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
|
|
|
Table_triggers_list::change_table_name_in_triggers(THD *thd,
|
|
|
|
const char *db_name,
|
|
|
|
LEX_STRING *old_table_name,
|
|
|
|
LEX_STRING *new_table_name)
|
|
|
|
{
|
|
|
|
char path_buff[FN_REFLEN];
|
|
|
|
LEX_STRING *def, *on_table_name, new_def;
|
|
|
|
ulong save_sql_mode= thd->variables.sql_mode;
|
|
|
|
List_iterator_fast<LEX_STRING> it_def(definitions_list);
|
|
|
|
List_iterator_fast<LEX_STRING> it_on_table_name(on_table_names_list);
|
|
|
|
List_iterator_fast<ulonglong> it_mode(definition_modes_list);
|
|
|
|
uint on_q_table_name_len, before_on_len;
|
|
|
|
String buff;
|
|
|
|
|
|
|
|
DBUG_ASSERT(definitions_list.elements == on_table_names_list.elements &&
|
|
|
|
definitions_list.elements == definition_modes_list.elements);
|
|
|
|
|
|
|
|
while ((def= it_def++))
|
|
|
|
{
|
|
|
|
on_table_name= it_on_table_name++;
|
2006-11-30 02:40:42 +01:00
|
|
|
thd->variables.sql_mode= (ulong) *(it_mode++);
|
2006-02-24 21:50:36 +01:00
|
|
|
|
|
|
|
/* Construct CREATE TRIGGER statement with new table name. */
|
|
|
|
buff.length(0);
|
Bug#25411 (trigger code truncated), PART II
Bug 28127 (Some valid identifiers names are not parsed correctly)
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
This patch is the second part of a major cleanup, required to fix
Bug 25411 (trigger code truncated).
The root cause of the issue stems from the function skip_rear_comments,
which was a work around to remove "extra" "*/" characters from the query
text, when parsing a query and reusing the text fragments to represent a
view, trigger, function or stored procedure.
The reason for this work around is that "special comments",
like /*!50002 XXX */, were not parsed properly, so that a query like:
AAA /*!50002 BBB */ CCC
would be seen by the parser as "AAA BBB */ CCC" when the current version
is greater or equal to 5.0.2
The root cause of this stems from how special comments are parsed.
Special comments are really out-of-bound text that appear inside a query,
that affects how the parser behave.
In nature, /*!50002 XXX */ in MySQL is similar to the C concept
of preprocessing :
#if VERSION >= 50002
XXX
#endif
Depending on the current VERSION of the server, either the special comment
should be expanded or it should be ignored, but in all cases the "text" of
the query should be re-written to strip the "/*!50002" and "*/" markers,
which does not belong to the SQL language itself.
Prior to this fix, these markers would leak into :
- the storage format for VIEW,
- the storage format for FUNCTION,
- the storage format for FUNCTION parameters, in mysql.proc (param_list),
- the storage format for PROCEDURE,
- the storage format for PROCEDURE parameters, in mysql.proc (param_list),
- the storage format for TRIGGER,
- the binary log used for replication.
In all cases, not only this cause format corruption, but also provide a vector
for dormant security issues, by allowing to tunnel code that will be activated
after an upgrade.
The proper solution is to deal with special comments strictly during parsing,
when accepting a query from the outside world.
Once a query is parsed and an object is created with a persistant
representation, this object should not arbitrarily mutate after an upgrade.
In short, special comments are a useful but limited feature for MYSQLdump,
when used at an *interface* level to facilitate import/export,
but bloating the server *internal* storage format is *not* the proper way
to deal with configuration management of the user logic.
With this fix:
- the Lex_input_stream class now acts as a comment pre-processor,
and either expands or ignore special comments on the fly.
- MYSQLlex and sql_yacc.yy have been cleaned up to strictly use the
public interface of Lex_input_stream. In particular, how the input stream
accepts or rejects a character is private to Lex_input_stream, and the
internal buffer pointers of that class are strictly private, and should not
be tempered with during parsing.
This caused many changes mostly in sql_lex.cc.
During the code cleanup in case MY_LEX_NUMBER_IDENT,
Bug 28127 (Some valid identifiers names are not parsed correctly)
was found and fixed.
By parsing special comments properly, and removing the function
'skip_rear_comments' [sic],
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
has been fixed as well.
2007-06-12 23:23:58 +02:00
|
|
|
|
|
|
|
/* WARNING: 'on_table_name' is supposed to point inside 'def' */
|
|
|
|
DBUG_ASSERT(on_table_name->str > def->str);
|
|
|
|
DBUG_ASSERT(on_table_name->str < (def->str + def->length));
|
2006-02-24 21:50:36 +01:00
|
|
|
before_on_len= on_table_name->str - def->str;
|
Bug#25411 (trigger code truncated), PART II
Bug 28127 (Some valid identifiers names are not parsed correctly)
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
This patch is the second part of a major cleanup, required to fix
Bug 25411 (trigger code truncated).
The root cause of the issue stems from the function skip_rear_comments,
which was a work around to remove "extra" "*/" characters from the query
text, when parsing a query and reusing the text fragments to represent a
view, trigger, function or stored procedure.
The reason for this work around is that "special comments",
like /*!50002 XXX */, were not parsed properly, so that a query like:
AAA /*!50002 BBB */ CCC
would be seen by the parser as "AAA BBB */ CCC" when the current version
is greater or equal to 5.0.2
The root cause of this stems from how special comments are parsed.
Special comments are really out-of-bound text that appear inside a query,
that affects how the parser behave.
In nature, /*!50002 XXX */ in MySQL is similar to the C concept
of preprocessing :
#if VERSION >= 50002
XXX
#endif
Depending on the current VERSION of the server, either the special comment
should be expanded or it should be ignored, but in all cases the "text" of
the query should be re-written to strip the "/*!50002" and "*/" markers,
which does not belong to the SQL language itself.
Prior to this fix, these markers would leak into :
- the storage format for VIEW,
- the storage format for FUNCTION,
- the storage format for FUNCTION parameters, in mysql.proc (param_list),
- the storage format for PROCEDURE,
- the storage format for PROCEDURE parameters, in mysql.proc (param_list),
- the storage format for TRIGGER,
- the binary log used for replication.
In all cases, not only this cause format corruption, but also provide a vector
for dormant security issues, by allowing to tunnel code that will be activated
after an upgrade.
The proper solution is to deal with special comments strictly during parsing,
when accepting a query from the outside world.
Once a query is parsed and an object is created with a persistant
representation, this object should not arbitrarily mutate after an upgrade.
In short, special comments are a useful but limited feature for MYSQLdump,
when used at an *interface* level to facilitate import/export,
but bloating the server *internal* storage format is *not* the proper way
to deal with configuration management of the user logic.
With this fix:
- the Lex_input_stream class now acts as a comment pre-processor,
and either expands or ignore special comments on the fly.
- MYSQLlex and sql_yacc.yy have been cleaned up to strictly use the
public interface of Lex_input_stream. In particular, how the input stream
accepts or rejects a character is private to Lex_input_stream, and the
internal buffer pointers of that class are strictly private, and should not
be tempered with during parsing.
This caused many changes mostly in sql_lex.cc.
During the code cleanup in case MY_LEX_NUMBER_IDENT,
Bug 28127 (Some valid identifiers names are not parsed correctly)
was found and fixed.
By parsing special comments properly, and removing the function
'skip_rear_comments' [sic],
Bug 26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
has been fixed as well.
2007-06-12 23:23:58 +02:00
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
buff.append(def->str, before_on_len);
|
|
|
|
buff.append(STRING_WITH_LEN("ON "));
|
|
|
|
append_identifier(thd, &buff, new_table_name->str, new_table_name->length);
|
2006-03-04 14:55:06 +01:00
|
|
|
buff.append(STRING_WITH_LEN(" "));
|
2006-02-24 21:50:36 +01:00
|
|
|
on_q_table_name_len= buff.length() - before_on_len;
|
|
|
|
buff.append(on_table_name->str + on_table_name->length,
|
|
|
|
def->length - (before_on_len + on_table_name->length));
|
|
|
|
/*
|
|
|
|
It is OK to allocate some memory on table's MEM_ROOT since this
|
|
|
|
table instance will be thrown out at the end of rename anyway.
|
|
|
|
*/
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
new_def.str= (char*) memdup_root(&trigger_table->mem_root, buff.ptr(),
|
|
|
|
buff.length());
|
2006-02-24 21:50:36 +01:00
|
|
|
new_def.length= buff.length();
|
|
|
|
on_table_name->str= new_def.str + before_on_len;
|
|
|
|
on_table_name->length= on_q_table_name_len;
|
|
|
|
*def= new_def;
|
|
|
|
}
|
|
|
|
|
|
|
|
thd->variables.sql_mode= save_sql_mode;
|
|
|
|
|
|
|
|
if (thd->is_fatal_error)
|
|
|
|
return TRUE; /* OOM */
|
|
|
|
|
|
|
|
if (save_trigger_file(this, db_name, new_table_name->str))
|
|
|
|
return TRUE;
|
|
|
|
if (rm_trigger_file(path_buff, db_name, old_table_name->str))
|
|
|
|
{
|
|
|
|
(void) rm_trigger_file(path_buff, db_name, new_table_name->str);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Iterate though Table_triggers_list::names_list list and update .TRN files
|
|
|
|
after renaming triggers' subject table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
change_table_name_in_trignames()
|
|
|
|
db_name Database of subject table
|
|
|
|
new_table_name New subject table's name
|
|
|
|
stopper Pointer to Table_triggers_list::names_list at
|
|
|
|
which we should stop updating.
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
0 Success
|
|
|
|
non-0 Failure, pointer to Table_triggers_list::names_list element
|
|
|
|
for which update failed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LEX_STRING*
|
|
|
|
Table_triggers_list::change_table_name_in_trignames(const char *db_name,
|
|
|
|
LEX_STRING *new_table_name,
|
|
|
|
LEX_STRING *stopper)
|
|
|
|
{
|
2006-02-27 18:00:07 +01:00
|
|
|
char trigname_buff[FN_REFLEN];
|
2006-02-24 21:50:36 +01:00
|
|
|
struct st_trigname trigname;
|
2006-02-27 18:00:07 +01:00
|
|
|
LEX_STRING trigname_file;
|
2006-02-24 21:50:36 +01:00
|
|
|
LEX_STRING *trigger;
|
|
|
|
List_iterator_fast<LEX_STRING> it_name(names_list);
|
|
|
|
|
|
|
|
while ((trigger= it_name++) != stopper)
|
|
|
|
{
|
2006-02-27 18:00:07 +01:00
|
|
|
trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
|
|
|
|
db_name, trigger->str,
|
2007-06-14 17:23:55 +02:00
|
|
|
TRN_EXT, 0);
|
2006-02-24 21:50:36 +01:00
|
|
|
trigname_file.str= trigname_buff;
|
|
|
|
|
|
|
|
trigname.trigger_table= *new_table_name;
|
|
|
|
|
2006-02-27 18:00:07 +01:00
|
|
|
if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
(uchar*)&trigname, trigname_file_parameters,
|
2006-02-27 18:00:07 +01:00
|
|
|
0))
|
2006-02-24 21:50:36 +01:00
|
|
|
return trigger;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-02 19:14:48 +02:00
|
|
|
/**
|
|
|
|
@brief Update .TRG and .TRN files after renaming triggers' subject table.
|
2006-02-24 21:50:36 +01:00
|
|
|
|
2007-07-02 19:14:48 +02:00
|
|
|
@param[in,out] thd Thread context
|
|
|
|
@param[in] db Old database of subject table
|
|
|
|
@param[in] old_table Old name of subject table
|
|
|
|
@param[in] new_db New database for subject table
|
|
|
|
@param[in] new_table New name of subject table
|
2006-02-24 21:50:36 +01:00
|
|
|
|
2007-07-02 19:14:48 +02:00
|
|
|
@note
|
2006-02-24 21:50:36 +01:00
|
|
|
This method tries to leave trigger related files in consistent state,
|
|
|
|
i.e. it either will complete successfully, or will fail leaving files
|
|
|
|
in their initial state.
|
2006-03-24 12:58:18 +01:00
|
|
|
Also this method assumes that subject table is not renamed to itself.
|
2007-07-02 19:14:48 +02:00
|
|
|
This method needs to be called under an exclusive table name lock.
|
2006-02-24 21:50:36 +01:00
|
|
|
|
2007-07-02 19:14:48 +02:00
|
|
|
@retval FALSE Success
|
|
|
|
@retval TRUE Error
|
2006-02-24 21:50:36 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
|
|
|
const char *old_table,
|
|
|
|
const char *new_db,
|
|
|
|
const char *new_table)
|
|
|
|
{
|
|
|
|
TABLE table;
|
|
|
|
bool result= 0;
|
|
|
|
LEX_STRING *err_trigname;
|
|
|
|
DBUG_ENTER("change_table_name");
|
|
|
|
|
|
|
|
bzero(&table, sizeof(table));
|
|
|
|
init_alloc_root(&table.mem_root, 8192, 0);
|
|
|
|
|
2007-07-02 19:14:48 +02:00
|
|
|
/*
|
|
|
|
This method interfaces the mysql server code protected by
|
|
|
|
either LOCK_open mutex or with an exclusive table name lock.
|
|
|
|
In the future, only an exclusive table name lock will be enough.
|
|
|
|
*/
|
|
|
|
#ifndef DBUG_OFF
|
2007-07-14 03:22:24 +02:00
|
|
|
uchar key[MAX_DBKEY_LENGTH];
|
|
|
|
uint key_length= (uint) (strmov(strmov((char*)&key[0], db)+1,
|
|
|
|
old_table)-(char*)&key[0])+1;
|
|
|
|
|
2007-07-02 19:14:48 +02:00
|
|
|
if (!is_table_name_exclusively_locked_by_this_thread(thd, key, key_length))
|
|
|
|
safe_mutex_assert_owner(&LOCK_open);
|
|
|
|
#endif
|
2006-02-24 21:50:36 +01:00
|
|
|
|
2006-03-24 12:58:18 +01:00
|
|
|
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
|
|
|
my_strcasecmp(table_alias_charset, old_table, new_table));
|
|
|
|
|
2006-02-24 21:50:36 +01:00
|
|
|
if (Table_triggers_list::check_n_load(thd, db, old_table, &table, TRUE))
|
|
|
|
{
|
|
|
|
result= 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (table.triggers)
|
|
|
|
{
|
2006-05-19 14:01:04 +02:00
|
|
|
LEX_STRING old_table_name= { (char *) old_table, strlen(old_table) };
|
|
|
|
LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
|
2006-02-24 21:50:36 +01:00
|
|
|
/*
|
|
|
|
Since triggers should be in the same schema as their subject tables
|
|
|
|
moving table with them between two schemas raises too many questions.
|
|
|
|
(E.g. what should happen if in new schema we already have trigger
|
|
|
|
with same name ?).
|
|
|
|
*/
|
|
|
|
if (my_strcasecmp(table_alias_charset, db, new_db))
|
|
|
|
{
|
|
|
|
my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0));
|
|
|
|
result= 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (table.triggers->change_table_name_in_triggers(thd, db,
|
|
|
|
&old_table_name,
|
|
|
|
&new_table_name))
|
|
|
|
{
|
|
|
|
result= 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if ((err_trigname= table.triggers->change_table_name_in_trignames(
|
|
|
|
db, &new_table_name, 0)))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
If we were unable to update one of .TRN files properly we will
|
|
|
|
revert all changes that we have done and report about error.
|
|
|
|
We assume that we will be able to undo our changes without errors
|
|
|
|
(we can't do much if there will be an error anyway).
|
|
|
|
*/
|
|
|
|
(void) table.triggers->change_table_name_in_trignames(db,
|
|
|
|
&old_table_name,
|
|
|
|
err_trigname);
|
|
|
|
(void) table.triggers->change_table_name_in_triggers(thd, db,
|
|
|
|
&new_table_name,
|
|
|
|
&old_table_name);
|
|
|
|
result= 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
delete table.triggers;
|
|
|
|
free_root(&table.mem_root, MYF(0));
|
|
|
|
DBUG_RETURN(result);
|
|
|
|
}
|
|
|
|
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
/**
|
|
|
|
Execute trigger for given (event, time) pair.
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
The operation executes trigger for the specified event (insert, update,
|
|
|
|
delete) and time (after, before) if it is set.
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
@param thd
|
|
|
|
@param event
|
2007-08-15 15:43:08 +02:00
|
|
|
@param time_type
|
2007-06-14 17:23:55 +02:00
|
|
|
@param old_row_is_record1
|
2006-02-01 11:28:45 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
@return Error status.
|
|
|
|
@retval FALSE on success.
|
|
|
|
@retval TRUE on error.
|
|
|
|
*/
|
2006-02-01 11:28:45 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
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;
|
|
|
|
Sub_statement_state statement_state;
|
2005-11-10 20:25:03 +01:00
|
|
|
sp_head *sp_trigger= bodies[event][time_type];
|
|
|
|
|
2007-07-16 21:31:36 +02:00
|
|
|
if (sp_trigger == NULL)
|
2007-06-14 17:23:55 +02:00
|
|
|
return FALSE;
|
2006-02-06 13:23:17 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
if (old_row_is_record1)
|
|
|
|
{
|
|
|
|
old_field= record1_field;
|
|
|
|
new_field= trigger_table->field;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_field= record1_field;
|
|
|
|
old_field= trigger_table->field;
|
|
|
|
}
|
2007-07-16 21:31:36 +02:00
|
|
|
/*
|
|
|
|
This trigger must have been processed by the pre-locking
|
|
|
|
algorithm.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(trigger_table->pos_in_table_list->trg_event_map &
|
|
|
|
static_cast<uint>(1 << static_cast<int>(event)));
|
2006-02-06 13:23:17 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
err_status=
|
2007-07-16 21:31:36 +02:00
|
|
|
sp_trigger->execute_trigger(thd,
|
|
|
|
&trigger_table->s->db,
|
|
|
|
&trigger_table->s->table_name,
|
|
|
|
&subject_table_grants[event][time_type]);
|
2005-11-10 20:25:03 +01:00
|
|
|
|
2007-06-14 17:23:55 +02:00
|
|
|
thd->restore_sub_statement_state(&statement_state);
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
return err_status;
|
2005-08-15 17:15:12 +02:00
|
|
|
}
|
2005-11-20 19:47:07 +01:00
|
|
|
|
|
|
|
|
2006-07-01 23:51:10 +02:00
|
|
|
/*
|
|
|
|
Mark fields of subject table which we read/set in its triggers as such.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
mark_fields_used()
|
|
|
|
thd Current thread context
|
A fix and a test case for Bug#26141 mixing table types in trigger
causes full table lock on innodb table.
Also fixes Bug#28502 Triggers that update another innodb table
will block on X lock unnecessarily (duplciate).
Code review fixes.
Both bugs' synopses are misleading: InnoDB table is
not X locked. The statements, however, cannot proceed concurrently,
but this happens due to lock conflicts for tables used in triggers,
not for the InnoDB table.
If a user had an InnoDB table, and two triggers, AFTER UPDATE and
AFTER INSERT, competing for different resources (e.g. two distinct
MyISAM tables), then these two triggers would not be able to execute
concurrently. Moreover, INSERTS/UPDATES of the InnoDB table would
not be able to run concurrently.
The problem had other side-effects (see respective bug reports).
This behavior was a consequence of a shortcoming of the pre-locking
algorithm, which would not distinguish between different DML operations
(e.g. INSERT and DELETE) and pre-lock all the tables
that are used by any trigger defined on the subject table.
The idea of the fix is to extend the pre-locking algorithm to keep track,
for each table, what DML operation it is used for and not
load triggers that are known to never be fired.
2007-07-12 20:26:41 +02:00
|
|
|
event Type of event triggers for which we are going to ins
|
2006-07-01 23:51:10 +02:00
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
This method marks fields of subject table which are read/set in its
|
2006-07-06 11:33:23 +02:00
|
|
|
triggers as such (by properly updating TABLE::read_set/write_set)
|
2006-07-01 23:51:10 +02:00
|
|
|
and thus informs handler that values for these fields should be
|
|
|
|
retrieved/stored during execution of statement.
|
|
|
|
*/
|
|
|
|
|
2006-07-06 11:33:23 +02:00
|
|
|
void Table_triggers_list::mark_fields_used(trg_event_type event)
|
2006-07-01 23:51:10 +02:00
|
|
|
{
|
|
|
|
int action_time;
|
|
|
|
Item_trigger_field *trg_field;
|
|
|
|
|
|
|
|
for (action_time= 0; action_time < (int)TRG_ACTION_MAX; action_time++)
|
|
|
|
{
|
|
|
|
for (trg_field= trigger_fields[event][action_time]; trg_field;
|
|
|
|
trg_field= trg_field->next_trg_field)
|
|
|
|
{
|
|
|
|
/* We cannot mark fields which does not present in table. */
|
|
|
|
if (trg_field->field_idx != (uint)-1)
|
2006-07-06 11:33:23 +02:00
|
|
|
{
|
2007-01-27 02:46:45 +01:00
|
|
|
bitmap_set_bit(trigger_table->read_set, trg_field->field_idx);
|
2006-07-06 11:33:23 +02:00
|
|
|
if (trg_field->get_settable_routine_parameter())
|
2007-01-27 02:46:45 +01:00
|
|
|
bitmap_set_bit(trigger_table->write_set, trg_field->field_idx);
|
2006-07-06 11:33:23 +02:00
|
|
|
}
|
2006-07-01 23:51:10 +02:00
|
|
|
}
|
|
|
|
}
|
2007-01-27 02:46:45 +01:00
|
|
|
trigger_table->file->column_bitmaps_signal();
|
2006-07-01 23:51:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
/*
|
|
|
|
Trigger BUG#14090 compatibility hook
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
Handle_old_incorrect_sql_modes_hook::process_unknown_string()
|
|
|
|
unknown_key [in/out] reference on the line with unknown
|
|
|
|
parameter and the parsing point
|
|
|
|
base [in] base address for parameter writing (structure
|
|
|
|
like TABLE)
|
|
|
|
mem_root [in] MEM_ROOT for parameters allocation
|
|
|
|
end [in] the end of the configuration
|
|
|
|
|
|
|
|
NOTE: this hook process back compatibility for incorrectly written
|
|
|
|
sql_modes parameter (see BUG#14090).
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
FALSE OK
|
|
|
|
TRUE Error
|
|
|
|
*/
|
|
|
|
|
2006-01-05 23:47:49 +01:00
|
|
|
#define INVALID_SQL_MODES_LENGTH 13
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
bool
|
|
|
|
Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar* base,
|
2005-11-20 19:47:07 +01:00
|
|
|
MEM_ROOT *mem_root,
|
|
|
|
char *end)
|
|
|
|
{
|
2006-03-27 23:01:51 +02:00
|
|
|
DBUG_ENTER("Handle_old_incorrect_sql_modes_hook::process_unknown_string");
|
2006-11-27 00:47:38 +01:00
|
|
|
DBUG_PRINT("info", ("unknown key: %60s", unknown_key));
|
2006-01-05 23:47:49 +01:00
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end &&
|
|
|
|
unknown_key[INVALID_SQL_MODES_LENGTH] == '=' &&
|
|
|
|
!memcmp(unknown_key, STRING_WITH_LEN("sql_modes")))
|
|
|
|
{
|
2006-01-05 23:47:49 +01:00
|
|
|
char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1;
|
|
|
|
|
2005-11-20 19:47:07 +01:00
|
|
|
DBUG_PRINT("info", ("sql_modes affected by BUG#14090 detected"));
|
|
|
|
push_warning_printf(current_thd,
|
|
|
|
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
|
|
|
ER_OLD_FILE_FORMAT,
|
|
|
|
ER(ER_OLD_FILE_FORMAT),
|
|
|
|
(char *)path, "TRIGGER");
|
|
|
|
if (get_file_options_ulllist(ptr, end, unknown_key, base,
|
|
|
|
&sql_modes_parameters, mem_root))
|
|
|
|
{
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Set parsing pointer to the last symbol of string (\n)
|
|
|
|
1) to avoid problem with \0 in the junk after sql_modes
|
|
|
|
2) to speed up skipping this line by parser.
|
|
|
|
*/
|
|
|
|
unknown_key= ptr-1;
|
|
|
|
}
|
|
|
|
DBUG_RETURN(FALSE);
|
|
|
|
}
|
2006-03-27 23:01:51 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Trigger BUG#15921 compatibility hook. For details see
|
|
|
|
Handle_old_incorrect_sql_modes_hook::process_unknown_string().
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define INVALID_TRIGGER_TABLE_LENGTH 15
|
|
|
|
|
|
|
|
bool
|
|
|
|
Handle_old_incorrect_trigger_table_hook::
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root,
|
2006-03-27 23:01:51 +02:00
|
|
|
char *end)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Handle_old_incorrect_trigger_table_hook::process_unknown_string");
|
2006-11-27 00:47:38 +01:00
|
|
|
DBUG_PRINT("info", ("unknown key: %60s", unknown_key));
|
2006-03-27 23:01:51 +02:00
|
|
|
|
|
|
|
if (unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1 < end &&
|
|
|
|
unknown_key[INVALID_TRIGGER_TABLE_LENGTH] == '=' &&
|
|
|
|
!memcmp(unknown_key, STRING_WITH_LEN("trigger_table")))
|
|
|
|
{
|
|
|
|
char *ptr= unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1;
|
|
|
|
|
|
|
|
DBUG_PRINT("info", ("trigger_table affected by BUG#15921 detected"));
|
|
|
|
push_warning_printf(current_thd,
|
|
|
|
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
|
|
|
ER_OLD_FILE_FORMAT,
|
|
|
|
ER(ER_OLD_FILE_FORMAT),
|
|
|
|
(char *)path, "TRIGGER");
|
|
|
|
|
|
|
|
if (!(ptr= parse_escaped_string(ptr, end, mem_root, trigger_table_value)))
|
|
|
|
{
|
|
|
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), "trigger_table",
|
|
|
|
unknown_key);
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set parsing pointer to the last symbol of string (\n). */
|
|
|
|
unknown_key= ptr-1;
|
|
|
|
}
|
|
|
|
DBUG_RETURN(FALSE);
|
|
|
|
}
|
2007-06-14 17:23:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Contruct path to TRN-file.
|
|
|
|
|
2007-08-15 15:43:08 +02:00
|
|
|
@param[in] thd Thread context.
|
|
|
|
@param[in] trg_name Trigger name.
|
|
|
|
@param[out] trn_path Variable to store constructed path
|
2007-06-14 17:23:55 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
2007-08-15 15:43:08 +02:00
|
|
|
@param[in] thd Thread context.
|
|
|
|
@param[in] trg_name Trigger name.
|
|
|
|
@param[in] trn_path Path to the corresponding TRN-file.
|
|
|
|
@param[out] tbl_name Variable to store retrieved table name.
|
2007-06-14 17:23:55 +02:00
|
|
|
|
|
|
|
@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);
|
|
|
|
}
|