Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into bodhi.(none):/opt/local/work/mysql-5.1-runtime client/mysqldump.c: Auto merged mysql-test/r/show_check.result: Auto merged mysql-test/t/show_check.test: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.h: Auto merged sql/share/errmsg.txt: Auto merged sql/sql_parse.cc: Auto merged sql/sql_show.cc: Auto merged mysql-test/r/events_bugs.result: Manual merge.
This commit is contained in:
commit
146b0e1475
@ -1213,6 +1213,20 @@ static void restore_time_zone(FILE *sql_file,
|
||||
(const char *) delimiter);
|
||||
}
|
||||
|
||||
|
||||
static int switch_character_set_results(MYSQL *mysql, const char *cs_name)
|
||||
{
|
||||
char query_buffer[QUERY_LENGTH];
|
||||
size_t query_length;
|
||||
|
||||
query_length= my_snprintf(query_buffer,
|
||||
sizeof (query_buffer),
|
||||
"SET SESSION character_set_results = '%s'",
|
||||
(const char *) cs_name);
|
||||
|
||||
return mysql_real_query(mysql, query_buffer, query_length);
|
||||
}
|
||||
|
||||
/*
|
||||
Open a new .sql file to dump the table or view into
|
||||
|
||||
@ -1718,6 +1732,9 @@ static uint dump_events_for_db(char *db)
|
||||
if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (switch_character_set_results(mysql, "binary"))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
while ((event_list_row= mysql_fetch_row(event_list_res)) != NULL)
|
||||
{
|
||||
event_name= quote_name(event_list_row[1], name_buff, 0);
|
||||
@ -1786,6 +1803,9 @@ static uint dump_events_for_db(char *db)
|
||||
} /* end of list of events */
|
||||
fprintf(sql_file, "DELIMITER ;\n");
|
||||
fprintf(sql_file, "/*!50106 SET TIME_ZONE= @save_time_zone */ ;\n");
|
||||
|
||||
if (switch_character_set_results(mysql, default_charset))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
mysql_free_result(event_list_res);
|
||||
|
||||
@ -1865,6 +1885,9 @@ static uint dump_routines_for_db(char *db)
|
||||
if (fetch_db_collation(db_name_buff, db_cl_name, sizeof (db_cl_name)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (switch_character_set_results(mysql, "binary"))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/* 0, retrieve and dump functions, 1, procedures */
|
||||
for (i= 0; i <= 1; i++)
|
||||
{
|
||||
@ -2002,6 +2025,9 @@ static uint dump_routines_for_db(char *db)
|
||||
mysql_free_result(routine_list_res);
|
||||
} /* end of for i (0 .. 1) */
|
||||
|
||||
if (switch_character_set_results(mysql, default_charset))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (lock_tables)
|
||||
VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
|
||||
DBUG_RETURN(0);
|
||||
@ -2554,6 +2580,9 @@ static void dump_triggers_for_table(char *table, char *db_name)
|
||||
if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name)))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
if (switch_character_set_results(mysql, "binary"))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
/* Dump triggers. */
|
||||
|
||||
while ((row= mysql_fetch_row(result)))
|
||||
@ -2649,6 +2678,9 @@ static void dump_triggers_for_table(char *table, char *db_name)
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
if (switch_character_set_results(mysql, default_charset))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
/*
|
||||
make sure to set back opt_compatible mode to
|
||||
original value
|
||||
@ -4391,14 +4423,22 @@ static my_bool get_view_structure(char *table, char* db)
|
||||
result_table= quote_name(table, table_buff, 1);
|
||||
opt_quoted_table= quote_name(table, table_buff2, 0);
|
||||
|
||||
if (switch_character_set_results(mysql, "binary"))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
|
||||
|
||||
if (mysql_query_with_error_report(mysql, &table_res, query))
|
||||
{
|
||||
switch_character_set_results(mysql, default_charset);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/* Check if this is a view */
|
||||
field= mysql_fetch_field_direct(table_res, 0);
|
||||
if (strcmp(field->name, "View") != 0)
|
||||
{
|
||||
switch_character_set_results(mysql, default_charset);
|
||||
verbose_msg("-- It's base table, skipped\n");
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -4541,6 +4581,9 @@ static my_bool get_view_structure(char *table, char* db)
|
||||
dynstr_free(&ds_view);
|
||||
}
|
||||
|
||||
if (switch_character_set_results(mysql, default_charset))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/* If a separate .sql file was opened, close it now */
|
||||
if (sql_file != md_result_file)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ create event e_55 on schedule at 10000101000000 do drop table t;
|
||||
ERROR HY000: Incorrect AT value: '10000101000000'
|
||||
create event e_55 on schedule at 20000101000000 do drop table t;
|
||||
Warnings:
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
show events;
|
||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
|
||||
create event e_55 on schedule at 20200101000000 starts 10000101000000 do drop table t;
|
||||
@ -447,32 +447,32 @@ e3 +00:00 CREATE EVENT `e3` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00
|
||||
The following should fail, and nothing should be altered.
|
||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||
ENDS '1999-01-02 00:00:00';
|
||||
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
|
||||
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||
ENDS '1999-01-02 00:00:00' DISABLE;
|
||||
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
|
||||
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
The following should give warnings, and nothing should be created.
|
||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||
ENDS '1999-01-02 00:00:00'
|
||||
DO
|
||||
SELECT 1;
|
||||
Warnings:
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||
ENDS '1999-01-02 00:00:00' DISABLE
|
||||
DO
|
||||
SELECT 1;
|
||||
Warnings:
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
|
||||
SELECT 1;
|
||||
Warnings:
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
|
||||
DO
|
||||
SELECT 1;
|
||||
Warnings:
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||
Note 1585 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
|
||||
SHOW EVENTS;
|
||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
|
||||
events_test e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
|
@ -1312,4 +1312,43 @@ t1_bi CREATE DEFINER=`root`@`localhost` TRIGGER t1_bi BEFORE INSERT ON t1 FOR E
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
DEALLOCATE PREPARE stmt1;
|
||||
set names koi8r;
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP EVENT IF EXISTS ev1;
|
||||
CREATE VIEW v1 AS SELECT 'ÔÅÓÔ' AS test;
|
||||
CREATE PROCEDURE p1() SELECT 'ÔÅÓÔ' AS test;
|
||||
CREATE FUNCTION f1() RETURNS CHAR(10) RETURN 'ÔÅÓÔ';
|
||||
CREATE TABLE t1(c1 CHAR(10));
|
||||
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET NEW.c1 = 'ÔÅÓÔ';
|
||||
CREATE EVENT ev1 ON SCHEDULE AT '2030-01-01 00:00:00' DO SELECT 'ÔÅÓÔ' AS test;
|
||||
set names utf8;
|
||||
SHOW CREATE VIEW v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _koi8r'теÑ<C2B5>Ñ‚' AS `test` koi8r koi8r_general_ci
|
||||
SHOW CREATE PROCEDURE p1;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
|
||||
SELECT 'теÑ<C2B5>Ñ‚' AS test koi8r koi8r_general_ci latin1_swedish_ci
|
||||
SHOW CREATE FUNCTION f1;
|
||||
Function sql_mode Create Function character_set_client collation_connection Database Collation
|
||||
f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS char(10) CHARSET latin1
|
||||
RETURN 'теÑ<C2B5>Ñ‚' koi8r koi8r_general_ci latin1_swedish_ci
|
||||
SHOW CREATE TRIGGER t1_bi;
|
||||
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
|
||||
t1_bi CREATE DEFINER=`root`@`localhost` TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET NEW.c1 = 'теÑ<C2B5>Ñ‚' koi8r koi8r_general_ci latin1_swedish_ci
|
||||
SHOW CREATE EVENT ev1;
|
||||
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation
|
||||
ev1 SYSTEM CREATE EVENT `ev1` ON SCHEDULE AT '2030-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 'теÑ<C2B5>Ñ‚' AS test koi8r koi8r_general_ci latin1_swedish_ci
|
||||
DROP VIEW v1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE t1;
|
||||
DROP EVENT ev1;
|
||||
End of 5.1 tests
|
||||
|
@ -913,4 +913,68 @@ DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
DEALLOCATE PREPARE stmt1;
|
||||
|
||||
#
|
||||
# BUG#10491: Server returns data as charset binary SHOW CREATE TABLE or SELECT
|
||||
# FROM INFORMATION_SCHEMA.
|
||||
#
|
||||
# Before the change performed to fix the bug, the metadata of the output of
|
||||
# SHOW CREATE statements would always describe the result as 'binary'. That
|
||||
# would ensure that the result is never converted to character_set_client
|
||||
# (which was essential to mysqldump). Now we return to the client the actual
|
||||
# character set of the object -- which is character_set_client of the
|
||||
# connection that issues the CREATE statement, and this triggers an automatic
|
||||
# conversion to character_set_results of the connection that issues SHOW CREATE
|
||||
# statement.
|
||||
#
|
||||
# This test demonstrates that this conversion indeed is taking place.
|
||||
#
|
||||
|
||||
# Prepare: create objects in a one character set.
|
||||
|
||||
set names koi8r;
|
||||
|
||||
--disable_warnings
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP EVENT IF EXISTS ev1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE VIEW v1 AS SELECT 'ÔÅÓÔ' AS test;
|
||||
|
||||
CREATE PROCEDURE p1() SELECT 'ÔÅÓÔ' AS test;
|
||||
|
||||
CREATE FUNCTION f1() RETURNS CHAR(10) RETURN 'ÔÅÓÔ';
|
||||
|
||||
CREATE TABLE t1(c1 CHAR(10));
|
||||
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET NEW.c1 = 'ÔÅÓÔ';
|
||||
|
||||
CREATE EVENT ev1 ON SCHEDULE AT '2030-01-01 00:00:00' DO SELECT 'ÔÅÓÔ' AS test;
|
||||
|
||||
# Test: switch the character set and show that SHOW CREATE output is
|
||||
# automatically converted to the new character_set_client.
|
||||
|
||||
set names utf8;
|
||||
|
||||
SHOW CREATE VIEW v1;
|
||||
|
||||
SHOW CREATE PROCEDURE p1;
|
||||
|
||||
SHOW CREATE FUNCTION f1;
|
||||
|
||||
SHOW CREATE TRIGGER t1_bi;
|
||||
|
||||
SHOW CREATE EVENT ev1;
|
||||
|
||||
# Cleanup.
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE t1;
|
||||
DROP EVENT ev1;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
@ -717,7 +717,8 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
|
||||
protocol->store(et->name.str, et->name.length, system_charset_info);
|
||||
protocol->store(sql_mode.str, sql_mode.length, system_charset_info);
|
||||
protocol->store(tz_name->ptr(), tz_name->length(), system_charset_info);
|
||||
protocol->store(show_str.c_ptr(), show_str.length(), &my_charset_bin);
|
||||
protocol->store(show_str.c_ptr(), show_str.length(),
|
||||
et->creation_ctx->get_client_cs());
|
||||
protocol->store(et->creation_ctx->get_client_cs()->csname,
|
||||
strlen(et->creation_ctx->get_client_cs()->csname),
|
||||
system_charset_info);
|
||||
|
@ -7033,9 +7033,6 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
}
|
||||
}
|
||||
|
||||
// Lock mutex before deleting and creating frm files
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
|
||||
if (!global_read_lock)
|
||||
{
|
||||
// Delete old files
|
||||
@ -7049,15 +7046,17 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
table_list.db= (char*) db;
|
||||
table_list.alias= table_list.table_name= (char*)file_name;
|
||||
(void)mysql_rm_table_part2(thd, &table_list,
|
||||
/* if_exists */ FALSE,
|
||||
/* drop_temporary */ FALSE,
|
||||
/* drop_view */ FALSE,
|
||||
/* dont_log_query*/ TRUE);
|
||||
FALSE, /* if_exists */
|
||||
FALSE, /* drop_temporary */
|
||||
FALSE, /* drop_view */
|
||||
TRUE /* dont_log_query*/);
|
||||
|
||||
/* Clear error message that is returned when table is deleted */
|
||||
thd->clear_error();
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
// Create new files
|
||||
List_iterator_fast<char> it2(create_list);
|
||||
while ((file_name=it2++))
|
||||
@ -7068,7 +7067,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
|
||||
hash_free(&ok_tables);
|
||||
hash_free(&ndb_tables);
|
||||
|
||||
|
96
sql/lock.cc
96
sql/lock.cc
@ -1033,6 +1033,102 @@ end:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Lock all tables in list with an exclusive table name lock.
|
||||
|
||||
@param thd Thread handle.
|
||||
@param table_list Names of tables to lock.
|
||||
|
||||
@note This function needs to be protected by LOCK_open. If we're
|
||||
under LOCK TABLES, this function does not work as advertised. Namely,
|
||||
it does not exclude other threads from using this table and does not
|
||||
put an exclusive name lock on this table into the table cache.
|
||||
|
||||
@see lock_table_names
|
||||
@see unlock_table_names
|
||||
|
||||
@retval TRUE An error occured.
|
||||
@retval FALSE Name lock successfully acquired.
|
||||
*/
|
||||
|
||||
bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list)
|
||||
{
|
||||
if (lock_table_names(thd, table_list))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
Upgrade the table name locks from semi-exclusive to exclusive locks.
|
||||
*/
|
||||
for (TABLE_LIST *table= table_list; table; table= table->next_global)
|
||||
{
|
||||
if (table->table)
|
||||
table->table->open_placeholder= 1;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Test is 'table' is protected by an exclusive name lock.
|
||||
|
||||
@param[in] thd The current thread handler
|
||||
@param[in] table Table container containing the single table to be tested
|
||||
|
||||
@note Needs to be protected by LOCK_open mutex.
|
||||
|
||||
@return Error status code
|
||||
@retval TRUE Table is protected
|
||||
@retval FALSE Table is not protected
|
||||
*/
|
||||
|
||||
bool
|
||||
is_table_name_exclusively_locked_by_this_thread(THD *thd,
|
||||
TABLE_LIST *table_list)
|
||||
{
|
||||
char key[MAX_DBKEY_LENGTH];
|
||||
uint key_length;
|
||||
|
||||
key_length= create_table_def_key(thd, key, table_list, 0);
|
||||
|
||||
return is_table_name_exclusively_locked_by_this_thread(thd, (uchar *)key,
|
||||
key_length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Test is 'table key' is protected by an exclusive name lock.
|
||||
|
||||
@param[in] thd The current thread handler.
|
||||
@param[in] table Table container containing the single table to be tested.
|
||||
|
||||
@note Needs to be protected by LOCK_open mutex
|
||||
|
||||
@retval TRUE Table is protected
|
||||
@retval FALSE Table is not protected
|
||||
*/
|
||||
|
||||
bool
|
||||
is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
|
||||
int key_length)
|
||||
{
|
||||
HASH_SEARCH_STATE state;
|
||||
TABLE *table;
|
||||
|
||||
for (table= (TABLE*) hash_first(&open_cache, key,
|
||||
key_length, &state);
|
||||
table ;
|
||||
table= (TABLE*) hash_next(&open_cache, key,
|
||||
key_length, &state))
|
||||
{
|
||||
if (table->in_use == thd &&
|
||||
table->open_placeholder == 1 &&
|
||||
table->s->version == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
Unlock all tables in list with a name lock
|
||||
|
||||
|
@ -908,10 +908,7 @@ void mysql_client_binlog_statement(THD *thd);
|
||||
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
|
||||
my_bool drop_temporary);
|
||||
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
bool drop_temporary, bool drop_view, bool log_query);
|
||||
int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
|
||||
bool if_exists, bool drop_temporary,
|
||||
bool log_query);
|
||||
bool drop_temporary, bool drop_view, bool log_query);
|
||||
bool quick_rm_table(handlerton *base,const char *db,
|
||||
const char *table_name, uint flags);
|
||||
void close_cached_table(THD *thd, TABLE *table);
|
||||
@ -1923,6 +1920,11 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
|
||||
bool lock_table_names(THD *thd, TABLE_LIST *table_list);
|
||||
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
|
||||
TABLE_LIST *last_table);
|
||||
bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list);
|
||||
bool is_table_name_exclusively_locked_by_this_thread(THD *thd,
|
||||
TABLE_LIST *table_list);
|
||||
bool is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
|
||||
int key_length);
|
||||
|
||||
|
||||
/* old unireg functions */
|
||||
|
@ -6062,9 +6062,9 @@ ER_BINLOG_PURGE_EMFILE
|
||||
eng "Too many files opened, please execute the command again"
|
||||
ger "Zu viele offene Dateien, bitte führen Sie den Befehl noch einmal aus"
|
||||
ER_EVENT_CANNOT_CREATE_IN_THE_PAST
|
||||
eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created"
|
||||
eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation."
|
||||
ER_EVENT_CANNOT_ALTER_IN_THE_PAST
|
||||
eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered"
|
||||
eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation."
|
||||
ER_SLAVE_INCIDENT
|
||||
eng "The incident %s occured on the master. Message: %-.64s"
|
||||
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
|
||||
|
@ -2260,7 +2260,8 @@ sp_head::show_create_routine(THD *thd, int type)
|
||||
protocol->store(sql_mode.str, sql_mode.length, system_charset_info);
|
||||
|
||||
if (full_access)
|
||||
protocol->store(m_defstr.str, m_defstr.length, &my_charset_bin);
|
||||
protocol->store(m_defstr.str, m_defstr.length,
|
||||
m_creation_ctx->get_client_cs());
|
||||
else
|
||||
protocol->store_null();
|
||||
|
||||
|
714
sql/sql_cache.cc
714
sql/sql_cache.cc
File diff suppressed because it is too large
Load Diff
@ -65,17 +65,44 @@ struct Query_cache_query;
|
||||
struct Query_cache_result;
|
||||
class Query_cache;
|
||||
|
||||
/**
|
||||
@brief This class represents a node in the linked chain of queries
|
||||
belonging to one table.
|
||||
|
||||
@note The root of this linked list is not a query-type block, but the table-
|
||||
type block which all queries has in common.
|
||||
*/
|
||||
struct Query_cache_block_table
|
||||
{
|
||||
Query_cache_block_table() {} /* Remove gcc warning */
|
||||
TABLE_COUNTER_TYPE n; // numbr in table (from 0)
|
||||
|
||||
/**
|
||||
This node holds a position in a static table list belonging
|
||||
to the associated query (base 0).
|
||||
*/
|
||||
TABLE_COUNTER_TYPE n;
|
||||
|
||||
/**
|
||||
Pointers to the next and previous node, linking all queries with
|
||||
a common table.
|
||||
*/
|
||||
Query_cache_block_table *next, *prev;
|
||||
|
||||
/**
|
||||
A pointer to the table-type block which all
|
||||
linked queries has in common.
|
||||
*/
|
||||
Query_cache_table *parent;
|
||||
|
||||
/**
|
||||
A method to calculate the address of the query cache block
|
||||
owning this node. The purpose of this calculation is to
|
||||
make it easier to move the query cache block without having
|
||||
to modify all the pointer addresses.
|
||||
*/
|
||||
inline Query_cache_block *block();
|
||||
};
|
||||
|
||||
|
||||
struct Query_cache_block
|
||||
{
|
||||
Query_cache_block() {} /* Remove gcc warning */
|
||||
@ -151,6 +178,11 @@ struct Query_cache_table
|
||||
/* data need by some engines */
|
||||
ulonglong engine_data_buff;
|
||||
|
||||
/**
|
||||
The number of queries depending of this table.
|
||||
*/
|
||||
int32 m_cached_query_count;
|
||||
|
||||
inline char *db() { return (char *) data(); }
|
||||
inline char *table() { return tbl; }
|
||||
inline void table(char *table_arg) { tbl= table_arg; }
|
||||
@ -237,9 +269,14 @@ public:
|
||||
ulong free_memory, queries_in_cache, hits, inserts, refused,
|
||||
free_memory_blocks, total_blocks, lowmem_prunes;
|
||||
|
||||
|
||||
private:
|
||||
pthread_cond_t COND_flush_finished;
|
||||
bool flush_in_progress;
|
||||
pthread_cond_t COND_cache_status_changed;
|
||||
|
||||
enum Cache_status { NO_FLUSH_IN_PROGRESS, FLUSH_IN_PROGRESS,
|
||||
TABLE_FLUSH_IN_PROGRESS };
|
||||
|
||||
Cache_status m_cache_status;
|
||||
|
||||
void free_query_internal(Query_cache_block *point);
|
||||
|
||||
@ -253,7 +290,7 @@ protected:
|
||||
2. query block (for operation inside query (query block/results))
|
||||
|
||||
Thread doing cache flush releases the mutex once it sets
|
||||
flush_in_progress flag, so other threads may bypass the cache as
|
||||
m_cache_status flag, so other threads may bypass the cache as
|
||||
if it is disabled, not waiting for reset to finish. The exception
|
||||
is other threads that were going to do cache flush---they'll wait
|
||||
till the end of a flush operation.
|
||||
@ -270,6 +307,7 @@ protected:
|
||||
/* options */
|
||||
ulong min_allocation_unit, min_result_data_size;
|
||||
uint def_query_hash_size, def_table_hash_size;
|
||||
|
||||
uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
|
||||
|
||||
my_bool initialized;
|
||||
@ -295,10 +333,13 @@ protected:
|
||||
ulong data_len,
|
||||
Query_cache_block *query_block,
|
||||
my_bool first_block);
|
||||
void invalidate_table(TABLE_LIST *table);
|
||||
void invalidate_table(TABLE *table);
|
||||
void invalidate_table(uchar *key, uint32 key_length);
|
||||
void invalidate_table(Query_cache_block *table_block);
|
||||
void invalidate_table(THD *thd, TABLE_LIST *table);
|
||||
void invalidate_table(THD *thd, TABLE *table);
|
||||
void invalidate_table(THD *thd, uchar *key, uint32 key_length);
|
||||
void invalidate_table(THD *thd, Query_cache_block *table_block);
|
||||
void invalidate_query_block_list(THD *thd,
|
||||
Query_cache_block_table *list_root);
|
||||
|
||||
TABLE_COUNTER_TYPE
|
||||
register_tables_from_list(TABLE_LIST *tables_used,
|
||||
TABLE_COUNTER_TYPE counter,
|
||||
@ -337,6 +378,8 @@ protected:
|
||||
Query_cache_block *pprev);
|
||||
my_bool join_results(ulong join_limit);
|
||||
|
||||
void wait_while_table_flush_is_in_progress(bool *interrupt);
|
||||
|
||||
/*
|
||||
Following function control structure_guard_mutex
|
||||
by themself or don't need structure_guard_mutex
|
||||
@ -347,8 +390,7 @@ protected:
|
||||
Query_cache_block *write_block_data(ulong data_len, uchar* data,
|
||||
ulong header_len,
|
||||
Query_cache_block::block_type type,
|
||||
TABLE_COUNTER_TYPE ntab = 0,
|
||||
my_bool under_guard=0);
|
||||
TABLE_COUNTER_TYPE ntab = 0);
|
||||
my_bool append_result_data(Query_cache_block **result,
|
||||
ulong data_len, uchar* data,
|
||||
Query_cache_block *parent);
|
||||
@ -360,8 +402,7 @@ protected:
|
||||
inline ulong get_min_first_result_data_size();
|
||||
inline ulong get_min_append_result_data_size();
|
||||
Query_cache_block *allocate_block(ulong len, my_bool not_less,
|
||||
ulong min,
|
||||
my_bool under_guard=0);
|
||||
ulong min);
|
||||
/*
|
||||
If query is cacheable return number tables in query
|
||||
(query without tables not cached)
|
||||
@ -424,6 +465,11 @@ protected:
|
||||
friend void query_cache_end_of_result(THD *thd);
|
||||
friend void query_cache_abort(NET *net);
|
||||
|
||||
bool is_flushing(void)
|
||||
{
|
||||
return (m_cache_status != Query_cache::NO_FLUSH_IN_PROGRESS);
|
||||
}
|
||||
|
||||
/*
|
||||
The following functions are only used when debugging
|
||||
We don't protect these with ifndef DBUG_OFF to not have to recompile
|
||||
|
@ -2015,8 +2015,8 @@ class select_insert :public select_result_interceptor {
|
||||
class select_create: public select_insert {
|
||||
ORDER *group;
|
||||
TABLE_LIST *create_table;
|
||||
TABLE_LIST *select_tables;
|
||||
HA_CREATE_INFO *create_info;
|
||||
TABLE_LIST *select_tables;
|
||||
Alter_info *alter_info;
|
||||
Field **field;
|
||||
public:
|
||||
|
@ -1113,7 +1113,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
|
||||
}
|
||||
}
|
||||
if (thd->killed ||
|
||||
(tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
|
||||
(tot_list && mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1)))
|
||||
goto err;
|
||||
|
||||
/* Remove RAID directories */
|
||||
|
@ -2449,7 +2449,7 @@ end_with_restore_list:
|
||||
check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
|
||||
goto error;
|
||||
}
|
||||
query_cache_invalidate3(thd, first_table, 0);
|
||||
|
||||
if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0))
|
||||
goto error;
|
||||
break;
|
||||
|
@ -144,10 +144,13 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
}
|
||||
}
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
if (lock_table_names(thd, table_list))
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
if (lock_table_names_exclusively(thd, table_list))
|
||||
{
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
goto err;
|
||||
|
||||
}
|
||||
|
||||
error=0;
|
||||
if ((ren_table=rename_tables(thd,table_list,0)))
|
||||
{
|
||||
@ -170,6 +173,17 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
|
||||
error= 1;
|
||||
}
|
||||
/*
|
||||
An exclusive lock on table names is satisfactory to ensure
|
||||
no other thread accesses this table.
|
||||
However, NDB assumes that handler::rename_tables is called under
|
||||
LOCK_open. And it indeed is, from ALTER TABLE.
|
||||
TODO: remove this limitation.
|
||||
We still should unlock LOCK_open as early as possible, to provide
|
||||
higher concurrency - query_cache_invalidate can take minutes to
|
||||
complete.
|
||||
*/
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
/* Lets hope this doesn't fail as the result will be messy */
|
||||
if (!silent && !error)
|
||||
@ -178,10 +192,14 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
|
||||
send_ok(thd);
|
||||
}
|
||||
|
||||
if (!error)
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
/* enable logging back if needed */
|
||||
if (disable_logs)
|
||||
{
|
||||
|
@ -639,7 +639,8 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
||||
|
||||
if (table_list->view)
|
||||
{
|
||||
protocol->store(buffer.ptr(), buffer.length(), &my_charset_bin);
|
||||
protocol->store(buffer.ptr(), buffer.length(),
|
||||
table_list->view_creation_ctx->get_client_cs());
|
||||
|
||||
protocol->store(table_list->view_creation_ctx->get_client_cs()->csname,
|
||||
system_charset_info);
|
||||
@ -5967,6 +5968,8 @@ static bool show_create_trigger_impl(THD *thd,
|
||||
LEX_STRING trg_connection_cl_name;
|
||||
LEX_STRING trg_db_cl_name;
|
||||
|
||||
CHARSET_INFO *trg_client_cs;
|
||||
|
||||
/*
|
||||
TODO: Check privileges here. This functionality will be added by
|
||||
implementation of the following WL items:
|
||||
@ -5992,6 +5995,11 @@ static bool show_create_trigger_impl(THD *thd,
|
||||
trg_sql_mode,
|
||||
&trg_sql_mode_str);
|
||||
|
||||
/* Resolve trigger client character set. */
|
||||
|
||||
if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs))
|
||||
return TRUE;
|
||||
|
||||
/* Send header. */
|
||||
|
||||
fields.push_back(new Item_empty_string("Trigger", NAME_LEN));
|
||||
@ -6038,7 +6046,7 @@ static bool show_create_trigger_impl(THD *thd,
|
||||
|
||||
p->store(trg_sql_original_stmt.str,
|
||||
trg_sql_original_stmt.length,
|
||||
&my_charset_bin);
|
||||
trg_client_cs);
|
||||
|
||||
p->store(trg_client_cs_name.str,
|
||||
trg_client_cs_name.length,
|
||||
|
@ -1430,19 +1430,8 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
|
||||
LOCK_open during wait_if_global_read_lock(), other threads could not
|
||||
close their tables. This would make a pretty deadlock.
|
||||
*/
|
||||
thd->mysys_var->current_mutex= &LOCK_open;
|
||||
thd->mysys_var->current_cond= &COND_refresh;
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
|
||||
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
|
||||
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||
thd->mysys_var->current_mutex= 0;
|
||||
thd->mysys_var->current_cond= 0;
|
||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
||||
|
||||
if (need_start_waiters)
|
||||
start_waiting_global_read_lock(thd);
|
||||
|
||||
@ -1452,49 +1441,6 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
delete (drop) tables.
|
||||
|
||||
SYNOPSIS
|
||||
mysql_rm_table_part2_with_lock()
|
||||
thd Thread handle
|
||||
tables List of tables to delete
|
||||
if_exists If 1, don't give error if one table doesn't exists
|
||||
dont_log_query Don't write query to log files. This will also not
|
||||
generate warnings if the handler files doesn't exists
|
||||
|
||||
NOTES
|
||||
Works like documented in mysql_rm_table(), but don't check
|
||||
global_read_lock and don't send_ok packet to server.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
int mysql_rm_table_part2_with_lock(THD *thd,
|
||||
TABLE_LIST *tables, bool if_exists,
|
||||
bool drop_temporary, bool dont_log_query)
|
||||
{
|
||||
int error;
|
||||
thd->mysys_var->current_mutex= &LOCK_open;
|
||||
thd->mysys_var->current_cond= &COND_refresh;
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
|
||||
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 1,
|
||||
dont_log_query);
|
||||
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||
thd->mysys_var->current_mutex= 0;
|
||||
thd->mysys_var->current_cond= 0;
|
||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Execute the drop of a normal or temporary table
|
||||
|
||||
@ -1541,7 +1487,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
|
||||
LINT_INIT(alias);
|
||||
LINT_INIT(path_length);
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
|
||||
if (thd->current_stmt_binlog_row_based && !dont_log_query)
|
||||
{
|
||||
@ -1551,6 +1496,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
else
|
||||
built_query.append("DROP TABLE ");
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
|
||||
/*
|
||||
If we have the table in the definition cache, we don't have to check the
|
||||
.frm file to find if the table is a normal table (not view) and what
|
||||
@ -1570,12 +1518,16 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
table->table_name_length, table->table_name, 1))
|
||||
{
|
||||
my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!drop_temporary && lock_table_names(thd, tables))
|
||||
if (!drop_temporary && lock_table_names_exclusively(thd, tables))
|
||||
{
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* Don't give warnings for not found errors, as we already generate notes */
|
||||
thd->no_warnings_for_error= 1;
|
||||
@ -1586,7 +1538,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
handlerton *table_type;
|
||||
enum legacy_db_type frm_db_type;
|
||||
|
||||
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
|
||||
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, 1);
|
||||
if (!close_temporary_table(thd, table))
|
||||
{
|
||||
tmp_table_deleted=1;
|
||||
@ -1635,8 +1587,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
|
||||
if (thd->killed)
|
||||
{
|
||||
thd->no_warnings_for_error= 0;
|
||||
DBUG_RETURN(-1);
|
||||
error= -1;
|
||||
goto err_with_placeholders;
|
||||
}
|
||||
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
|
||||
/* remove .frm file and engine files */
|
||||
@ -1699,6 +1651,11 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
wrong_tables.append(String(table->table_name,system_charset_info));
|
||||
}
|
||||
}
|
||||
/*
|
||||
It's safe to unlock LOCK_open: we have an exclusive lock
|
||||
on the table name.
|
||||
*/
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
thd->tmp_table_used= tmp_table_deleted;
|
||||
error= 0;
|
||||
if (wrong_tables.length())
|
||||
@ -1758,9 +1715,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (!drop_temporary)
|
||||
unlock_table_names(thd, tables, (TABLE_LIST*) 0);
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
err_with_placeholders:
|
||||
unlock_table_names(thd, tables, (TABLE_LIST*) 0);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
thd->no_warnings_for_error= 0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
@ -1606,8 +1606,6 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name)
|
||||
bzero(&table, sizeof(table));
|
||||
init_alloc_root(&table.mem_root, 8192, 0);
|
||||
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
|
||||
if (Table_triggers_list::check_n_load(thd, db, name, &table, 1))
|
||||
{
|
||||
result= 1;
|
||||
@ -1774,26 +1772,24 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Update .TRG and .TRN files after renaming triggers' subject table.
|
||||
/**
|
||||
@brief Update .TRG and .TRN files after renaming triggers' subject table.
|
||||
|
||||
SYNOPSIS
|
||||
change_table_name()
|
||||
thd Thread context
|
||||
db Old database of subject table
|
||||
old_table Old name of subject table
|
||||
new_db New database for subject table
|
||||
new_table New name of subject table
|
||||
@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
|
||||
|
||||
NOTE
|
||||
@note
|
||||
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.
|
||||
Also this method assumes that subject table is not renamed to itself.
|
||||
This method needs to be called under an exclusive table name lock.
|
||||
|
||||
RETURN VALUE
|
||||
FALSE Success
|
||||
TRUE Error
|
||||
@retval FALSE Success
|
||||
@retval TRUE Error
|
||||
*/
|
||||
|
||||
bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
||||
@ -1809,7 +1805,19 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
|
||||
bzero(&table, sizeof(table));
|
||||
init_alloc_root(&table.mem_root, 8192, 0);
|
||||
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
/*
|
||||
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
|
||||
uchar key[MAX_DBKEY_LENGTH];
|
||||
uint key_length= (uint) (strmov(strmov((char*)&key[0], db)+1,
|
||||
old_table)-(char*)&key[0])+1;
|
||||
|
||||
if (!is_table_name_exclusively_locked_by_this_thread(thd, key, key_length))
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
#endif
|
||||
|
||||
DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
|
||||
my_strcasecmp(table_alias_charset, old_table, new_table));
|
||||
|
Loading…
x
Reference in New Issue
Block a user