Loading include/mysql.h +11 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,17 @@ typedef struct st_mysql_parameters */ int STDCALL mysql_server_init(int argc, char **argv, char **groups); void STDCALL mysql_server_end(void); /* mysql_server_init/end need to be called when using libmysqld or libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so you don't need to call it explicitely; but you need to call mysql_server_end() to free memory). The names are a bit misleading (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general names which suit well whether you're using libmysqld or libmysqlclient. We intend to promote these aliases over the mysql_server* ones. */ #define mysql_library_init mysql_server_init #define mysql_library_end mysql_server_end MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); Loading mysql-test/r/drop_temp_table.result +11 −5 Original line number Diff line number Diff line reset master; create database `drop-temp+table-test`; use `drop-temp+table-test`; create temporary table shortn1 (a int); create temporary table `table:name` (a int); create temporary table shortn2 (a int); select get_lock("a",10); get_lock("a",10) 1 Loading @@ -10,9 +12,13 @@ get_lock("a",10) 1 show binlog events; Log_name Pos Event_type Server_id Orig_log_pos Info master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3 master-bin.000001 79 Query 1 79 create database `drop-temp+table-test` master-bin.000001 168 Query 1 168 use `drop-temp+table-test`; create temporary table `table:name` (a int) master-bin.000001 262 Query 1 262 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name` master-bin.000001 391 Query 1 391 use `drop-temp+table-test`; DO RELEASE_LOCK("a") master-bin.000001 # Start 1 # Server ver: VERSION, Binlog ver: 3 master-bin.000001 # Query 1 # create database `drop-temp+table-test` master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn1` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DO RELEASE_LOCK("a") drop database `drop-temp+table-test`; mysql-test/t/drop_temp_table.test +3 −0 Original line number Diff line number Diff line Loading @@ -4,7 +4,9 @@ connection con1; reset master; create database `drop-temp+table-test`; use `drop-temp+table-test`; create temporary table shortn1 (a int); create temporary table `table:name` (a int); create temporary table shortn2 (a int); select get_lock("a",10); disconnect con1; Loading @@ -15,5 +17,6 @@ connection con2; select get_lock("a",10); let $VERSION=`select version()`; --replace_result $VERSION VERSION --replace_column 2 # 5 # show binlog events; drop database `drop-temp+table-test`; sql/sql_base.cc +31 −35 Original line number Diff line number Diff line Loading @@ -485,55 +485,48 @@ void close_temporary(TABLE *table,bool delete_table) void close_temporary_tables(THD *thd) { TABLE *table,*next; char *query, *end; uint query_buf_size; bool found_user_tables = 0; char *query, *name_in_query, *end; uint greatest_key_length= 0; if (!thd->temporary_tables) return; /* We write a DROP TEMPORARY TABLE for each temp table left, so that our replication slave can clean them up. Not one multi-table DROP TABLE binlog event: this would cause problems if slave uses --replicate-*-table. */ LINT_INIT(end); query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS /* We'll re-use always same buffer so make it big enough for longest name */ for (table=thd->temporary_tables ; table ; table=table->next) /* We are going to add 4 ` around the db/table names, so 1 does not look enough; indeed it is enough, because table->key_length is greater (by 8, because of server_id and thread_id) than db||table. */ query_buf_size+= table->key_length+1; greatest_key_length= max(greatest_key_length, table->key_length); if ((query = alloc_root(thd->mem_root, query_buf_size))) if ((query = alloc_root(thd->mem_root, greatest_key_length+50))) // Better add "if exists", in case a RESET MASTER has been done end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "); name_in_query= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `"); for (table=thd->temporary_tables ; table ; table=next) { if (query) // we might be out of memory, but this is not fatal /* In we are OOM for 'query' this is not fatal. We skip temporary tables not created directly by the user. */ if (query && mysql_bin_log.is_open() && (table->real_name[0] != '#')) { // skip temporary tables not created directly by the user if (table->real_name[0] != '#') found_user_tables = 1; /* Here we assume table_cache_key always starts with \0 terminated db name */ end = strxmov(end,"`",table->table_cache_key,"`.`", table->real_name,"`,", NullS); } next=table->next; close_temporary(table); } if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ thd->clear_error(); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE); end = strxmov(name_in_query, table->table_cache_key, "`.`", table->real_name, "`", NullS); Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE); /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as "killed", because it's not really a statement updating data, and there are 99.99% chances it will succeed on slave. are 99.99% chances it will succeed on slave. And, if thread is killed now, it's not clever either. If a real update (one updating a persistent table) was killed on the master, then this real update will be logged with error_code=killed, rightfully causing the slave to stop. Loading @@ -541,6 +534,9 @@ void close_temporary_tables(THD *thd) qinfo.error_code= 0; mysql_bin_log.write(&qinfo); } next=table->next; close_temporary(table); } thd->temporary_tables=0; } Loading Loading
include/mysql.h +11 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,17 @@ typedef struct st_mysql_parameters */ int STDCALL mysql_server_init(int argc, char **argv, char **groups); void STDCALL mysql_server_end(void); /* mysql_server_init/end need to be called when using libmysqld or libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so you don't need to call it explicitely; but you need to call mysql_server_end() to free memory). The names are a bit misleading (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general names which suit well whether you're using libmysqld or libmysqlclient. We intend to promote these aliases over the mysql_server* ones. */ #define mysql_library_init mysql_server_init #define mysql_library_end mysql_server_end MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void); Loading
mysql-test/r/drop_temp_table.result +11 −5 Original line number Diff line number Diff line reset master; create database `drop-temp+table-test`; use `drop-temp+table-test`; create temporary table shortn1 (a int); create temporary table `table:name` (a int); create temporary table shortn2 (a int); select get_lock("a",10); get_lock("a",10) 1 Loading @@ -10,9 +12,13 @@ get_lock("a",10) 1 show binlog events; Log_name Pos Event_type Server_id Orig_log_pos Info master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3 master-bin.000001 79 Query 1 79 create database `drop-temp+table-test` master-bin.000001 168 Query 1 168 use `drop-temp+table-test`; create temporary table `table:name` (a int) master-bin.000001 262 Query 1 262 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name` master-bin.000001 391 Query 1 391 use `drop-temp+table-test`; DO RELEASE_LOCK("a") master-bin.000001 # Start 1 # Server ver: VERSION, Binlog ver: 3 master-bin.000001 # Query 1 # create database `drop-temp+table-test` master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn1` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DO RELEASE_LOCK("a") drop database `drop-temp+table-test`;
mysql-test/t/drop_temp_table.test +3 −0 Original line number Diff line number Diff line Loading @@ -4,7 +4,9 @@ connection con1; reset master; create database `drop-temp+table-test`; use `drop-temp+table-test`; create temporary table shortn1 (a int); create temporary table `table:name` (a int); create temporary table shortn2 (a int); select get_lock("a",10); disconnect con1; Loading @@ -15,5 +17,6 @@ connection con2; select get_lock("a",10); let $VERSION=`select version()`; --replace_result $VERSION VERSION --replace_column 2 # 5 # show binlog events; drop database `drop-temp+table-test`;
sql/sql_base.cc +31 −35 Original line number Diff line number Diff line Loading @@ -485,55 +485,48 @@ void close_temporary(TABLE *table,bool delete_table) void close_temporary_tables(THD *thd) { TABLE *table,*next; char *query, *end; uint query_buf_size; bool found_user_tables = 0; char *query, *name_in_query, *end; uint greatest_key_length= 0; if (!thd->temporary_tables) return; /* We write a DROP TEMPORARY TABLE for each temp table left, so that our replication slave can clean them up. Not one multi-table DROP TABLE binlog event: this would cause problems if slave uses --replicate-*-table. */ LINT_INIT(end); query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS /* We'll re-use always same buffer so make it big enough for longest name */ for (table=thd->temporary_tables ; table ; table=table->next) /* We are going to add 4 ` around the db/table names, so 1 does not look enough; indeed it is enough, because table->key_length is greater (by 8, because of server_id and thread_id) than db||table. */ query_buf_size+= table->key_length+1; greatest_key_length= max(greatest_key_length, table->key_length); if ((query = alloc_root(thd->mem_root, query_buf_size))) if ((query = alloc_root(thd->mem_root, greatest_key_length+50))) // Better add "if exists", in case a RESET MASTER has been done end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "); name_in_query= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `"); for (table=thd->temporary_tables ; table ; table=next) { if (query) // we might be out of memory, but this is not fatal /* In we are OOM for 'query' this is not fatal. We skip temporary tables not created directly by the user. */ if (query && mysql_bin_log.is_open() && (table->real_name[0] != '#')) { // skip temporary tables not created directly by the user if (table->real_name[0] != '#') found_user_tables = 1; /* Here we assume table_cache_key always starts with \0 terminated db name */ end = strxmov(end,"`",table->table_cache_key,"`.`", table->real_name,"`,", NullS); } next=table->next; close_temporary(table); } if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ thd->clear_error(); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE); end = strxmov(name_in_query, table->table_cache_key, "`.`", table->real_name, "`", NullS); Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE); /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as "killed", because it's not really a statement updating data, and there are 99.99% chances it will succeed on slave. are 99.99% chances it will succeed on slave. And, if thread is killed now, it's not clever either. If a real update (one updating a persistent table) was killed on the master, then this real update will be logged with error_code=killed, rightfully causing the slave to stop. Loading @@ -541,6 +534,9 @@ void close_temporary_tables(THD *thd) qinfo.error_code= 0; mysql_bin_log.write(&qinfo); } next=table->next; close_temporary(table); } thd->temporary_tables=0; } Loading