diff --git a/client/mysqldump.c b/client/mysqldump.c index 0f30ebddacc..cfdde285040 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2116,7 +2116,10 @@ static uint get_table_structure(char *table, char *db, char *table_type, MYSQL_FIELD *field; my_snprintf(buff, sizeof(buff), "show create table %s", result_table); - if (mysql_query_with_error_report(mysql, 0, buff)) + + if (switch_character_set_results(mysql, "binary") || + mysql_query_with_error_report(mysql, &result, buff) || + switch_character_set_results(mysql, default_charset)) DBUG_RETURN(0); if (path) @@ -2147,7 +2150,6 @@ static uint get_table_structure(char *table, char *db, char *table_type, check_io(sql_file); } - result= mysql_store_result(mysql); field= mysql_fetch_field_direct(result, 0); if (strcmp(field->name, "View") == 0) { @@ -2174,7 +2176,9 @@ static uint get_table_structure(char *table, char *db, char *table_type, */ my_snprintf(query_buff, sizeof(query_buff), "SHOW FIELDS FROM %s", result_table); - if (mysql_query_with_error_report(mysql, 0, query_buff)) + if (switch_character_set_results(mysql, "binary") || + mysql_query_with_error_report(mysql, &result, query_buff) || + switch_character_set_results(mysql, default_charset)) { /* View references invalid or privileged table/col/fun (err 1356), @@ -2192,43 +2196,50 @@ static uint get_table_structure(char *table, char *db, char *table_type, else my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); - if ((result= mysql_store_result(mysql))) + if (mysql_num_rows(result)) { - if (mysql_num_rows(result)) + if (opt_drop) { - if (opt_drop) - { /* - We have already dropped any table of the same name - above, so here we just drop the view. - */ - - fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n", - opt_quoted_table); - check_io(sql_file); - } - - fprintf(sql_file, "/*!50001 CREATE TABLE %s (\n", result_table); - /* - Get first row, following loop will prepend comma - keeps - from having to know if the row being printed is last to - determine if there should be a _trailing_ comma. + We have already dropped any table of the same name above, so + here we just drop the view. */ - row= mysql_fetch_row(result); - fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0), - row[1]); - - while((row= mysql_fetch_row(result))) - { - /* col name, col type */ - fprintf(sql_file, ",\n %s %s", - quote_name(row[0], name_buff, 0), row[1]); - } - fprintf(sql_file, "\n) */;\n"); + fprintf(sql_file, "/*!50001 DROP VIEW IF EXISTS %s*/;\n", + opt_quoted_table); check_io(sql_file); } + + fprintf(sql_file, + "SET @saved_cs_client = @@character_set_client;\n" + "SET character_set_client = utf8;\n" + "/*!50001 CREATE TABLE %s (\n", + result_table); + + /* + Get first row, following loop will prepend comma - keeps from + having to know if the row being printed is last to determine if + there should be a _trailing_ comma. + */ + + row= mysql_fetch_row(result); + + fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0), + row[1]); + + while((row= mysql_fetch_row(result))) + { + /* col name, col type */ + fprintf(sql_file, ",\n %s %s", + quote_name(row[0], name_buff, 0), row[1]); + } + fprintf(sql_file, + "\n) */;\n" + "SET character_set_client = @saved_cs_client;\n"); + + check_io(sql_file); } + mysql_free_result(result); if (path) @@ -2239,7 +2250,14 @@ static uint get_table_structure(char *table, char *db, char *table_type, } row= mysql_fetch_row(result); - fprintf(sql_file, "%s;\n", row[1]); + + fprintf(sql_file, + "SET @saved_cs_client = @@character_set_client;\n" + "SET character_set_client = utf8;\n" + "%s;\n" + "SET character_set_client = @saved_cs_client;\n", + row[1]); + check_io(sql_file); mysql_free_result(result); } @@ -3726,11 +3744,12 @@ static int dump_all_tables_in_db(char *database) { DYNAMIC_STRING query; init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024); - for (numrows= 0 ; (table= getTableName(1)) ; numrows++) + for (numrows= 0 ; (table= getTableName(1)) ; ) { char *end= strmov(afterdot, table); if (include_table(hash_key,end - hash_key)) { + numrows++; dynstr_append_checked(&query, quote_name(table, table_buff, 1)); dynstr_append_checked(&query, " READ /*!32311 LOCAL */,"); } @@ -3804,6 +3823,11 @@ static my_bool dump_all_views_in_db(char *database) char *table; uint numrows; char table_buff[NAME_LEN*2+3]; + char hash_key[2*NAME_LEN+2]; /* "db.tablename" */ + char *afterdot; + + afterdot= strmov(hash_key, database); + *afterdot++= '.'; if (init_dumping(database, init_dumping_views)) return 1; @@ -3813,10 +3837,15 @@ static my_bool dump_all_views_in_db(char *database) { DYNAMIC_STRING query; init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024); - for (numrows= 0 ; (table= getTableName(1)); numrows++) + for (numrows= 0 ; (table= getTableName(1)); ) { - dynstr_append_checked(&query, quote_name(table, table_buff, 1)); - dynstr_append_checked(&query, " READ /*!32311 LOCAL */,"); + char *end= strmov(afterdot, table); + if (include_table(hash_key,end - hash_key)) + { + numrows++; + dynstr_append_checked(&query, quote_name(table, table_buff, 1)); + dynstr_append_checked(&query, " READ /*!32311 LOCAL */,"); + } } if (numrows && mysql_real_query(mysql, query.str, query.length-1)) DB_error(mysql, "when using LOCK TABLES"); @@ -3830,7 +3859,11 @@ static my_bool dump_all_views_in_db(char *database) /* We shall continue here, if --force was given */ } while ((table= getTableName(0))) - get_view_structure(table, database); + { + char *end= strmov(afterdot, table); + if (include_table(hash_key, end - hash_key)) + get_view_structure(table, database); + } if (opt_xml) { fputs("\n", md_result_file); diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index 591971a32a4..7ca6bb57909 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -814,6 +814,38 @@ create table t1 (a int) engine=innodb; alter table t1 alter a set default 1; drop table t1; +--echo +--echo Bug#24918 drop table and lock / inconsistent between +--echo perm and temp tables +--echo +--echo Check transactional tables under LOCK TABLES +--echo +--disable_warnings +drop table if exists t24918, t24918_tmp, t24918_trans, t24918_trans_tmp, +t24918_access; +--enable_warnings +create table t24918_access (id int); +create table t24918 (id int) engine=myisam; +create temporary table t24918_tmp (id int) engine=myisam; +create table t24918_trans (id int) engine=innodb; +create temporary table t24918_trans_tmp (id int) engine=innodb; + +lock table t24918 write, t24918_tmp write, t24918_trans write, t24918_trans_tmp write; +drop table t24918; +--error ER_TABLE_NOT_LOCKED +select * from t24918_access; +drop table t24918_trans; +--error ER_TABLE_NOT_LOCKED +select * from t24918_access; +drop table t24918_trans_tmp; +--error ER_TABLE_NOT_LOCKED +select * from t24918_access; +drop table t24918_tmp; +--error ER_TABLE_NOT_LOCKED +select * from t24918_access; +unlock tables; + +drop table t24918_access; # # Bug #28591: MySQL need not sort the records in case of ORDER BY # primary_key on InnoDB table diff --git a/mysql-test/r/ddl_i18n_koi8r.result b/mysql-test/r/ddl_i18n_koi8r.result index 9e5931330e2..3d38319df21 100644 --- a/mysql-test/r/ddl_i18n_koi8r.result +++ b/mysql-test/r/ddl_i18n_koi8r.result @@ -1689,12 +1689,18 @@ DELETE FROM mysqltest2.log| CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `log` ( `msg` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (1),(0),(1); ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; @@ -1762,12 +1768,18 @@ ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `log` ( `msg` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (1),(0),(1); ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; diff --git a/mysql-test/r/ddl_i18n_utf8.result b/mysql-test/r/ddl_i18n_utf8.result index d74d014d755..b8e690bfeb7 100644 --- a/mysql-test/r/ddl_i18n_utf8.result +++ b/mysql-test/r/ddl_i18n_utf8.result @@ -1689,12 +1689,18 @@ DELETE FROM mysqltest2.log| CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `log` ( `msg` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (1),(0),(1); ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; @@ -1762,12 +1768,18 @@ ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `log` ( `msg` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (1),(0),(1); ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index 557c8e0b477..1bfa0e84f72 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -611,3 +611,10 @@ id ev_nm ev_cnt DROP TABLE event_log; SET GLOBAL event_scheduler = OFF; DROP DATABASE events_test; +SET GLOBAL event_scheduler= ON; +CREATE EVENT bug28641 ON SCHEDULE AT '2038.01.18 03:00:00' + DO BEGIN +SELECT 1; +END;| +SET GLOBAL event_scheduler= OFF; +DROP EVENT bug28641; diff --git a/mysql-test/r/im_options.result b/mysql-test/r/im_options.result index 3225db0c8c5..22bd5d5bdf6 100644 --- a/mysql-test/r/im_options.result +++ b/mysql-test/r/im_options.result @@ -37,9 +37,10 @@ log-slow-queries option_value language option_value character-sets-dir option_value basedir option_value +shutdown-delay option_value skip-stack-trace option_value -skip-innodb option_value -skip-ndbcluster option_value +loose-skip-innodb option_value +loose-skip-ndbcluster option_value nonguarded option_value log-output option_value SET mysqld2.server_id = 2; @@ -57,9 +58,10 @@ log-slow-queries option_value language option_value character-sets-dir option_value basedir option_value +shutdown-delay option_value skip-stack-trace option_value -skip-innodb option_value -skip-ndbcluster option_value +loose-skip-innodb option_value +loose-skip-ndbcluster option_value nonguarded option_value log-output option_value server_id option_value diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 273374d016b..947f8abcc53 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -814,6 +814,34 @@ drop table if exists t1; create table t1 (a int) engine=innodb; alter table t1 alter a set default 1; drop table t1; + +Bug#24918 drop table and lock / inconsistent between +perm and temp tables + +Check transactional tables under LOCK TABLES + +drop table if exists t24918, t24918_tmp, t24918_trans, t24918_trans_tmp, +t24918_access; +create table t24918_access (id int); +create table t24918 (id int) engine=myisam; +create temporary table t24918_tmp (id int) engine=myisam; +create table t24918_trans (id int) engine=innodb; +create temporary table t24918_trans_tmp (id int) engine=innodb; +lock table t24918 write, t24918_tmp write, t24918_trans write, t24918_trans_tmp write; +drop table t24918; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +drop table t24918_trans; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +drop table t24918_trans_tmp; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +drop table t24918_tmp; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +unlock tables; +drop table t24918_access; CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2); INSERT INTO t1 SELECT a + 8, 2 FROM t1; diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 38b3ebd6e98..0c6be16b9b7 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -153,3 +153,25 @@ select * from mysql.general_log; event_time user_host thread_id server_id command_type argument TIMESTAMP USER_HOST # 1 Query drop table t1 TIMESTAMP USER_HOST # 1 Query select * from mysql.general_log +SET @old_general_log_state = @@global.general_log; +SET @old_slow_log_state = @@global.slow_query_log; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; +FLUSH TABLES WITH READ LOCK; +SET GLOBAL general_log = OFF; +SET GLOBAL slow_query_log = OFF; +UNLOCK TABLES; +FLUSH TABLES WITH READ LOCK; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; +UNLOCK TABLES; +SET GLOBAL READ_ONLY = ON; +SET GLOBAL general_log = OFF; +SET GLOBAL slow_query_log = OFF; +SET GLOBAL READ_ONLY = OFF; +SET GLOBAL READ_ONLY = ON; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; +SET GLOBAL READ_ONLY = OFF; +SET GLOBAL general_log = @old_general_log_state; +SET GLOBAL slow_query_log = @old_slow_log_state; diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index ce3dabe3a56..39349183276 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -29,30 +29,83 @@ on (mysql.general_log.command_type = join_test.command_type) drop table join_test; flush logs; lock tables mysql.general_log WRITE; -ERROR HY000: You can't write-lock a log table. Only read access is possible +ERROR HY000: You can't use locks with log tables. lock tables mysql.slow_log WRITE; -ERROR HY000: You can't write-lock a log table. Only read access is possible +ERROR HY000: You can't use locks with log tables. lock tables mysql.general_log READ; -ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead +ERROR HY000: You can't use locks with log tables. lock tables mysql.slow_log READ; -ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead +ERROR HY000: You can't use locks with log tables. lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL; -unlock tables; -lock tables mysql.general_log READ LOCAL; +ERROR HY000: You can't use locks with log tables. +show create table mysql.general_log; +Table Create Table +general_log CREATE TABLE `general_log` ( + `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `user_host` mediumtext, + `thread_id` int(11) DEFAULT NULL, + `server_id` int(11) DEFAULT NULL, + `command_type` varchar(64) DEFAULT NULL, + `argument` mediumtext +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' +show fields from mysql.general_log; +Field Type Null Key Default Extra +event_time timestamp NO CURRENT_TIMESTAMP +user_host mediumtext YES NULL +thread_id int(11) YES NULL +server_id int(11) YES NULL +command_type varchar(64) YES NULL +argument mediumtext YES NULL +show create table mysql.slow_log; +Table Create Table +slow_log CREATE TABLE `slow_log` ( + `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `user_host` mediumtext NOT NULL, + `query_time` time NOT NULL, + `lock_time` time NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) DEFAULT NULL, + `last_insert_id` int(11) DEFAULT NULL, + `insert_id` int(11) DEFAULT NULL, + `server_id` int(11) DEFAULT NULL, + `sql_text` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log' +show fields from mysql.slow_log; +Field Type Null Key Default Extra +start_time timestamp NO CURRENT_TIMESTAMP +user_host mediumtext NO +query_time time NO +lock_time time NO +rows_sent int(11) NO +rows_examined int(11) NO +db varchar(512) YES NULL +last_insert_id int(11) YES NULL +insert_id int(11) YES NULL +server_id int(11) YES NULL +sql_text mediumtext NO flush logs; -unlock tables; -select "Mark that we woke up from flush logs in the test" - as "test passed"; -test passed -Mark that we woke up from flush logs in the test -lock tables mysql.general_log READ LOCAL; -truncate mysql.general_log; -unlock tables; -select "Mark that we woke up from TRUNCATE in the test" - as "test passed"; -test passed -Mark that we woke up from TRUNCATE in the test -use test; +flush tables; +SET GLOBAL GENERAL_LOG=ON; +SET GLOBAL SLOW_QUERY_LOG=ON; +show open tables; +Database Table In_use Name_locked +mysql general_log 0 0 +flush logs; +show open tables; +Database Table In_use Name_locked +mysql general_log 0 0 +flush tables; +show open tables; +Database Table In_use Name_locked +mysql general_log 0 0 +SET GLOBAL GENERAL_LOG=OFF; +SET GLOBAL SLOW_QUERY_LOG=OFF; +flush tables; +show open tables; +Database Table In_use Name_locked +SET GLOBAL GENERAL_LOG=ON; +SET GLOBAL SLOW_QUERY_LOG=ON; truncate table mysql.general_log; set names utf8; create table bug16905 (s char(15) character set utf8 default 'пусто'); @@ -71,7 +124,7 @@ sleep(2) 0 select * from mysql.slow_log; start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text -TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 select sleep(2) +TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 mysql 0 0 1 select sleep(2) alter table mysql.general_log engine=myisam; ERROR HY000: You cannot 'ALTER' a log table if logging is enabled alter table mysql.slow_log engine=myisam; @@ -158,15 +211,13 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query set global slow_query_log='ON' TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log flush logs; lock tables mysql.general_log WRITE; -ERROR HY000: You can't write-lock a log table. Only read access is possible +ERROR HY000: You can't use locks with log tables. lock tables mysql.slow_log WRITE; -ERROR HY000: You can't write-lock a log table. Only read access is possible +ERROR HY000: You can't use locks with log tables. lock tables mysql.general_log READ; -ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead +ERROR HY000: You can't use locks with log tables. lock tables mysql.slow_log READ; -ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead -lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL; -unlock tables; +ERROR HY000: You can't use locks with log tables. set global general_log='OFF'; set global slow_query_log='OFF'; set @save_storage_engine= @@session.storage_engine; @@ -217,6 +268,7 @@ flush tables with read lock; unlock tables; use mysql; lock tables general_log read local, help_category read local; +ERROR HY000: You can't use locks with log tables. unlock tables; use mysql; RENAME TABLE general_log TO renamed_general_log; @@ -258,9 +310,9 @@ RENAME TABLE general_log TO general_log2; set global slow_query_log='OFF'; RENAME TABLE slow_log TO slow_log2; set global general_log='ON'; -ERROR HY000: Cannot activate 'general' log +ERROR 42S02: Table 'mysql.general_log' doesn't exist set global slow_query_log='ON'; -ERROR HY000: Cannot activate 'slow query' log +ERROR 42S02: Table 'mysql.slow_log' doesn't exist RENAME TABLE general_log2 TO general_log; RENAME TABLE slow_log2 TO slow_log; set global general_log='ON'; @@ -355,3 +407,192 @@ SET SESSION long_query_time =@old_long_query_time; FLUSH LOGS; ALTER TABLE mysql.slow_log DROP COLUMN seq; ALTER TABLE mysql.slow_log ENGINE = CSV; +drop procedure if exists proc25422_truncate_slow; +drop procedure if exists proc25422_truncate_general; +drop procedure if exists proc25422_alter_slow; +drop procedure if exists proc25422_alter_general; +use test// +create procedure proc25422_truncate_slow (loops int) +begin +declare v1 int default 0; +while v1 < loops do +truncate mysql.slow_log; +set v1 = v1 + 1; +end while; +end// +create procedure proc25422_truncate_general (loops int) +begin +declare v1 int default 0; +while v1 < loops do +truncate mysql.general_log; +set v1 = v1 + 1; +end while; +end// +create procedure proc25422_alter_slow (loops int) +begin +declare v1 int default 0; +declare ER_BAD_LOG_STATEMENT condition for 1575; +declare continue handler for ER_BAD_LOG_STATEMENT begin end; +while v1 < loops do +set @old_log_state = @@global.slow_query_log; +set global slow_query_log = 'OFF'; +alter table mysql.slow_log engine = CSV; +set global slow_query_log = @old_log_state; +set v1 = v1 + 1; +end while; +end// +create procedure proc25422_alter_general (loops int) +begin +declare v1 int default 0; +declare ER_BAD_LOG_STATEMENT condition for 1575; +declare continue handler for ER_BAD_LOG_STATEMENT begin end; +while v1 < loops do +set @old_log_state = @@global.general_log; +set global general_log = 'OFF'; +alter table mysql.general_log engine = CSV; +set global general_log = @old_log_state; +set v1 = v1 + 1; +end while; +end// +"Serial test (proc25422_truncate_slow)" +call proc25422_truncate_slow(100); +"Serial test (proc25422_truncate_general)" +call proc25422_truncate_general(100); +"Serial test (proc25422_alter_slow)" +call proc25422_alter_slow(100); +"Serial test (proc25422_alter_general)" +call proc25422_alter_general(100); +"Parallel test" +call proc25422_truncate_slow(100); +call proc25422_truncate_slow(100); +call proc25422_truncate_general(100); +call proc25422_truncate_general(100); +call proc25422_alter_slow(100); +call proc25422_alter_slow(100); +call proc25422_alter_general(100); +call proc25422_alter_general(100); +drop procedure proc25422_truncate_slow; +drop procedure proc25422_truncate_general; +drop procedure proc25422_alter_slow; +drop procedure proc25422_alter_general; +FLUSH TABLE mysql.general_log; +show warnings; +Level Code Message +FLUSH TABLE mysql.slow_log; +show warnings; +Level Code Message +DROP TABLE IF EXISTS `db_17876.slow_log_data`; +DROP TABLE IF EXISTS `db_17876.general_log_data`; +DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; +DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; +DROP DATABASE IF EXISTS `db_17876`; +CREATE DATABASE db_17876; +CREATE TABLE `db_17876.slow_log_data` ( +`start_time` timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, +`user_host` mediumtext , +`query_time` time , +`lock_time` time , +`rows_sent` int(11) , +`rows_examined` int(11) , +`db` varchar(512) default NULL, +`last_insert_id` int(11) default NULL, +`insert_id` int(11) default NULL, +`server_id` int(11) default NULL, +`sql_text` mediumtext +); +CREATE TABLE `db_17876.general_log_data` ( +`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +`user_host` mediumtext, +`thread_id` int(11) DEFAULT NULL, +`server_id` int(11) DEFAULT NULL, +`command_type` varchar(64) DEFAULT NULL, +`argument` mediumtext +); +CREATE procedure `db_17876.archiveSlowLog`() +BEGIN +DECLARE start_time, query_time, lock_time CHAR(20); +DECLARE user_host MEDIUMTEXT; +DECLARE rows_set, rows_examined, last_insert_id, insert_id, server_id INT; +DECLARE dbname MEDIUMTEXT; +DECLARE sql_text BLOB; +DECLARE done INT DEFAULT 0; +DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329; +DECLARE cur1 CURSOR FOR SELECT * FROM mysql.slow_log; +OPEN cur1; +REPEAT +BEGIN +BEGIN +DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1; +FETCH cur1 INTO +start_time, user_host, query_time, lock_time, +rows_set, rows_examined, dbname, last_insert_id, +insert_id, server_id, sql_text; +END; +IF NOT done THEN +BEGIN +INSERT INTO +`db_17876.slow_log_data` + VALUES(start_time, user_host, query_time, lock_time, rows_set, rows_examined, +dbname, last_insert_id, insert_id, server_id, sql_text); +END; +END IF; +END; +UNTIL done END REPEAT; +CLOSE cur1; +TRUNCATE mysql.slow_log; +END // +CREATE procedure `db_17876.archiveGeneralLog`() +BEGIN +DECLARE event_time CHAR(20); +DECLARE user_host, argument MEDIUMTEXT; +DECLARE thread_id, server_id INT; +DECLARE sql_text BLOB; +DECLARE done INT DEFAULT 0; +DECLARE command_type VARCHAR(64); +DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329; +DECLARE cur1 CURSOR FOR SELECT * FROM mysql.general_log; +OPEN cur1; +REPEAT +BEGIN +BEGIN +DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1; +FETCH cur1 INTO +event_time, user_host, thread_id, server_id, +command_type, argument; +END; +IF NOT done THEN +BEGIN +INSERT INTO +`db_17876.general_log_data` + VALUES(event_time, user_host, thread_id, server_id, +command_type, argument); +END; +END IF; +END; +UNTIL done END REPEAT; +CLOSE cur1; +TRUNCATE mysql.general_log; +END // +SET @old_general_log_state = @@global.general_log; +SET @old_slow_log_state = @@global.slow_query_log; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; +select "put something into general_log"; +put something into general_log +put something into general_log +select "... and something more ..."; +... and something more ... +... and something more ... +call `db_17876.archiveSlowLog`(); +call `db_17876.archiveGeneralLog`(); +SET GLOBAL general_log = OFF; +SET GLOBAL slow_query_log = OFF; +call `db_17876.archiveSlowLog`(); +call `db_17876.archiveGeneralLog`(); +DROP TABLE `db_17876.slow_log_data`; +DROP TABLE `db_17876.general_log_data`; +DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; +DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; +DROP DATABASE IF EXISTS `db_17876`; +SET GLOBAL general_log = @old_general_log_state; +SET GLOBAL slow_query_log = @old_slow_log_state; diff --git a/mysql-test/r/mysqldump-max.result b/mysql-test/r/mysqldump-max.result index e78fc4d386a..2d118092a2c 100644 --- a/mysql-test/r/mysqldump-max.result +++ b/mysql-test/r/mysqldump-max.result @@ -93,55 +93,73 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `t3`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t3` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t3` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t3` ENABLE KEYS */; DROP TABLE IF EXISTS `t4`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t4` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t4` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t4` ENABLE KEYS */; DROP TABLE IF EXISTS `t5`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t5` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=ARCHIVE DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t5` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t5` ENABLE KEYS */; DROP TABLE IF EXISTS `t6`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t6` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t6` DISABLE KEYS */; INSERT IGNORE INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); @@ -172,55 +190,73 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT DELAYED INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; INSERT DELAYED INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `t3`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t3` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t3` DISABLE KEYS */; INSERT DELAYED INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t3` ENABLE KEYS */; DROP TABLE IF EXISTS `t4`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t4` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t4` DISABLE KEYS */; INSERT DELAYED INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t4` ENABLE KEYS */; DROP TABLE IF EXISTS `t5`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t5` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=ARCHIVE DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t5` DISABLE KEYS */; INSERT DELAYED INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t5` ENABLE KEYS */; DROP TABLE IF EXISTS `t6`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t6` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t6` DISABLE KEYS */; INSERT INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 1fa18482b9c..58bcac42f9c 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -29,9 +29,12 @@ DROP TABLE t1; CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` decimal(64,20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; # @@ -41,9 +44,12 @@ CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: Warning 1264 Out of range value for column 'a' at row 1 +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; # @@ -59,15 +65,21 @@ INSERT INTO t1 VALUES ('1.2345', 2.3456); INSERT INTO t1 VALUES ("1.2345", 2.3456); ERROR 42S22: Unknown column '1.2345' in 'field list' SET SQL_MODE=@OLD_SQL_MODE; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456); +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL ); +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -81,10 +93,13 @@ INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456) /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -107,10 +122,13 @@ UNLOCK TABLES; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL ); +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456); /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -186,9 +204,12 @@ INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` varchar(255) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=koi8r; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -219,9 +240,12 @@ INSERT INTO t1 VALUES (1), (2); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL40' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) TYPE=MyISAM; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -242,9 +266,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) TYPE=MyISAM; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -263,9 +290,12 @@ DROP TABLE t1; # Bug #2592 'mysqldump doesn't quote "tricky" names correctly' # create table ```a` (i int); +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE ```a` ( `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; drop table ```a`; # # Bug #2591 "mysqldump quotes names inconsistently" @@ -283,9 +313,12 @@ create table t1(a int); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -308,9 +341,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE "t1" ( "a" int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES "t1" WRITE; /*!40000 ALTER TABLE "t1" DISABLE KEYS */; @@ -336,9 +372,12 @@ set global sql_mode='ANSI_QUOTES'; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -361,9 +400,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE "t1" ( "a" int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES "t1" WRITE; /*!40000 ALTER TABLE "t1" DISABLE KEYS */; @@ -393,9 +435,12 @@ insert into t1 values (1),(2),(3); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -484,9 +529,12 @@ INSERT INTO t1 VALUES (_latin1 ' /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -517,9 +565,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) TYPE=MyISAM; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -540,9 +591,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) TYPE=MyISAM; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -563,9 +617,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) TYPE=MyISAM; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -599,9 +656,12 @@ INSERT INTO t2 VALUES (4),(5),(6); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -637,9 +697,12 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -675,9 +738,12 @@ INSERT INTO t1 VALUES (4),(5),(6); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -706,9 +772,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); @@ -1072,6 +1141,8 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `F_c4ca4238a0b923820dcc509a6f75849b` int(11) DEFAULT NULL, `F_c81e728d9d4c2f636f067f89cc14862c` int(11) DEFAULT NULL, @@ -1404,6 +1475,7 @@ CREATE TABLE `t1` ( `F_6faa8040da20ef399b63a72d0e4ab575` int(11) DEFAULT NULL, `F_fe73f687e5bc5280214e0486b273a5f9` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1444,9 +1516,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1485,13 +1560,19 @@ INSERT INTO t2 VALUES (1), (2); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1514,13 +1595,19 @@ CREATE TABLE `t2` ( /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1720,17 +1807,26 @@ create table t3(a int); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t3`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1760,9 +1856,12 @@ mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manu /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -1793,12 +1892,15 @@ insert into t1 values (0815, 4711, 2006); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE "t1" ( "a b" int(11) NOT NULL DEFAULT '0', "c""d" int(11) NOT NULL DEFAULT '0', "e`f" int(11) NOT NULL DEFAULT '0', PRIMARY KEY ("a b","c""d","e`f") ); +SET character_set_client = @saved_cs_client; LOCK TABLES "t1" WRITE; /*!40000 ALTER TABLE "t1" DISABLE KEYS */; @@ -1824,12 +1926,15 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a b` int(11) NOT NULL DEFAULT '0', `c"d` int(11) NOT NULL DEFAULT '0', `e``f` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`a b`,`c"d`,`e``f`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1875,10 +1980,13 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` varchar(30) DEFAULT NULL, KEY `a` (`a`(5)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -1887,9 +1995,12 @@ INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon'); UNLOCK TABLES; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v2` ( `a` varchar(30) ) */; +SET character_set_client = @saved_cs_client; /*!50001 DROP TABLE `v2`*/; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 SET @saved_cs_client = @@character_set_client */; @@ -1968,9 +2079,12 @@ create view v1 as select * from t1; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1978,9 +2092,12 @@ LOCK TABLES `t1` WRITE; UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v1` ( `a` int(11) ) */; +SET character_set_client = @saved_cs_client; /*!50001 DROP TABLE `v1`*/; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 SET @saved_cs_client = @@character_set_client */; @@ -2034,10 +2151,13 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` varchar(30) DEFAULT NULL, KEY `a` (`a`(5)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2046,9 +2166,12 @@ INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon'); UNLOCK TABLES; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v2` ( `a` varchar(30) ) */; +SET character_set_client = @saved_cs_client; /*!50001 DROP TABLE `v2`*/; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 SET @saved_cs_client = @@character_set_client */; @@ -2095,9 +2218,12 @@ INSERT INTO t1 VALUES ('\''); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2138,11 +2264,14 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` varchar(30) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2151,23 +2280,32 @@ INSERT INTO `t1` VALUES (1,2,'one'),(2,4,'two'),(3,6,'three'); UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v1` ( `a` int(11), `b` int(11), `c` varchar(30) ) */; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v2` ( `a` int(11) ) */; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v3`; /*!50001 DROP VIEW IF EXISTS `v3`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v3` ( `a` int(11), `b` int(11), `c` varchar(30) ) */; +SET character_set_client = @saved_cs_client; /*!50001 DROP TABLE `v1`*/; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 SET @saved_cs_client = @@character_set_client */; @@ -2285,10 +2423,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2354,9 +2495,12 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2408,10 +2552,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2419,9 +2566,12 @@ INSERT INTO `t1` VALUES (1,NULL),(2,NULL),(4,NULL),(11,NULL); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2545,9 +2695,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2693,10 +2846,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `d` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `d` (`d`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2727,10 +2883,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `d` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY `d` (`d`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2777,9 +2936,12 @@ a2 /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1 test"; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE "t1 test" ( "a1" int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES "t1 test" WRITE; /*!40000 ALTER TABLE "t1 test" DISABLE KEYS */; @@ -2803,9 +2965,12 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; DROP TABLE IF EXISTS "t2 test"; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE "t2 test" ( "a2" int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES "t2 test" WRITE; /*!40000 ALTER TABLE "t2 test" DISABLE KEYS */; @@ -2854,11 +3019,14 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` varchar(32) DEFAULT NULL, `c` varchar(32) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2867,25 +3035,34 @@ INSERT INTO `t1` VALUES (1,'first value','xxxx'),(2,'second value','tttt'),(3,'t UNLOCK TABLES; DROP TABLE IF EXISTS `v0`; /*!50001 DROP VIEW IF EXISTS `v0`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v0` ( `a` int(11), `b` varchar(32), `c` varchar(32) ) */; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v1` ( `a` int(11), `b` varchar(32), `c` varchar(32) ) */; +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v2` ( `a` int(11), `b` varchar(32), `c` varchar(32) ) */; +SET character_set_client = @saved_cs_client; USE `test`; /*!50001 DROP TABLE `v0`*/; @@ -2973,9 +3150,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3029,10 +3209,13 @@ insert into t1 values ('',''); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` binary(1) DEFAULT NULL, `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3061,10 +3244,13 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` binary(1) DEFAULT NULL, `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3237,9 +3423,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CH USE `mysqldump_test_db`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3248,9 +3437,12 @@ INSERT INTO `t1` VALUES (1232131),(4711),(3231),(815); UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v1` ( `id` int(11) ) */; +SET character_set_client = @saved_cs_client; USE `mysqldump_test_db`; /*!50001 DROP TABLE `v1`*/; @@ -3293,18 +3485,24 @@ create view nasishnasifu as select mysqldump_tables.basetable.id from mysqldump_ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_tables` /*!40100 DEFAULT CHARACTER SET latin1 */; USE `mysqldump_tables`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `basetable` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `tag` varchar(64) DEFAULT NULL, UNIQUE KEY `id` (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHARACTER SET latin1 */; USE `mysqldump_views`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `nasishnasifu` ( `id` bigint(20) unsigned ) */; +SET character_set_client = @saved_cs_client; USE `mysqldump_tables`; @@ -3461,22 +3659,31 @@ CREATE TABLE t1 (a int) ENGINE=merge UNION=(t2, t3); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t2`,`t3`); +SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `t2`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; /*!40000 ALTER TABLE `t2` ENABLE KEYS */; UNLOCK TABLES; DROP TABLE IF EXISTS `t3`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t3` WRITE; /*!40000 ALTER TABLE `t3` DISABLE KEYS */; @@ -3556,10 +3763,13 @@ drop database mysqldump_test_db; # CREATE TABLE t1 (c1 INT, c2 LONGBLOB); INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `c1` int(11) DEFAULT NULL, `c2` longblob ); +SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (11,0x7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171); DROP TABLE t1; # @@ -3614,10 +3824,13 @@ INSERT INTO t1 VALUES (3,4), (4,5); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3881,9 +4094,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CH USE `mysqldump_test_db`; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3892,9 +4108,12 @@ INSERT INTO `t1` VALUES (1232131),(4711),(3231),(815); UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; /*!50001 CREATE TABLE `v1` ( `id` int(11) ) */; +SET character_set_client = @saved_cs_client; USE `mysqldump_test_db`; /*!50001 DROP TABLE `v1`*/; @@ -3925,5 +4144,38 @@ drop view v1; drop table t1; drop database mysqldump_test_db; # +# Bug #30027: mysqldump does not dump views properly. +# + +# Cleanup. +DROP DATABASE IF EXISTS mysqldump_test_db; + +# Create objects. +CREATE DATABASE mysqldump_test_db; +set names koi8r; +CREATE VIEW mysqldump_test_db.v2 AS SELECT 1 AS 1; +CREATE VIEW mysqldump_test_db.v1 AS SELECT 1 FROM mysqldump_test_db.v2; +set names latin1; + +# Dump mysqldump_test_db to bug30027.sql. + +# Drop mysqldump_test_db. +DROP DATABASE mysqldump_test_db; + +# Restore mysqldump_test_db from bug30027.sql. + +# Check the view. +set names utf8; +SHOW CREATE VIEW mysqldump_test_db.v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqldump_test_db`.`v1` AS select `v2`.`колонка1` AS `колонка1` from `mysqldump_test_db`.`v2` koi8r koi8r_general_ci +SHOW CREATE VIEW mysqldump_test_db.v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqldump_test_db`.`v2` AS select 1 AS `колонка1` koi8r koi8r_general_ci +set names latin1; + +# Cleanup. +DROP DATABASE mysqldump_test_db; +# # End of 5.1 tests # diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 5e29e30732f..a042d0a5dc3 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -99,9 +99,12 @@ INSERT INTO t1 VALUES (1), (2); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -130,9 +133,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -161,9 +167,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); +SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 9214d470b37..341a6b7cd43 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1850,61 +1850,57 @@ create procedure proc_1() flush tables; flush tables; show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 call proc_1(); show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 call proc_1(); show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 call proc_1(); show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 flush tables; @@ -1922,54 +1918,50 @@ select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 -mysql host 0 0 mysql user 0 0 +mysql general_log 0 0 +mysql host 0 0 prepare abc from "flush tables"; execute abc; show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 execute abc; show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 execute abc; show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User select Host, Db from mysql.host limit 0; Host Db show open tables from mysql; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql host 0 0 mysql user 0 0 flush tables; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 2bdd29602fb..3a20cbb11da 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -251,14 +251,13 @@ drop table t1; flush tables; show open tables; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 create table t1(n int); insert into t1 values (1); show open tables; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 test t1 0 0 drop table t1; create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" ENGINE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed; @@ -672,24 +671,23 @@ SELECT 1 FROM mysql.db, mysql.proc, mysql.user, mysql.time_zone, mysql.time_zone 1 SHOW OPEN TABLES; Database Table In_use Name_locked -mysql proc 0 0 +mysql db 0 0 test urkunde 0 0 mysql time_zone 0 0 -mysql db 0 0 +mysql general_log 0 0 test txt1 0 0 -mysql slow_log 1 0 +mysql proc 0 0 test tyt2 0 0 -mysql general_log 1 0 mysql user 0 0 mysql time_zone_name 0 0 SHOW OPEN TABLES FROM mysql; Database Table In_use Name_locked -mysql proc 0 0 -mysql time_zone 0 0 mysql db 0 0 -mysql slow_log 1 0 -mysql general_log 1 0 +mysql time_zone 0 0 +mysql general_log 0 0 +mysql slow_log 0 0 mysql user 0 0 +mysql proc 0 0 mysql time_zone_name 0 0 SHOW OPEN TABLES FROM mysql LIKE 'u%'; Database Table In_use Name_locked @@ -702,16 +700,15 @@ test tyt2 0 0 mysql time_zone_name 0 0 SHOW OPEN TABLES LIKE '%o%'; Database Table In_use Name_locked -mysql proc 0 0 mysql time_zone 0 0 -mysql slow_log 1 0 -mysql general_log 1 0 +mysql general_log 0 0 +mysql slow_log 0 0 +mysql proc 0 0 mysql time_zone_name 0 0 FLUSH TABLES; SHOW OPEN TABLES; Database Table In_use Name_locked -mysql general_log 1 0 -mysql slow_log 1 0 +mysql general_log 0 0 DROP TABLE txt1; DROP TABLE tyt2; DROP TABLE urkunde; @@ -1148,6 +1145,26 @@ DROP TABLE t1; DROP VIEW v1; DROP PROCEDURE p1; DROP FUNCTION f1; +set names koi8r; +DROP DATABASE IF EXISTS mysqltest1; +CREATE DATABASE mysqltest1; +use mysqltest1; +CREATE TABLE t1(1 INT); + +---> Dumping mysqltest1 to show_check.mysqltest1.sql + + +DROP DATABASE mysqltest1; + + +---> Restoring mysqltest1... +SHOW CREATE TABLE mysqltest1.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `1` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP DATABASE mysqltest1; +use test; flush status; show variables like "log_queries_not_using_indexes"; Variable_name Value diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index c19bd1abd26..186b2c05d34 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -289,4 +289,34 @@ create table t1 select f_bug22427() as i; ERROR 42S01: Table 't1' already exists drop table t1; drop function f_bug22427; +# +# Bug #29929 LOCK TABLES does not pre-lock tables used in triggers of the locked tables +# +DROP table IF EXISTS t1,t2; +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c2 INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW +BEGIN +UPDATE t2 SET c2= c2 + 1; +END// +# Take a table lock on t1. +# This should pre-lock t2 through the trigger. +LOCK TABLE t1 WRITE; +INSERT INTO t1 VALUES (3); +UNLOCK TABLES; +LOCK TABLE t1 READ; +INSERT INTO t2 values(4); +ERROR HY000: Table 't2' was not locked with LOCK TABLES +UNLOCK TABLES; +SELECT * FROM t1; +c1 +1 +3 +SELECT * FROM t2; +c2 +3 +DROP TRIGGER t1_ai; +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index b6dcbc251d7..8f10625744b 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -1,11 +1,11 @@ flush status; show status like 'Table_lock%'; Variable_name Value -Table_locks_immediate 0 +Table_locks_immediate 1 Table_locks_waited 0 select * from information_schema.session_status where variable_name like 'Table_lock%'; VARIABLE_NAME VARIABLE_VALUE -TABLE_LOCKS_IMMEDIATE 0 +TABLE_LOCKS_IMMEDIATE 2 TABLE_LOCKS_WAITED 0 SET SQL_LOG_BIN=0; drop table if exists t1; @@ -18,11 +18,11 @@ update t1 set n = 3; unlock tables; show status like 'Table_lock%'; Variable_name Value -Table_locks_immediate 3 +Table_locks_immediate 17 Table_locks_waited 1 select * from information_schema.session_status where variable_name like 'Table_lock%'; VARIABLE_NAME VARIABLE_VALUE -TABLE_LOCKS_IMMEDIATE 3 +TABLE_LOCKS_IMMEDIATE 18 TABLE_LOCKS_WAITED 1 drop table t1; select 1; @@ -97,7 +97,7 @@ Variable_name Value Com_show_status 3 show status like 'hand%write%'; Variable_name Value -Handler_write 0 +Handler_write 5 show status like '%tmp%'; Variable_name Value Created_tmp_disk_tables 0 @@ -105,7 +105,7 @@ Created_tmp_files 0 Created_tmp_tables 0 show status like 'hand%write%'; Variable_name Value -Handler_write 0 +Handler_write 7 show status like '%tmp%'; Variable_name Value Created_tmp_disk_tables 0 diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 368a659d939..96b5c8049b8 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -19,6 +19,7 @@ im_instance_conf : Bug#20294 2007-05-30 alik Instance manager tests im_life_cycle : BUG#27851 Instance manager dies on ASSERT in ~Thread_registry() or from not being able to close a mysqld instance. im_instance_conf : BUG#28743 Instance manager generates warnings in test suite im_utils : BUG#28743 Instance manager generates warnings in test suite + concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences ctype_big5 : BUG#26711 2007-06-21 Lars Test has never worked on Double Whopper diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index 4186b4701fa..36052fdb9af 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -722,3 +722,18 @@ let $wait_condition= --source include/wait_condition.inc DROP DATABASE events_test; + + +# +# Bug#28641 CREATE EVENT with '2038.01.18 03:00:00' let server crash. +# +SET GLOBAL event_scheduler= ON; +DELIMITER |; +CREATE EVENT bug28641 ON SCHEDULE AT '2038.01.18 03:00:00' + DO BEGIN + SELECT 1; + END;| + +DELIMITER ;| +SET GLOBAL event_scheduler= OFF; +DROP EVENT bug28641; diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test index 16f466e9b54..b0bb818b783 100644 --- a/mysql-test/t/log_state.test +++ b/mysql-test/t/log_state.test @@ -126,6 +126,59 @@ drop table t1; --replace_column 1 TIMESTAMP 2 USER_HOST 3 # select * from mysql.general_log; +# +# Bug#29129 (Resetting general_log while the GLOBAL READ LOCK is set causes +# a deadlock) + +# save state + +SET @old_general_log_state = @@global.general_log; +SET @old_slow_log_state = @@global.slow_query_log; + +# Test ON->OFF transition under a GLOBAL READ LOCK + +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; + +FLUSH TABLES WITH READ LOCK; + +SET GLOBAL general_log = OFF; +SET GLOBAL slow_query_log = OFF; + +UNLOCK TABLES; + +# Test OFF->ON transition under a GLOBAL READ LOCK + +FLUSH TABLES WITH READ LOCK; + +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; + +UNLOCK TABLES; + +# Test ON->OFF transition under a GLOBAL READ_ONLY + +SET GLOBAL READ_ONLY = ON; + +SET GLOBAL general_log = OFF; +SET GLOBAL slow_query_log = OFF; + +SET GLOBAL READ_ONLY = OFF; + +# Test OFF->ON transition under a GLOBAL READ_ONLY + +SET GLOBAL READ_ONLY = ON; + +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; + +SET GLOBAL READ_ONLY = OFF; + +# Restore state + +SET GLOBAL general_log = @old_general_log_state; +SET GLOBAL slow_query_log = @old_slow_log_state; + --enable_ps_protocol # diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index e8eff7cba0a..8baa4e5a373 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -64,10 +64,10 @@ flush logs; # check locking of the log tables # ---error ER_CANT_WRITE_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.general_log WRITE; ---error ER_CANT_WRITE_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.slow_log WRITE; # @@ -76,78 +76,59 @@ lock tables mysql.slow_log WRITE; # tables are always opened and locked by the logger. # ---error ER_CANT_READ_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.general_log READ; ---error ER_CANT_READ_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.slow_log READ; # -# This call should result in TL_READ lock on the log table. This is ok and -# should pass. +# This call should result in TL_READ lock on the log table. +# This is not ok and should fail. # +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL; -unlock tables; +# Misc locking tests + +show create table mysql.general_log; +show fields from mysql.general_log; + +show create table mysql.slow_log; +show fields from mysql.slow_log; # -# check that FLUSH LOGS waits for all readers of the log table to vanish +# check that FLUSH LOGS does not flush the log tables # -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); +flush logs; +flush tables; -connection con1; +SET GLOBAL GENERAL_LOG=ON; +SET GLOBAL SLOW_QUERY_LOG=ON; -lock tables mysql.general_log READ LOCAL; - -connection con2; - -# this should wait for log tables to unlock -send flush logs; - -connection con1; - -unlock tables; - -# this connection should be alive by the time -connection con2; - -reap; - -select "Mark that we woke up from flush logs in the test" - as "test passed"; +show open tables; +flush logs; +show open tables; # -# perform the same check for TRUNCATE: it should also wait for readers -# to disappear +# check that FLUSH TABLES does flush the log tables # -connection con1; +flush tables; +# Since the flush is logged, mysql.general_log will be in the cache +show open tables; -lock tables mysql.general_log READ LOCAL; +SET GLOBAL GENERAL_LOG=OFF; +SET GLOBAL SLOW_QUERY_LOG=OFF; -connection con2; +flush tables; +# Here the table cache is empty +show open tables; -# this should wait for log tables to unlock -send truncate mysql.general_log; - -connection con1; - -unlock tables; - -# this connection should be alive by the time -connection con2; - -reap; - -select "Mark that we woke up from TRUNCATE in the test" - as "test passed"; - -connection con1; - -use test; +SET GLOBAL GENERAL_LOG=ON; +SET GLOBAL SLOW_QUERY_LOG=ON; # # Bug #16905 Log tables: unicode statements are logged incorrectly @@ -220,10 +201,10 @@ flush logs; # check locking of myisam-based log tables ---error ER_CANT_WRITE_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.general_log WRITE; ---error ER_CANT_WRITE_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.slow_log WRITE; # @@ -232,21 +213,12 @@ lock tables mysql.slow_log WRITE; # tables are always opened and locked by the logger. # ---error ER_CANT_READ_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.general_log READ; ---error ER_CANT_READ_LOCK_LOG_TABLE +--error ER_CANT_LOCK_LOG_TABLE lock tables mysql.slow_log READ; -# -# This call should result in TL_READ lock on the log table. This is ok and -# should pass. -# - -lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL; - -unlock tables; - # check that we can drop them set global general_log='OFF'; set global slow_query_log='OFF'; @@ -314,6 +286,7 @@ use test; flush tables with read lock; unlock tables; use mysql; +--error ER_CANT_LOCK_LOG_TABLE lock tables general_log read local, help_category read local; unlock tables; @@ -368,9 +341,9 @@ set global slow_query_log='OFF'; RENAME TABLE slow_log TO slow_log2; # this should fail ---error ER_CANT_ACTIVATE_LOG +--error ER_NO_SUCH_TABLE set global general_log='ON'; ---error ER_CANT_ACTIVATE_LOG +--error ER_NO_SUCH_TABLE set global slow_query_log='ON'; RENAME TABLE general_log2 TO general_log; @@ -470,8 +443,305 @@ FLUSH LOGS; ALTER TABLE mysql.slow_log DROP COLUMN seq; ALTER TABLE mysql.slow_log ENGINE = CSV; -# kill all connections -disconnect con1; -disconnect con2; +# +# Bug#25422 (Hang with log tables) +# + +--disable_warnings +drop procedure if exists proc25422_truncate_slow; +drop procedure if exists proc25422_truncate_general; +drop procedure if exists proc25422_alter_slow; +drop procedure if exists proc25422_alter_general; +--enable_warnings + +delimiter //; + +use test// +create procedure proc25422_truncate_slow (loops int) +begin + declare v1 int default 0; + while v1 < loops do + truncate mysql.slow_log; + set v1 = v1 + 1; + end while; +end// + +create procedure proc25422_truncate_general (loops int) +begin + declare v1 int default 0; + while v1 < loops do + truncate mysql.general_log; + set v1 = v1 + 1; + end while; +end// + +create procedure proc25422_alter_slow (loops int) +begin + declare v1 int default 0; + declare ER_BAD_LOG_STATEMENT condition for 1575; + declare continue handler for ER_BAD_LOG_STATEMENT begin end; + + while v1 < loops do + set @old_log_state = @@global.slow_query_log; + set global slow_query_log = 'OFF'; + alter table mysql.slow_log engine = CSV; + set global slow_query_log = @old_log_state; + set v1 = v1 + 1; + end while; +end// + +create procedure proc25422_alter_general (loops int) +begin + declare v1 int default 0; + declare ER_BAD_LOG_STATEMENT condition for 1575; + declare continue handler for ER_BAD_LOG_STATEMENT begin end; + + while v1 < loops do + set @old_log_state = @@global.general_log; + set global general_log = 'OFF'; + alter table mysql.general_log engine = CSV; + set global general_log = @old_log_state; + set v1 = v1 + 1; + end while; +end// + +delimiter ;// + +--echo "Serial test (proc25422_truncate_slow)" +call proc25422_truncate_slow(100); +--echo "Serial test (proc25422_truncate_general)" +call proc25422_truncate_general(100); +--echo "Serial test (proc25422_alter_slow)" +call proc25422_alter_slow(100); +--echo "Serial test (proc25422_alter_general)" +call proc25422_alter_general(100); + +--echo "Parallel test" + +# ER_BAD_LOG_STATEMENT errors will occur, +# since concurrent threads do SET GLOBAL general_log= ... +# This is silenced by handlers and will not affect the test + +connect (addconroot1, localhost, root,,); +connect (addconroot2, localhost, root,,); +connect (addconroot3, localhost, root,,); +connect (addconroot4, localhost, root,,); +connect (addconroot5, localhost, root,,); +connect (addconroot6, localhost, root,,); +connect (addconroot7, localhost, root,,); +connect (addconroot8, localhost, root,,); + +connection addconroot1; +send call proc25422_truncate_slow(100); +connection addconroot2; +send call proc25422_truncate_slow(100); + +connection addconroot3; +send call proc25422_truncate_general(100); +connection addconroot4; +send call proc25422_truncate_general(100); + +connection addconroot5; +send call proc25422_alter_slow(100); +connection addconroot6; +send call proc25422_alter_slow(100); + +connection addconroot7; +send call proc25422_alter_general(100); +connection addconroot8; +send call proc25422_alter_general(100); + +connection addconroot1; +reap; +connection addconroot2; +reap; +connection addconroot3; +reap; +connection addconroot4; +reap; +connection addconroot5; +reap; +connection addconroot6; +reap; +connection addconroot7; +reap; +connection addconroot8; +reap; + +connection default; + +disconnect addconroot1; +disconnect addconroot2; +disconnect addconroot3; +disconnect addconroot4; +disconnect addconroot5; +disconnect addconroot6; +disconnect addconroot7; +disconnect addconroot8; + +drop procedure proc25422_truncate_slow; +drop procedure proc25422_truncate_general; +drop procedure proc25422_alter_slow; +drop procedure proc25422_alter_general; + --enable_ps_protocol + +# +# Bug#23044 (Warnings on flush of a log table) +# + +FLUSH TABLE mysql.general_log; +show warnings; + +FLUSH TABLE mysql.slow_log; +show warnings; + +# +# Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the +# thread) +# + +--disable_warnings +DROP TABLE IF EXISTS `db_17876.slow_log_data`; +DROP TABLE IF EXISTS `db_17876.general_log_data`; +DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; +DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; +DROP DATABASE IF EXISTS `db_17876`; +--enable_warnings + +CREATE DATABASE db_17876; + +CREATE TABLE `db_17876.slow_log_data` ( + `start_time` timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `user_host` mediumtext , + `query_time` time , + `lock_time` time , + `rows_sent` int(11) , + `rows_examined` int(11) , + `db` varchar(512) default NULL, + `last_insert_id` int(11) default NULL, + `insert_id` int(11) default NULL, + `server_id` int(11) default NULL, + `sql_text` mediumtext +); + +CREATE TABLE `db_17876.general_log_data` ( + `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `user_host` mediumtext, + `thread_id` int(11) DEFAULT NULL, + `server_id` int(11) DEFAULT NULL, + `command_type` varchar(64) DEFAULT NULL, + `argument` mediumtext +); + +DELIMITER //; + +CREATE procedure `db_17876.archiveSlowLog`() +BEGIN + DECLARE start_time, query_time, lock_time CHAR(20); + DECLARE user_host MEDIUMTEXT; + DECLARE rows_set, rows_examined, last_insert_id, insert_id, server_id INT; + DECLARE dbname MEDIUMTEXT; + DECLARE sql_text BLOB; + DECLARE done INT DEFAULT 0; + DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329; + + DECLARE cur1 CURSOR FOR SELECT * FROM mysql.slow_log; + + OPEN cur1; + + REPEAT + BEGIN + BEGIN + DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1; + + FETCH cur1 INTO + start_time, user_host, query_time, lock_time, + rows_set, rows_examined, dbname, last_insert_id, + insert_id, server_id, sql_text; + END; + + IF NOT done THEN + BEGIN + INSERT INTO + `db_17876.slow_log_data` + VALUES(start_time, user_host, query_time, lock_time, rows_set, rows_examined, + dbname, last_insert_id, insert_id, server_id, sql_text); + END; + END IF; + END; + UNTIL done END REPEAT; + + CLOSE cur1; + TRUNCATE mysql.slow_log; +END // + +CREATE procedure `db_17876.archiveGeneralLog`() +BEGIN + DECLARE event_time CHAR(20); + DECLARE user_host, argument MEDIUMTEXT; + DECLARE thread_id, server_id INT; + DECLARE sql_text BLOB; + DECLARE done INT DEFAULT 0; + DECLARE command_type VARCHAR(64); + DECLARE ER_SP_FETCH_NO_DATA CONDITION for 1329; + + DECLARE cur1 CURSOR FOR SELECT * FROM mysql.general_log; + + OPEN cur1; + + REPEAT + BEGIN + BEGIN + DECLARE CONTINUE HANDLER FOR ER_SP_FETCH_NO_DATA SET done = 1; + + FETCH cur1 INTO + event_time, user_host, thread_id, server_id, + command_type, argument; + END; + + IF NOT done THEN + BEGIN + INSERT INTO + `db_17876.general_log_data` + VALUES(event_time, user_host, thread_id, server_id, + command_type, argument); + END; + END IF; + END; + UNTIL done END REPEAT; + + CLOSE cur1; + TRUNCATE mysql.general_log; +END // + +DELIMITER ;// + +SET @old_general_log_state = @@global.general_log; +SET @old_slow_log_state = @@global.slow_query_log; + +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; + +select "put something into general_log"; +select "... and something more ..."; + +call `db_17876.archiveSlowLog`(); +call `db_17876.archiveGeneralLog`(); + +SET GLOBAL general_log = OFF; +SET GLOBAL slow_query_log = OFF; + +call `db_17876.archiveSlowLog`(); +call `db_17876.archiveGeneralLog`(); + +DROP TABLE `db_17876.slow_log_data`; +DROP TABLE `db_17876.general_log_data`; +DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; +DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; +DROP DATABASE IF EXISTS `db_17876`; + +SET GLOBAL general_log = @old_general_log_state; +SET GLOBAL slow_query_log = @old_slow_log_state; + diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 4e8d3ae916e..171434f9dfd 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1698,6 +1698,63 @@ drop database mysqldump_test_db; --exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug26121.sql --remove_file $MYSQLTEST_VARDIR/tmp/bug26121.sql +########################################################################### + +--echo # +--echo # Bug #30027: mysqldump does not dump views properly. +--echo # + +--echo +--echo # Cleanup. + +--disable_warnings +DROP DATABASE IF EXISTS mysqldump_test_db; +--enable_warnings + +--echo +--echo # Create objects. + +CREATE DATABASE mysqldump_test_db; + +set names koi8r; + +CREATE VIEW mysqldump_test_db.v2 AS SELECT 1 AS 1; +CREATE VIEW mysqldump_test_db.v1 AS SELECT 1 FROM mysqldump_test_db.v2; + +set names latin1; + +--echo +--echo # Dump mysqldump_test_db to bug30027.sql. + +--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --default-character-set=latin1 --databases mysqldump_test_db > $MYSQLTEST_VARDIR/tmp/bug30027.sql + +--echo +--echo # Drop mysqldump_test_db. + +DROP DATABASE mysqldump_test_db; + +--echo +--echo # Restore mysqldump_test_db from bug30027.sql. + +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug30027.sql + +--echo +--echo # Check the view. + +set names utf8; + +SHOW CREATE VIEW mysqldump_test_db.v1; +SHOW CREATE VIEW mysqldump_test_db.v2; + +set names latin1; + +--echo +--echo # Cleanup. + +DROP DATABASE mysqldump_test_db; + +########################################################################### + --echo # --echo # End of 5.1 tests --echo # diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 394f44bbc83..5a4d30fdd50 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -2018,10 +2018,17 @@ delimiter ;| select func_1(), func_1(), func_1() from dual; drop function func_1; drop procedure proc_1; + +# make the output deterministic: +# the order used in SHOW OPEN TABLES +# is too much implementation dependent +--disable_ps_protocol flush tables; select Host, User from mysql.user limit 0; select Host, Db from mysql.host limit 0; show open tables from mysql; +--enable_ps_protocol + prepare abc from "flush tables"; execute abc; show open tables from mysql; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 09c0b08a3cd..77ba1b22065 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -438,6 +438,11 @@ drop table if exists t1; CREATE TABLE txt1(a int); CREATE TABLE tyt2(a int); CREATE TABLE urkunde(a int); + +# make the output deterministic: +# the order used in SHOW OPEN TABLES +# is too much implementation dependent +--disable_ps_protocol FLUSH TABLES; SELECT 1 FROM mysql.db, mysql.proc, mysql.user, mysql.time_zone, mysql.time_zone_name, txt1, tyt2, urkunde LIMIT 0; SHOW OPEN TABLES; @@ -447,6 +452,8 @@ SHOW OPEN TABLES LIKE 't%'; SHOW OPEN TABLES LIKE '%o%'; FLUSH TABLES; SHOW OPEN TABLES; +--enable_ps_protocol + DROP TABLE txt1; DROP TABLE tyt2; DROP TABLE urkunde; @@ -554,6 +561,10 @@ show status like 'slow_queries'; # FROM I_S. # +# +# Part 1: check that meta-data specifies not-binary character set. +# + # Ensure that all needed objects are dropped. --disable_warnings @@ -761,6 +772,59 @@ DROP VIEW v1; DROP PROCEDURE p1; DROP FUNCTION f1; +# +# Part 2: check that table with non-latin1 characters are dumped/restored +# correctly. +# + +# Ensure that all needed objects are dropped. + +set names koi8r; + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +--enable_warnings + +# Create objects. + +CREATE DATABASE mysqltest1; + +use mysqltest1; + +CREATE TABLE t1(1 INT); + +# Check: +# - Dump mysqltest1; + +--echo +--echo ---> Dumping mysqltest1 to show_check.mysqltest1.sql + +--exec $MYSQL_DUMP --default-character-set=latin1 --character-sets-dir=$CHARSETSDIR --databases mysqltest1 > $MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql + +# - Clean mysqltest1; + +--echo +--echo + +DROP DATABASE mysqltest1; + +# - Restore mysqltest1; + +--echo +--echo + +--echo ---> Restoring mysqltest1... +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql + +# - Check definition of the table. + +SHOW CREATE TABLE mysqltest1.t1; + +# Cleanup. + +DROP DATABASE mysqltest1; +use test; + # # Bug #28808: log_queries_not_using_indexes variable dynamic change is ignored # diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index 60e97260839..966c59a5789 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -356,4 +356,35 @@ create table t1 select f_bug22427() as i; drop table t1; drop function f_bug22427; +--echo # +--echo # Bug #29929 LOCK TABLES does not pre-lock tables used in triggers of the locked tables +--echo # +--disable_warnings +DROP table IF EXISTS t1,t2; +--enable_warnings +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c2 INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +DELIMITER //; +CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW +BEGIN +UPDATE t2 SET c2= c2 + 1; +END// +DELIMITER ;// +--echo # Take a table lock on t1. +--echo # This should pre-lock t2 through the trigger. +LOCK TABLE t1 WRITE; +INSERT INTO t1 VALUES (3); +UNLOCK TABLES; +LOCK TABLE t1 READ; +--error ER_TABLE_NOT_LOCKED +INSERT INTO t2 values(4); +UNLOCK TABLES; +SELECT * FROM t1; +SELECT * FROM t2; +DROP TRIGGER t1_ai; +DROP TABLE t1, t2; + --echo End of 5.0 tests + diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index f46c7c7027a..cd0882e3af4 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -63,16 +63,21 @@ CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NUL CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +-- Create general_log if CSV is enabled. -delimiter ;; -CREATE PROCEDURE create_general_log_table() BEGIN DECLARE is_csv_enabled int DEFAULT 0; SELECT @@have_csv = 'YES' INTO is_csv_enabled; IF (is_csv_enabled) THEN CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT, thread_id INTEGER, server_id INTEGER, command_type VARCHAR(64), argument MEDIUMTEXT) engine=CSV CHARACTER SET utf8 comment='General log'; END IF; END;; -CALL create_general_log_table();; -DROP PROCEDURE create_general_log_table;; +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT, thread_id INTEGER, server_id INTEGER, command_type VARCHAR(64), argument MEDIUMTEXT) engine=CSV CHARACTER SET utf8 comment="General log"', 'SET @dummy = 0'); -CREATE PROCEDURE create_slow_log_table() BEGIN DECLARE is_csv_enabled int DEFAULT 0; SELECT @@have_csv = 'YES' INTO is_csv_enabled; IF (is_csv_enabled) THEN CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512), last_insert_id INTEGER, insert_id INTEGER, server_id INTEGER, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment='Slow log'; END IF; END;; -CALL create_slow_log_table();; -DROP PROCEDURE create_slow_log_table;; -delimiter ; +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + +-- Create slow_log if CSV is enabled. + +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512), last_insert_id INTEGER, insert_id INTEGER, server_id INTEGER, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment="Slow log"', 'SET @dummy = 0'); + +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator int(10) NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index e114496248e..b49b0ec0a00 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -403,6 +403,8 @@ void Guardian::init() void Guardian::stop_instances() { + static const int NUM_STOP_ATTEMPTS = 100; + Instance_map::Iterator instances_it(instance_map); Instance *instance; @@ -438,7 +440,34 @@ void Guardian::stop_instances() /* Request mysqld to stop. */ - instance->kill_mysqld(SIGTERM); + bool instance_stopped= FALSE; + + for (int cur_attempt= 0; cur_attempt < NUM_STOP_ATTEMPTS; ++cur_attempt) + { + if (!instance->kill_mysqld(SIGTERM)) + { + instance_stopped= TRUE; + break; + } + + if (!instance->is_active()) + { + instance_stopped= TRUE; + break; + } + + /* Sleep for 0.3 sec and check again. */ + + my_sleep(300000); + } + + /* + Abort if we failed to stop mysqld instance. That should not happen, + but if it happened, we don't know what to do and prefer to have clear + failure with coredump. + */ + + DBUG_ASSERT(instance_stopped); instance->unlock(); } diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index edc9c88fe9f..4a1b658737e 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -524,24 +524,17 @@ bool Instance::init(const LEX_STRING *name_arg) /** - Complete instance options initialization. + @brief Complete instance options initialization. - SYNOPSIS - complete_initialization() - - RETURN - FALSE - ok - TRUE - error + @return Error status. + @retval FALSE ok + @retval TRUE error */ bool Instance::complete_initialization() { configured= ! options.complete_initialization(); - return FALSE; - /* - TODO: return actual status (from - Instance_options::complete_initialization()) here. - */ + return !configured; } /************************************************************************** @@ -644,25 +637,24 @@ bool Instance::is_mysqld_running() /** - Start mysqld. + @brief Start mysqld. - SYNOPSIS - start_mysqld() + Reset flags and start Instance Monitor thread, which will start mysqld. - DESCRIPTION - Reset flags and start Instance Monitor thread, which will start mysqld. + @note Instance must be locked before calling the operation. - MT-NOTE: instance must be locked before calling the operation. - - RETURN - FALSE - ok - TRUE - could not start instance + @return Error status code + @retval FALSE Ok + @retval TRUE Could not start instance */ bool Instance::start_mysqld() { Instance_monitor *instance_monitor; + if (!configured) + return TRUE; + /* Prepare instance to start Instance Monitor thread. @@ -779,7 +771,7 @@ bool Instance::stop_mysqld() These operations should also be used in Guardian to manage instances. */ -void Instance::kill_mysqld(int signum) +bool Instance::kill_mysqld(int signum) { pid_t mysqld_pid= options.load_pid(); @@ -788,7 +780,7 @@ void Instance::kill_mysqld(int signum) log_info("Instance '%s': no pid file to send a signal (%d).", (const char *) get_name()->str, (int) signum); - return; + return TRUE; } log_info("Instance '%s': sending %d to %d...", @@ -800,7 +792,7 @@ void Instance::kill_mysqld(int signum) { log_info("Instance '%s': kill() failed.", (const char *) get_name()->str); - return; + return TRUE; } /* Kill suceeded */ @@ -812,6 +804,8 @@ void Instance::kill_mysqld(int signum) /* After sucessful hard kill the pidfile need to be removed */ options.unlink_pidfile(); } + + return FALSE; } diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index e87bb49b49c..aa9c923cba1 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -104,7 +104,7 @@ public: bool start_mysqld(); bool stop_mysqld(); - void kill_mysqld(int signo); + bool kill_mysqld(int signo); void lock(); void unlock(); diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 5665c6f8670..8b96d6f0f96 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -156,7 +156,8 @@ int Instance_options::get_default_option(char *result, size_t result_len, goto err; /* +2 eats first "--" from the option string (E.g. "--datadir") */ - rc= parse_output_and_get_value((char*) cmd.buffer, option_name + 2, + rc= parse_output_and_get_value((char*) cmd.buffer, + option_name + 2, strlen(option_name + 2), result, result_len, GET_VALUE); err: return rc; @@ -194,8 +195,8 @@ bool Instance_options::fill_instance_version() bzero(result, MAX_VERSION_LENGTH); - if (parse_output_and_get_value((char*) cmd.buffer, "Ver", result, - MAX_VERSION_LENGTH, GET_LINE)) + if (parse_output_and_get_value((char*) cmd.buffer, STRING_WITH_LEN("Ver"), + result, MAX_VERSION_LENGTH, GET_LINE)) { log_error("Failed to get version of '%s': unexpected output.", (const char *) mysqld_path.str); @@ -206,8 +207,7 @@ bool Instance_options::fill_instance_version() { char *start; - /* chop the newline from the end of the version string */ - result[strlen(result) - NEWLINE_LEN]= '\0'; + /* trim leading whitespaces */ start= result; while (my_isspace(default_charset_info, *start)) @@ -255,7 +255,8 @@ bool Instance_options::fill_mysqld_real_path() bzero(result, FN_REFLEN); - if (parse_output_and_get_value((char*) cmd.buffer, "Usage: ", + if (parse_output_and_get_value((char*) cmd.buffer, + STRING_WITH_LEN("Usage: "), result, FN_REFLEN, GET_LINE)) { diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 36eb5185f6b..3511589acd6 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -24,6 +24,13 @@ #include "parse.h" #include "portability.h" +/************************************************************************** + Private module implementation. +**************************************************************************/ + +namespace { /* no-indent */ + +/*************************************************************************/ void trim_space(const char **text, uint *word_len) { @@ -39,90 +46,362 @@ void trim_space(const char **text, uint *word_len) *word_len= (end - start)+1; } -/* - Parse output of the given command +/*************************************************************************/ - SYNOPSIS - parse_output_and_get_value() - - command the command to execue with popen. - word the word to look for (usually an option name) - result the buffer to store the next word (option value) - input_buffer_len self-explanatory - flag this equals to GET_LINE if we want to get all the line after - the matched word and GET_VALUE otherwise. - - DESCRIPTION - - Parse output of the "command". Find the "word" and return the next one - if flag is GET_VALUE. Return the rest of the parsed string otherwise. - - RETURN - 0 - ok, the word has been found - 1 - error occured or the word is not found +/** + @brief A facade to the internal workings of optaining the output from an + executed system process. */ -int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t input_buffer_len, - uint flag) +class Mysqld_output_parser +{ +public: + Mysqld_output_parser() + { } + + virtual ~Mysqld_output_parser() + { } + +public: + bool parse(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type); + +protected: + /** + @brief Run a process and attach stdout- and stdin-pipes to it. + + @param command The path to the process to be executed + + @return Error status. + @retval TRUE An error occurred + @retval FALSE Operation was a success + */ + + virtual bool run_command(const char *command)= 0; + + + /** + @brief Read a sequence of bytes from the executed process' stdout pipe. + + The sequence is terminated by either '\0', LF or CRLF tokens. The + terminating token is excluded from the result. + + @param line_buffer A pointer to a character buffer + @param line_buffer_size The size of the buffer in bytes + + @return Error status. + @retval TRUE An error occured + @retval FALSE Operation was a success + */ + + virtual bool read_line(char *line_buffer, + uint line_buffer_size)= 0; + + + /** + @brief Release any resources needed after a execution and parsing. + */ + + virtual bool cleanup()= 0; +}; + +/*************************************************************************/ + +bool Mysqld_output_parser::parse(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type) { - FILE *output; - uint wordlen; /* should be enough to store the string from the output */ - enum { MAX_LINE_LEN= 512 }; - char linebuf[MAX_LINE_LEN]; - int rc= 1; + const int LINE_BUFFER_SIZE= 512; + char line_buffer[LINE_BUFFER_SIZE]; - wordlen= strlen(word); + if (run_command(command)) + return TRUE; - /* - Successful return of popen does not tell us whether the command has been - executed successfully: if the command was not found, we'll get EOF - when reading the output buffer below. - */ - if (!(output= popen(command, "r"))) - goto err; - - /* - We want fully buffered stream. We also want system to - allocate appropriate buffer. - */ - setvbuf(output, NULL, _IOFBF, 0); - - while (fgets(linebuf, sizeof(linebuf) - 1, output)) + while (true) { - uint found_word_len= 0; - char *linep= linebuf; - - linebuf[sizeof(linebuf) - 1]= '\0'; /* safety */ - - /* - Find the word(s) we are looking for in the line - */ - if ((linep= strstr(linep, word))) + if (read_line(line_buffer, LINE_BUFFER_SIZE)) { - /* - If we have found our word(s), then move linep past the word(s) - */ - linep+= wordlen; - if (flag & GET_VALUE) + cleanup(); + return TRUE; + } + + uint found_word_len= 0; + char *linep= line_buffer; + + line_buffer[sizeof(line_buffer) - 1]= '\0'; /* safety */ + + /* Find the word(s) we are looking for in the line. */ + + linep= strstr(linep, option_name_str); + + if (!linep) + continue; + + linep+= option_name_length; + + switch (option_type) + { + case GET_VALUE: + trim_space((const char**) &linep, &found_word_len); + + if (option_value_buf_size <= found_word_len) { - trim_space((const char**) &linep, &found_word_len); - if (input_buffer_len <= found_word_len) - goto err; - strmake(result, linep, found_word_len); + cleanup(); + return TRUE; } - else /* currently there are only two options */ - strmake(result, linep, input_buffer_len - 1); - rc= 0; + + strmake(option_value_buf, linep, found_word_len); + + break; + + case GET_LINE: + strmake(option_value_buf, linep, option_value_buf_size - 1); + break; } + + cleanup(); + + return FALSE; } - - /* we are not interested in the termination status */ - pclose(output); - -err: - return rc; } +/************************************************************************** + Platform-specific implementation: UNIX. +**************************************************************************/ + +#ifndef __WIN__ + +class Mysqld_output_parser_unix : public Mysqld_output_parser +{ +public: + Mysqld_output_parser_unix() : + m_stdout(NULL) + { } + +protected: + virtual bool run_command(const char *command); + + virtual bool read_line(char *line_buffer, + uint line_buffer_size); + + virtual bool cleanup(); + +private: + FILE *m_stdout; +}; + +bool Mysqld_output_parser_unix::run_command(const char *command) +{ + if (!(m_stdout= popen(command, "r"))) + return TRUE; + + /* + We want fully buffered stream. We also want system to allocate + appropriate buffer. + */ + + setvbuf(m_stdout, NULL, _IOFBF, 0); + + return FALSE; +} + +bool Mysqld_output_parser_unix::read_line(char *line_buffer, + uint line_buffer_size) +{ + char *retbuff = fgets(line_buffer, line_buffer_size, m_stdout); + /* Remove any tailing new line charaters */ + if (line_buffer[line_buffer_size-1] == LF) + line_buffer[line_buffer_size-1]= '\0'; + return (retbuff == NULL); +} + +bool Mysqld_output_parser_unix::cleanup() +{ + if (m_stdout) + pclose(m_stdout); + + return FALSE; +} + +#else /* Windows */ + +/************************************************************************** + Platform-specific implementation: Windows. +**************************************************************************/ + +class Mysqld_output_parser_win : public Mysqld_output_parser +{ +public: + Mysqld_output_parser_win() : + m_internal_buffer(NULL), + m_internal_buffer_offset(0), + m_internal_buffer_size(0) + { } + +protected: + virtual bool run_command(const char *command); + virtual bool read_line(char *line_buffer, + uint line_buffer_size); + virtual bool cleanup(); + +private: + HANDLE m_h_child_stdout_wr; + HANDLE m_h_child_stdout_rd; + uint m_internal_buffer_offset; + uint m_internal_buffer_size; + char *m_internal_buffer; +}; + +bool Mysqld_output_parser_win::run_command(const char *command) +{ + BOOL op_status; + + SECURITY_ATTRIBUTES sa_attr; + sa_attr.nLength= sizeof(SECURITY_ATTRIBUTES); + sa_attr.bInheritHandle= TRUE; + sa_attr.lpSecurityDescriptor= NULL; + + op_status= CreatePipe(&m_h_child_stdout_rd, + &m_h_child_stdout_wr, + &sa_attr, + 0 /* Use system-default buffer size. */); + + if (!op_status) + return TRUE; + + SetHandleInformation(m_h_child_stdout_rd, HANDLE_FLAG_INHERIT, 0); + + STARTUPINFO si_start_info; + ZeroMemory(&si_start_info, sizeof(STARTUPINFO)); + si_start_info.cb= sizeof(STARTUPINFO); + si_start_info.hStdError= m_h_child_stdout_wr; + si_start_info.hStdOutput= m_h_child_stdout_wr; + si_start_info.dwFlags|= STARTF_USESTDHANDLES; + + PROCESS_INFORMATION pi_proc_info; + + op_status= CreateProcess(NULL, /* Application name. */ + (char*)command, /* Command line. */ + NULL, /* Process security attributes. */ + NULL, /* Primary thread security attr.*/ + TRUE, /* Handles are inherited. */ + 0, /* Creation flags. */ + NULL, /* Use parent's environment. */ + NULL, /* Use parent's curr. directory. */ + &si_start_info, /* STARTUPINFO pointer. */ + &pi_proc_info); /* Rec. PROCESS_INFORMATION. */ + + if (!op_status) + { + CloseHandle(m_h_child_stdout_rd); + CloseHandle(m_h_child_stdout_wr); + + return TRUE; + } + + /* Close unnessary handles. */ + + CloseHandle(pi_proc_info.hProcess); + CloseHandle(pi_proc_info.hThread); + + return FALSE; +} + +bool Mysqld_output_parser_win::read_line(char *line_buffer, + uint line_buffer_size) +{ + DWORD dw_read_count= m_internal_buffer_size; + bzero(line_buffer,line_buffer_size); + char *buff_ptr= line_buffer; + char ch; + + while ((unsigned)(buff_ptr - line_buffer) < line_buffer_size) + { + do + { + ReadFile(m_h_child_stdout_rd, &ch, + 1, &dw_read_count, NULL); + } while ((ch == CR || ch == LF) && buff_ptr == line_buffer); + + if (dw_read_count == 0) + return TRUE; + + if (ch == CR || ch == LF) + break; + + *buff_ptr++ = ch; + } + + return FALSE; +} + +bool Mysqld_output_parser_win::cleanup() +{ + /* Close all handles. */ + + CloseHandle(m_h_child_stdout_wr); + CloseHandle(m_h_child_stdout_rd); + + return FALSE; +} +#endif + +/*************************************************************************/ + +} /* End of private module implementation. */ + +/*************************************************************************/ + +/** + @brief Parse output of the given command + + @param command The command to execute. + @param option_name_str Option name. + @param option_name_length Length of the option name. + @param[out] option_value_buf The buffer to store option value. + @param option_value_buf_size Size of the option value buffer. + @param option_type Type of the option: + - GET_LINE if we want to get all the + line after the option name; + - GET_VALUE otherwise. + + Execute the process by running "command". Find the "option name" and + return the next word if "option_type" is GET_VALUE. Return the rest of + the parsed string otherwise. + + @note This function has a separate windows implementation. + + @return The error status. + @retval FALSE Ok, the option name has been found. + @retval TRUE Error occured or the option name is not found. +*/ + +bool parse_output_and_get_value(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type) +{ +#ifndef __WIN__ + Mysqld_output_parser_unix parser; +#else /* __WIN__ */ + Mysqld_output_parser_win parser; +#endif + + return parser.parse(command, + option_name_str, + option_name_length, + option_value_buf, + option_value_buf_size, + option_type); +} diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h index 8851934f230..41618f643a3 100644 --- a/server-tools/instance-manager/parse_output.h +++ b/server-tools/instance-manager/parse_output.h @@ -17,11 +17,17 @@ #include -#define GET_VALUE 1 -#define GET_LINE 2 +enum enum_option_type +{ + GET_VALUE = 1, + GET_LINE +}; -int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t input_buffer_len, - uint flag); +bool parse_output_and_get_value(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type); #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */ diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h index eb677a0135c..990e6140a9e 100644 --- a/server-tools/instance-manager/portability.h +++ b/server-tools/instance-manager/portability.h @@ -48,11 +48,16 @@ typedef int pid_t; #define NEWLINE "\r\n" #define NEWLINE_LEN 2 +const char CR = '\r'; +const char LF = '\n'; + #else /* ! __WIN__ */ #define NEWLINE "\n" #define NEWLINE_LEN 1 +const char LF = '\n'; + #endif /* __WIN__ */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H */ diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc index b06c1240d92..72d81523022 100644 --- a/server-tools/instance-manager/thread_registry.cc +++ b/server-tools/instance-manager/thread_registry.cc @@ -64,11 +64,14 @@ Thread_registry::~Thread_registry() /* Check that no one uses the repository. */ pthread_mutex_lock(&LOCK_thread_registry); - if (head.next != &head) - log_error("Not all threads died properly\n"); + for (Thread_info *ti= head.next; ti != &head; ti= ti->next) + { + log_error("Thread_registry: unregistered thread: %lu.", + (unsigned long) ti->thread_id); + } + /* All threads must unregister */ - // Disabled assert temporarily - BUG#28030 - // DBUG_ASSERT(head.next == &head); + DBUG_ASSERT(head.next == &head); pthread_mutex_unlock(&LOCK_thread_registry); pthread_cond_destroy(&COND_thread_registry_is_empty); diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 7b58c10079a..144a87e13f6 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -979,17 +979,18 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) DBUG_RETURN(TRUE); starts_null= table->field[ET_FIELD_STARTS]->is_null(); + my_bool not_used= FALSE; if (!starts_null) { table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE); - starts= sec_since_epoch_TIME(&time); + starts= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } ends_null= table->field[ET_FIELD_ENDS]->is_null(); if (!ends_null) { table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE); - ends= sec_since_epoch_TIME(&time); + ends= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } if (!table->field[ET_FIELD_INTERVAL_EXPR]->is_null()) @@ -1007,7 +1008,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, TIME_NO_ZERO_DATE)) DBUG_RETURN(TRUE); - execute_at= sec_since_epoch_TIME(&time); + execute_at= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } /* @@ -1039,7 +1040,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) { table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time, TIME_NO_ZERO_DATE); - last_executed= sec_since_epoch_TIME(&time); + last_executed= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } last_executed_changed= FALSE; diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index a16a04739e2..b7bcb6344fd 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -250,7 +250,7 @@ mysql_event_fill_row(THD *thd, if (!et->starts_null) { MYSQL_TIME time; - my_tz_UTC->gmt_sec_to_TIME(&time, et->starts); + my_tz_OFFSET0->gmt_sec_to_TIME(&time, et->starts); fields[ET_FIELD_STARTS]->set_notnull(); fields[ET_FIELD_STARTS]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); @@ -259,7 +259,7 @@ mysql_event_fill_row(THD *thd, if (!et->ends_null) { MYSQL_TIME time; - my_tz_UTC->gmt_sec_to_TIME(&time, et->ends); + my_tz_OFFSET0->gmt_sec_to_TIME(&time, et->ends); fields[ET_FIELD_ENDS]->set_notnull(); fields[ET_FIELD_ENDS]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); @@ -278,7 +278,7 @@ mysql_event_fill_row(THD *thd, fields[ET_FIELD_ENDS]->set_null(); MYSQL_TIME time; - my_tz_UTC->gmt_sec_to_TIME(&time, et->execute_at); + my_tz_OFFSET0->gmt_sec_to_TIME(&time, et->execute_at); fields[ET_FIELD_EXECUTE_AT]->set_notnull(); fields[ET_FIELD_EXECUTE_AT]-> @@ -1004,7 +1004,7 @@ update_timing_fields_for_event(THD *thd, if (update_last_executed) { MYSQL_TIME time; - my_tz_UTC->gmt_sec_to_TIME(&time, last_executed); + my_tz_OFFSET0->gmt_sec_to_TIME(&time, last_executed); fields[ET_FIELD_LAST_EXECUTED]->set_notnull(); fields[ET_FIELD_LAST_EXECUTED]->store_time(&time, diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 634cc764d74..04449dd48a1 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -740,7 +740,7 @@ Event_queue::dump_internal_status() printf("WOC : %s\n", waiting_on_cond? "YES":"NO"); MYSQL_TIME time; - my_tz_UTC->gmt_sec_to_TIME(&time, next_activation_at); + my_tz_OFFSET0->gmt_sec_to_TIME(&time, next_activation_at); if (time.year != 1970) printf("Next activation : %04d-%02d-%02d %02d:%02d:%02d\n", time.year, time.month, time.day, time.hour, time.minute, time.second); diff --git a/sql/handler.cc b/sql/handler.cc index 55e2e478027..f06ad282efa 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1516,34 +1516,6 @@ THD *handler::ha_thd(void) const } -bool handler::check_if_log_table_locking_is_allowed(uint sql_command, - ulong type, TABLE *table) -{ - /* - Deny locking of the log tables, which is incompatible with - concurrent insert. The routine is not called if the table is - being locked from a logger THD (general_log_thd or slow_log_thd) - or from a privileged thread (see log.cc for details) - */ - if (table->s->log_table && - sql_command != SQLCOM_TRUNCATE && - sql_command != SQLCOM_ALTER_TABLE && - !(sql_command == SQLCOM_FLUSH && - type & REFRESH_LOG) && - (table->reginfo.lock_type >= TL_READ_NO_INSERT)) - { - /* - The check >= TL_READ_NO_INSERT denies all write locks - plus the only read lock (TL_READ_NO_INSERT itself) - */ - table->reginfo.lock_type == TL_READ_NO_INSERT ? - my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0)) : - my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0)); - return FALSE; - } - return TRUE; -} - /** @brief Open database-handler. @@ -3687,6 +3659,7 @@ int handler::ha_write_row(uchar *buf) return 0; } + int handler::ha_update_row(const uchar *old_data, uchar *new_data) { int error; diff --git a/sql/handler.h b/sql/handler.h index f45b28c55f5..7cf7bfe043d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -992,6 +992,7 @@ public: uint ref_length; FT_INFO *ft_handler; enum {NONE=0, INDEX, RND} inited; + bool locked; bool implicit_emptied; /* Can be !=0 only if HEAP */ const COND *pushed_cond; /* @@ -1022,11 +1023,13 @@ public: estimation_rows_to_insert(0), ht(ht_arg), ref(0), key_used_on_scan(MAX_KEY), active_index(MAX_KEY), ref_length(sizeof(my_off_t)), - ft_handler(0), inited(NONE), implicit_emptied(0), + ft_handler(0), inited(NONE), + locked(FALSE), implicit_emptied(0), pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0) {} virtual ~handler(void) { + DBUG_ASSERT(locked == FALSE); /* TODO: DBUG_ASSERT(inited == NONE); */ } virtual handler *clone(MEM_ROOT *mem_root); @@ -1035,44 +1038,6 @@ public: { cached_table_flags= table_flags(); } - /* - Check whether a handler allows to lock the table. - - SYNOPSIS - check_if_locking_is_allowed() - thd Handler of the thread, trying to lock the table - table Table handler to check - count Total number of tables to be locked - current Index of the current table in the list of the tables - to be locked. - system_count Pointer to the counter of system tables seen thus - far. - called_by_privileged_thread TRUE if called from a logger THD - (general_log_thd or slow_log_thd) - or by a privileged thread, which - has the right to lock log tables. - - DESCRIPTION - Check whether a handler allows to lock the table. For instance, - MyISAM does not allow to lock mysql.proc along with other tables. - This limitation stems from the fact that MyISAM does not support - row-level locking and we have to add this limitation to avoid - deadlocks. - - RETURN - TRUE Locking is allowed - FALSE Locking is not allowed. The error was thrown. - */ - virtual bool check_if_locking_is_allowed(uint sql_command, - ulong type, TABLE *table, - uint count, uint current, - uint *system_count, - bool called_by_privileged_thread) - { - return TRUE; - } - bool check_if_log_table_locking_is_allowed(uint sql_command, - ulong type, TABLE *table); int ha_open(TABLE *table, const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); int update_auto_increment(); @@ -1629,8 +1594,10 @@ public: /* lock_count() can be more than one if the table is a MERGE */ virtual uint lock_count(void) const { return 1; } - /* - NOTE that one can NOT rely on table->in_use in store_lock(). It may + /** + Is not invoked for non-transactional temporary tables. + + @note that one can NOT rely on table->in_use in store_lock(). It may refer to a different thread if called from mysql_lock_abort_for_thread(). */ virtual THR_LOCK_DATA **store_lock(THD *thd, @@ -1761,6 +1728,29 @@ private: overridden by the storage engine class. To call these methods, use the corresponding 'ha_*' method above. */ + + /** + Is not invoked for non-transactional temporary tables. + + Tells the storage engine that we intend to read or write data + from the table. This call is prefixed with a call to handler::store_lock() + and is invoked only for those handler instances that stored the lock. + + Calls to rnd_init/index_init are prefixed with this call. When table + IO is complete, we call external_lock(F_UNLCK). + A storage engine writer should expect that each call to + ::external_lock(F_[RD|WR]LOCK is followed by a call to + ::external_lock(F_UNLCK). If it is not, it is a bug in MySQL. + + The name and signature originate from the first implementation + in MyISAM, which would call fcntl to set/clear an advisory + lock on the data file in this method. + + @param lock_type F_RDLCK, F_WRLCK, F_UNLCK + + @return non-0 in case of failure, 0 in case of success. + When lock_type is F_UNLCK, the return value is ignored. + */ virtual int external_lock(THD *thd __attribute__((unused)), int lock_type __attribute__((unused))) { diff --git a/sql/lock.cc b/sql/lock.cc index 63d0807b975..08ff90ce983 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -116,16 +116,90 @@ static void print_lock_error(int error, const char *); static int thr_lock_errno_to_mysql[]= { 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK }; +/** + Perform semantic checks for mysql_lock_tables. + @param thd The current thread + @param tables The tables to lock + @param count The number of tables to lock + @param flags Lock flags + @return 0 if all the check passed, non zero if a check failed. +*/ +int mysql_lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags) +{ + bool log_table_write_query; + uint system_count; + uint i; + + DBUG_ENTER("mysql_lock_tables_check"); + + system_count= 0; + log_table_write_query= (is_log_table_write_query(thd->lex->sql_command) + || ((flags & MYSQL_LOCK_PERF_SCHEMA) != 0)); + + for (i=0 ; is->table_category != TABLE_UNKNOWN_CATEGORY); + + /* + Table I/O to performance schema tables is performed + only internally by the server implementation. + When a user is requesting a lock, the following + constraints are enforced: + */ + if (t->s->require_write_privileges() && + ! log_table_write_query) + { + /* + A user should not be able to prevent writes, + or hold any type of lock in a session, + since this would be a DOS attack. + */ + if ((t->reginfo.lock_type >= TL_READ_NO_INSERT) + || (thd->lex->sql_command == SQLCOM_LOCK_TABLES)) + { + my_error(ER_CANT_LOCK_LOG_TABLE, MYF(0)); + DBUG_RETURN(1); + } + } + + if ((t->s->table_category == TABLE_CATEGORY_SYSTEM) && + (t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE)) + { + system_count++; + } + } + + /* + Locking of system tables is restricted: + locking a mix of system and non-system tables in the same lock + is prohibited, to prevent contention. + */ + if ((system_count > 0) && (system_count < count)) + { + my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0)); + DBUG_RETURN(1); + } + + DBUG_RETURN(0); +} + MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags, bool *need_reopen) { MYSQL_LOCK *sql_lock; TABLE *write_lock_used; int rc; + DBUG_ENTER("mysql_lock_tables"); *need_reopen= FALSE; + if (mysql_lock_tables_check(thd, tables, count, flags)) + DBUG_RETURN (NULL); + for (;;) { if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS, @@ -175,7 +249,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, thd->proc_info="System lock"; DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info)); - if (lock_external(thd, tables, count)) + if (sql_lock->table_count && lock_external(thd, sql_lock->table, + sql_lock->table_count)) { /* Clear the lock type of all lock data to avoid reusage. */ reset_lock_data(sql_lock); @@ -271,6 +346,7 @@ static int lock_external(THD *thd, TABLE **tables, uint count) ((*tables)->reginfo.lock_type >= TL_READ && (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT)) lock_type=F_RDLCK; + if ((error=(*tables)->file->ha_external_lock(thd,lock_type))) { print_lock_error(error, (*tables)->file->table_type()); @@ -379,10 +455,28 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock) } +/** + Try to find the table in the list of locked tables. + In case of success, unlock the table and remove it from this list. -void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table) + @note This function has a legacy side effect: the table is + unlocked even if it is not found in the locked list. + It's not clear if this side effect is intentional or still + desirable. It might lead to unmatched calls to + unlock_external(). Moreover, a discrepancy can be left + unnoticed by the storage engine, because in + unlock_external() we call handler::external_lock(F_UNLCK) only + if table->current_lock is not F_UNLCK. + + @param always_unlock specify explicitly if the legacy side + effect is desired. +*/ + +void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table, + bool always_unlock) { - mysql_unlock_some_tables(thd, &table,1); + if (always_unlock == TRUE) + mysql_unlock_some_tables(thd, &table, /* table count */ 1); if (locked) { reg1 uint i; @@ -396,6 +490,10 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table) DBUG_ASSERT(table->lock_position == i); + /* Unlock if not yet unlocked */ + if (always_unlock == FALSE) + mysql_unlock_some_tables(thd, &table, /* table count */ 1); + /* Decrement table_count in advance, making below expressions easier */ old_tables= --locked->table_count; @@ -445,7 +543,8 @@ void mysql_lock_downgrade_write(THD *thd, TABLE *table, { MYSQL_LOCK *locked; TABLE *write_lock_used; - if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used))) + if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK, + &write_lock_used))) { for (uint i=0; i < locked->lock_count; i++) thr_downgrade_write_lock(locked->locks[i], new_lock_type); @@ -704,25 +803,19 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, TABLE **to, **table_buf; DBUG_ENTER("get_lock_data"); + DBUG_ASSERT((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS)); + DBUG_PRINT("info", ("count %d", count)); *write_lock_used=0; - uint system_count= 0; for (i=tables=lock_count=0 ; i < count ; i++) { - if (table_ptr[i]->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE) + TABLE *t= table_ptr[i]; + + if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE) { - tables+=table_ptr[i]->file->lock_count(); + tables+= t->file->lock_count(); lock_count++; } - /* - Check if we can lock the table. For some tables we cannot do that - beacause of handler-specific locking issues. - */ - if (!table_ptr[i]-> file-> - check_if_locking_is_allowed(thd->lex->sql_command, thd->lex->type, - table_ptr[i], count, i, &system_count, - logger.is_privileged_thread(thd))) - DBUG_RETURN(0); } /* diff --git a/sql/log.cc b/sql/log.cc index 0bf77d68410..dbb664c9d18 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -57,6 +57,35 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all); static int binlog_rollback(handlerton *hton, THD *thd, bool all); static int binlog_prepare(handlerton *hton, THD *thd, bool all); +/** + Silence all errors and warnings reported when performing a write + to a log table. + Errors and warnings are not reported to the client or SQL exception + handlers, so that the presence of logging does not interfere and affect + the logic of an application. +*/ +class Silence_log_table_errors : public Internal_error_handler +{ +public: + Silence_log_table_errors() + {} + + virtual ~Silence_log_table_errors() {} + + virtual bool handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level, + THD *thd); +}; + +bool +Silence_log_table_errors::handle_error(uint /* sql_errno */, + MYSQL_ERROR::enum_warning_level /* level */, + THD * /* thd */) +{ + return TRUE; +} + + sql_print_message_func sql_print_message_handlers[3] = { sql_print_information, @@ -187,6 +216,19 @@ public: handlerton *binlog_hton; +bool LOGGER::is_log_table_enabled(uint log_table_type) +{ + switch (log_table_type) { + case QUERY_LOG_SLOW: + return (table_log_handler != NULL) && opt_slow_log; + case QUERY_LOG_GENERAL: + return (table_log_handler != NULL) && opt_log ; + default: + DBUG_ASSERT(0); + return FALSE; /* make compiler happy */ + } +} + /* Check if a given table is opened log table */ int check_if_log_table(uint db_len, const char *db, uint table_name_len, @@ -200,211 +242,38 @@ int check_if_log_table(uint db_len, const char *db, uint table_name_len, if (table_name_len == 11 && !(lower_case_table_names ? my_strcasecmp(system_charset_info, table_name, "general_log") : - strcmp(table_name, "general_log")) && - (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL))) - return QUERY_LOG_GENERAL; - else - if (table_name_len == 8 && !(lower_case_table_names ? - my_strcasecmp(system_charset_info, table_name, "slow_log") : - strcmp(table_name, "slow_log")) && - (!check_if_opened ||logger.is_log_table_enabled(QUERY_LOG_SLOW))) + strcmp(table_name, "general_log"))) + { + if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL)) + return QUERY_LOG_GENERAL; + return 0; + } + + if (table_name_len == 8 && !(lower_case_table_names ? + my_strcasecmp(system_charset_info, table_name, "slow_log") : + strcmp(table_name, "slow_log"))) + { + if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_SLOW)) return QUERY_LOG_SLOW; + return 0; + } } return 0; } -/* - Open log table of a given type (general or slow log) - - SYNOPSIS - open_log_table() - - log_table_type type of the log table to open: QUERY_LOG_GENERAL - or QUERY_LOG_SLOW - - DESCRIPTION - - The function opens a log table and marks it as such. Log tables are open - during the whole time, while server is running. Except for the moments - when they have to be reopened: during FLUSH LOGS and TRUNCATE. This - function is invoked directly only once during startup. All subsequent - calls happen through reopen_log_table(), which performs additional check. - - RETURN - FALSE - OK - TRUE - error occured -*/ - -bool Log_to_csv_event_handler::open_log_table(uint log_table_type) -{ - THD *log_thd, *curr= current_thd; - TABLE_LIST *table; - bool error= FALSE; - DBUG_ENTER("open_log_table"); - - switch (log_table_type) { - case QUERY_LOG_GENERAL: - log_thd= general_log_thd; - table= &general_log; - /* clean up table before reuse/initial usage */ - bzero((char*) table, sizeof(TABLE_LIST)); - table->alias= table->table_name= (char*) "general_log"; - table->table_name_length= 11; - break; - case QUERY_LOG_SLOW: - log_thd= slow_log_thd; - table= &slow_log; - bzero((char*) table, sizeof(TABLE_LIST)); - table->alias= table->table_name= (char*) "slow_log"; - table->table_name_length= 8; - break; - default: - assert(0); // Impossible - } - - /* - This way we check that appropriate log thd was created ok during - initialization. We cannot check "is_log_tables_initialized" var, as - the very initialization is not finished until this function is - completed in the very first time. - */ - if (!log_thd) - { - DBUG_PRINT("error",("Cannot initialize log tables")); - DBUG_RETURN(TRUE); - } - - /* - Set THD's thread_stack. This is needed to perform stack overrun - check, which is done by some routines (e.g. open_table()). - In the case we are called by thread, which already has this parameter - set, we use this value. Otherwise we do a wild guess. This won't help - to correctly track the stack overrun in these exceptional cases (which - could probably happen only during startup and shutdown) but at least - lets us to pass asserts. - The problem stems from the fact that logger THDs are not real threads. - */ - if (curr) - log_thd->thread_stack= curr->thread_stack; - else - log_thd->thread_stack= (char*) &log_thd; - - log_thd->store_globals(); - - table->lock_type= TL_WRITE_CONCURRENT_INSERT; - table->db= log_thd->db; - table->db_length= log_thd->db_length; - - lex_start(log_thd); - log_thd->clear_error(); - if (simple_open_n_lock_tables(log_thd, table) || - table->table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || - table->table->file->ha_rnd_init(0)) - error= TRUE; - else - { - table->table->use_all_columns(); - table->table->locked_by_logger= TRUE; - table->table->no_replicate= TRUE; - - /* Honor next number columns if present */ - table->table->next_number_field= table->table->found_next_number_field; - } - /* restore thread settings */ - if (curr) - curr->store_globals(); - else - { - my_pthread_setspecific_ptr(THR_THD, 0); - my_pthread_setspecific_ptr(THR_MALLOC, 0); - } - - /* - After a log table was opened, we should clear privileged thread - flag (which allows locking of a log table by a special thread, usually - the one who closed log tables temporarily). - */ - privileged_thread= 0; - DBUG_RETURN(error); -} - - Log_to_csv_event_handler::Log_to_csv_event_handler() { - /* init artificial THD's */ - general_log_thd= new THD; - /* logger thread always works with mysql database */ - general_log_thd->db= my_strdup("mysql", MYF(0)); - general_log_thd->db_length= 5; - general_log.table= 0; - - slow_log_thd= new THD; - /* logger thread always works with mysql database */ - slow_log_thd->db= my_strdup("mysql", MYF(0));; - slow_log_thd->db_length= 5; - slow_log.table= 0; - /* no privileged thread exists at the moment */ - privileged_thread= 0; } Log_to_csv_event_handler::~Log_to_csv_event_handler() { - /* now cleanup the tables */ - if (general_log_thd) - { - delete general_log_thd; - general_log_thd= NULL; - } - - if (slow_log_thd) - { - delete slow_log_thd; - slow_log_thd= NULL; - } -} - - -/* - Reopen log table of a given type - - SYNOPSIS - reopen_log_table() - - log_table_type type of the log table to open: QUERY_LOG_GENERAL - or QUERY_LOG_SLOW - - DESCRIPTION - - The function is a wrapper around open_log_table(). It is used during - FLUSH LOGS and TRUNCATE of the log tables (i.e. when we need to close - and reopen them). The difference is in the check of the - logger.is_log_tables_initialized var, which can't be done in - open_log_table(), as it makes no sense during startup. - - NOTE: this code assumes that we have logger mutex locked - - RETURN - FALSE - ok - TRUE - open_log_table() returned an error -*/ - -bool Log_to_csv_event_handler::reopen_log_table(uint log_table_type) -{ - /* don't open the log table, if it wasn't enabled during startup */ - if (!logger.is_log_tables_initialized) - return FALSE; - return open_log_table(log_table_type); } void Log_to_csv_event_handler::cleanup() { - if (opt_log) - close_log_table(QUERY_LOG_GENERAL, FALSE); - if (opt_slow_log) - close_log_table(QUERY_LOG_SLOW, FALSE); logger.is_log_tables_initialized= FALSE; } @@ -436,49 +305,88 @@ void Log_to_csv_event_handler::cleanup() */ bool Log_to_csv_event_handler:: - log_general(time_t event_time, const char *user_host, + log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, CHARSET_INFO *client_cs) { - TABLE *table= general_log.table; + TABLE_LIST table_list; + TABLE *table; + bool result= TRUE; + bool need_close= FALSE; + bool need_pop= FALSE; + bool need_rnd_end= FALSE; uint field_index; + Silence_log_table_errors error_handler; + Open_tables_state open_tables_backup; + Field_timestamp *field0; + ulonglong save_thd_options; + bool save_query_start_used; + time_t save_start_time; + time_t save_time_after_lock; + time_t save_user_time; + bool save_time_zone_used; + + save_thd_options= thd->options; + thd->options&= ~OPTION_BIN_LOG; + + save_query_start_used= thd->query_start_used; + save_start_time= thd->start_time; + save_time_after_lock= thd->time_after_lock; + save_user_time= thd->user_time; + save_time_zone_used= thd->time_zone_used; + + bzero(& table_list, sizeof(TABLE_LIST)); + table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str; + table_list.table_name_length= GENERAL_LOG_NAME.length; + + table_list.lock_type= TL_WRITE_CONCURRENT_INSERT; + + table_list.db= MYSQL_SCHEMA_NAME.str; + table_list.db_length= MYSQL_SCHEMA_NAME.length; + + table= open_performance_schema_table(thd, & table_list, + & open_tables_backup); + need_close= TRUE; + + if (!table || + table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || + table->file->ha_rnd_init(0)) + goto err; + + need_rnd_end= TRUE; + + /* Honor next number columns if present */ + table->next_number_field= table->found_next_number_field; /* "INSERT INTO general_log" can generate warning sometimes. - Let's reset warnings from previous queries, - otherwise warning list can grow too much, - so thd->query gets spoiled as some point in time, - and mysql_parse() receives a broken query. QQ: this problem needs to be studied in more details. - Probably it's better to suppress warnings in logging INSERTs at all. - Comment this line and run "cast.test" to see what's happening: + Comment this 2 lines and run "cast.test" to see what's happening: */ - mysql_reset_errors(table->in_use, 1); - - /* below should never happen */ - if (unlikely(!logger.is_log_tables_initialized)) - return FALSE; + thd->push_internal_handler(& error_handler); + need_pop= TRUE; /* NOTE: we do not call restore_record() here, as all fields are filled by the Logger (=> no need to load default ones). */ - /* Set current time. Required for CURRENT_TIMESTAMP to work */ - general_log_thd->start_time= event_time; - /* We do not set a value for table->field[0], as it will use default value (which is CURRENT_TIMESTAMP). */ /* check that all columns exist */ - if (!table->field[1] || !table->field[2] || !table->field[3] || - !table->field[4] || !table->field[5]) + if (table->s->fields < 6) goto err; + DBUG_ASSERT(table->field[0]->type() == MYSQL_TYPE_TIMESTAMP); + + field0= (Field_timestamp*) (table->field[0]); + field0->set_time(); + /* do a write */ if (table->field[1]->store(user_host, user_host_len, client_cs) || table->field[2]->store((longlong) thread_id, TRUE) || @@ -500,16 +408,39 @@ bool Log_to_csv_event_handler:: table->field[field_index]->set_default(); } - /* log table entries are not replicated at the moment */ - tmp_disable_binlog(current_thd); + /* log table entries are not replicated */ + if (table->file->ha_write_row(table->record[0])) + { + struct tm start; + localtime_r(&event_time, &start); - table->file->ha_write_row(table->record[0]); + sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.general_log", + start.tm_year % 100, start.tm_mon + 1, + start.tm_mday, start.tm_hour, + start.tm_min, start.tm_sec); + } - reenable_binlog(current_thd); + result= FALSE; - return FALSE; err: - return TRUE; + if (need_rnd_end) + { + table->file->ha_rnd_end(); + table->file->ha_release_auto_increment(); + } + if (need_pop) + thd->pop_internal_handler(); + if (need_close) + close_performance_schema_table(thd, & open_tables_backup); + + thd->options= save_thd_options; + + thd->query_start_used= save_query_start_used; + thd->start_time= save_start_time; + thd->time_after_lock= save_time_after_lock; + thd->user_time= save_user_time; + thd->time_zone_used= save_time_zone_used; + return result; } @@ -548,34 +479,61 @@ bool Log_to_csv_event_handler:: longlong query_time, longlong lock_time, bool is_command, const char *sql_text, uint sql_text_len) { - /* table variables */ - TABLE *table= slow_log.table; + TABLE_LIST table_list; + TABLE *table; + bool result= TRUE; + bool need_close= FALSE; + bool need_rnd_end= FALSE; + Open_tables_state open_tables_backup; + bool save_query_start_used; + time_t save_start_time; + time_t save_time_after_lock; + time_t save_user_time; + bool save_time_zone_used; CHARSET_INFO *client_cs= thd->variables.character_set_client; - DBUG_ENTER("log_slow"); + DBUG_ENTER("Log_to_csv_event_handler::log_slow"); - /* below should never happen */ - if (unlikely(!logger.is_log_tables_initialized)) - return FALSE; + bzero(& table_list, sizeof(TABLE_LIST)); + table_list.alias= table_list.table_name= SLOW_LOG_NAME.str; + table_list.table_name_length= SLOW_LOG_NAME.length; + + table_list.lock_type= TL_WRITE_CONCURRENT_INSERT; + + table_list.db= MYSQL_SCHEMA_NAME.str; + table_list.db_length= MYSQL_SCHEMA_NAME.length; + + save_query_start_used= thd->query_start_used; + save_start_time= thd->start_time; + save_time_after_lock= thd->time_after_lock; + save_user_time= thd->user_time; + save_time_zone_used= thd->time_zone_used; + + table= open_performance_schema_table(thd, & table_list, + & open_tables_backup); + need_close= TRUE; + + if (!table || + table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || + table->file->ha_rnd_init(0)) + goto err; + + need_rnd_end= TRUE; + + /* Honor next number columns if present */ + table->next_number_field= table->found_next_number_field; - /* - Set start time for CURRENT_TIMESTAMP to the start of the query. - This will be default value for the field[0] - */ - slow_log_thd->start_time= query_start_arg; restore_record(table, s->default_values); // Get empty record + /* check that all columns exist */ + if (table->s->fields < 11) + goto err; + /* We do not set a value for table->field[0], as it will use default value. */ - if (!table->field[1] || !table->field[2] || !table->field[3] || - !table->field[4] || !table->field[5] || !table->field[6] || - !table->field[7] || !table->field[8] || !table->field[9] || - !table->field[10]) - goto err; - /* store the value */ if (table->field[1]->store(user_host, user_host_len, client_cs)) goto err; @@ -612,7 +570,6 @@ bool Log_to_csv_event_handler:: table->field[4]->set_null(); table->field[5]->set_null(); } - /* fill database field */ if (thd->db) { @@ -654,17 +611,71 @@ bool Log_to_csv_event_handler:: if (table->field[10]->store(sql_text,sql_text_len, client_cs)) goto err; - /* log table entries are not replicated at the moment */ - tmp_disable_binlog(current_thd); + /* log table entries are not replicated */ + if (table->file->ha_write_row(table->record[0])) + { + struct tm start; + localtime_r(¤t_time, &start); - /* write the row */ - table->file->ha_write_row(table->record[0]); + sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.slow_log", + start.tm_year % 100, start.tm_mon + 1, + start.tm_mday, start.tm_hour, + start.tm_min, start.tm_sec); + } - reenable_binlog(current_thd); + result= FALSE; - DBUG_RETURN(0); err: - DBUG_RETURN(1); + if (need_rnd_end) + { + table->file->ha_rnd_end(); + table->file->ha_release_auto_increment(); + } + if (need_close) + close_performance_schema_table(thd, & open_tables_backup); + + thd->query_start_used= save_query_start_used; + thd->start_time= save_start_time; + thd->time_after_lock= save_time_after_lock; + thd->user_time= save_user_time; + thd->time_zone_used= save_time_zone_used; + DBUG_RETURN(result); +} + +int Log_to_csv_event_handler:: + activate_log(THD *thd, uint log_table_type) +{ + TABLE_LIST table_list; + TABLE *table; + int result; + Open_tables_state open_tables_backup; + + DBUG_ENTER("Log_to_csv_event_handler::activate_log"); + + bzero(& table_list, sizeof(TABLE_LIST)); + + if (log_table_type == QUERY_LOG_GENERAL) + { + table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str; + table_list.table_name_length= GENERAL_LOG_NAME.length; + } + else + { + DBUG_ASSERT(log_table_type == QUERY_LOG_SLOW); + table_list.alias= table_list.table_name= SLOW_LOG_NAME.str; + table_list.table_name_length= SLOW_LOG_NAME.length; + } + + table_list.lock_type= TL_WRITE_CONCURRENT_INSERT; + + table_list.db= MYSQL_SCHEMA_NAME.str; + table_list.db_length= MYSQL_SCHEMA_NAME.length; + + table= open_performance_schema_table(thd, & table_list, + & open_tables_backup); + result= (table ? 0 : 1); + close_performance_schema_table(thd, & open_tables_backup); + DBUG_RETURN(result); } bool Log_to_csv_event_handler:: @@ -710,7 +721,7 @@ bool Log_to_file_event_handler:: */ bool Log_to_file_event_handler:: - log_general(time_t event_time, const char *user_host, + log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, @@ -787,7 +798,7 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format, void LOGGER::cleanup_base() { DBUG_ASSERT(inited == 1); - (void) pthread_mutex_destroy(&LOCK_logger); + rwlock_destroy(&LOCK_logger); if (table_log_handler) { table_log_handler->cleanup(); @@ -806,12 +817,6 @@ void LOGGER::cleanup_end() } -void LOGGER::close_log_table(uint log_table_type, bool lock_in_use) -{ - table_log_handler->close_log_table(log_table_type, lock_in_use); -} - - /* Perform basic log initialization: create file-based log handler and init error log. @@ -833,7 +838,7 @@ void LOGGER::init_base() init_error_log(LOG_FILE); file_log_handler->init_pthread_objects(); - (void) pthread_mutex_init(&LOCK_logger, MY_MUTEX_INIT_SLOW); + my_rwlock_init(&LOCK_logger, NULL); } @@ -848,29 +853,6 @@ void LOGGER::init_log_tables() } -bool LOGGER::reopen_log_table(uint log_table_type) -{ - return table_log_handler->reopen_log_table(log_table_type); -} - -bool LOGGER::reopen_log_tables() -{ - /* - we use | and not || here, to ensure that both reopen_log_table - are called, even if the first one fails - */ - if ((opt_slow_log && logger.reopen_log_table(QUERY_LOG_SLOW)) | - (opt_log && logger.reopen_log_table(QUERY_LOG_GENERAL))) - return TRUE; - return FALSE; -} - - -void LOGGER::tmp_close_log_tables(THD *thd) -{ - table_log_handler->tmp_close_log_tables(thd); -} - bool LOGGER::flush_logs(THD *thd) { int rc= 0; @@ -879,19 +861,11 @@ bool LOGGER::flush_logs(THD *thd) Now we lock logger, as nobody should be able to use logging routines while log tables are closed */ - logger.lock(); - if (logger.is_log_tables_initialized) - table_log_handler->tmp_close_log_tables(thd); // the locking happens here + logger.lock_exclusive(); /* reopen log files */ file_log_handler->flush(); - /* reopen tables in the case they were enabled */ - if (logger.is_log_tables_initialized) - { - if (reopen_log_tables()) - rc= TRUE; - } /* end of log flush */ logger.unlock(); return rc; @@ -939,7 +913,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, if (thd->slave_thread) return 0; - lock(); + lock_shared(); if (!opt_slow_log) { unlock(); @@ -1011,7 +985,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, else id=0; /* Log from connect handler */ - lock(); + lock_shared(); if (!opt_log) { unlock(); @@ -1035,7 +1009,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, while (*current_handler) error+= (*current_handler++)-> - log_general(current_time, user_host_buff, + log_general(thd, current_time, user_host_buff, user_host_len, id, command_name[(uint) command].str, command_name[(uint) command].length, @@ -1122,35 +1096,51 @@ void LOGGER::init_general_log(uint general_log_printer) bool LOGGER::activate_log_handler(THD* thd, uint log_type) { - bool res= 0; - lock(); + MYSQL_QUERY_LOG *file_log; + bool res= FALSE; + lock_exclusive(); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) { - if ((res= reopen_log_table(log_type))) - goto err; - file_log_handler->get_mysql_slow_log()-> - open_slow_log(sys_var_slow_log_path.value); - init_slow_log(log_output_options); - opt_slow_log= TRUE; + file_log= file_log_handler->get_mysql_slow_log(); + + file_log->open_slow_log(sys_var_slow_log_path.value); + if (table_log_handler->activate_log(thd, QUERY_LOG_SLOW)) + { + /* Error printed by open table in activate_log() */ + res= TRUE; + file_log->close(0); + } + else + { + init_slow_log(log_output_options); + opt_slow_log= TRUE; + } } break; case QUERY_LOG_GENERAL: if (!opt_log) { - if ((res= reopen_log_table(log_type))) - goto err; - file_log_handler->get_mysql_log()-> - open_query_log(sys_var_general_log_path.value); - init_general_log(log_output_options); - opt_log= TRUE; + file_log= file_log_handler->get_mysql_log(); + + file_log->open_query_log(sys_var_general_log_path.value); + if (table_log_handler->activate_log(thd, QUERY_LOG_GENERAL)) + { + /* Error printed by open table in activate_log() */ + res= TRUE; + file_log->close(0); + } + else + { + init_general_log(log_output_options); + opt_log= TRUE; + } } break; default: DBUG_ASSERT(0); } -err: unlock(); return res; } @@ -1158,23 +1148,17 @@ err: void LOGGER::deactivate_log_handler(THD *thd, uint log_type) { - TABLE_LIST *table_list; my_bool *tmp_opt= 0; MYSQL_LOG *file_log; - THD *log_thd; switch (log_type) { case QUERY_LOG_SLOW: - table_list= &table_log_handler->slow_log; tmp_opt= &opt_slow_log; file_log= file_log_handler->get_mysql_slow_log(); - log_thd= table_log_handler->slow_log_thd; break; case QUERY_LOG_GENERAL: - table_list= &table_log_handler->general_log; tmp_opt= &opt_log; file_log= file_log_handler->get_mysql_log(); - log_thd= table_log_handler->general_log_thd; break; default: assert(0); // Impossible @@ -1183,81 +1167,16 @@ void LOGGER::deactivate_log_handler(THD *thd, uint log_type) if (!(*tmp_opt)) return; - if (is_log_tables_initialized) - lock_and_wait_for_table_name(log_thd, table_list); - lock(); - - if (is_log_tables_initialized) - { - VOID(pthread_mutex_lock(&LOCK_open)); - close_log_table(log_type, TRUE); - table_list->table= 0; - query_cache_invalidate3(log_thd, table_list, 0); - unlock_table_name(log_thd, table_list); - VOID(pthread_mutex_unlock(&LOCK_open)); - } + lock_exclusive(); file_log->close(0); *tmp_opt= FALSE; unlock(); } -/* - Close log tables temporarily. The thread which closed - them this way can lock them in any mode it needs. - NOTE: one should call logger.lock() before entering this - function. -*/ -void Log_to_csv_event_handler::tmp_close_log_tables(THD *thd) -{ - TABLE_LIST close_slow_log, close_general_log; - - /* fill lists, we will need to perform operations on tables */ - bzero((char*) &close_slow_log, sizeof(TABLE_LIST)); - close_slow_log.alias= close_slow_log.table_name=(char*) "slow_log"; - close_slow_log.table_name_length= 8; - close_slow_log.db= (char*) "mysql"; - close_slow_log.db_length= 5; - - bzero((char*) &close_general_log, sizeof(TABLE_LIST)); - close_general_log.alias= close_general_log.table_name=(char*) "general_log"; - close_general_log.table_name_length= 11; - close_general_log.db= (char*) "mysql"; - close_general_log.db_length= 5; - - privileged_thread= thd; - - VOID(pthread_mutex_lock(&LOCK_open)); - /* - NOTE: in fact, the first parameter used in query_cache_invalidate3() - could be any non-NULL THD, as the underlying code makes certain - assumptions about this. - Here we use one of the logger handler THD's. Simply because it - seems appropriate. - */ - if (opt_log) - { - close_log_table(QUERY_LOG_GENERAL, TRUE); - query_cache_invalidate3(general_log_thd, &close_general_log, 0); - } - if (opt_slow_log) - { - close_log_table(QUERY_LOG_SLOW, TRUE); - query_cache_invalidate3(general_log_thd, &close_slow_log, 0); - } - VOID(pthread_mutex_unlock(&LOCK_open)); -} - /* the parameters are unused for the log tables */ bool Log_to_csv_event_handler::init() { - /* - we use | and not || here, to ensure that both open_log_table - are called, even if the first one fails - */ - if ((opt_log && open_log_table(QUERY_LOG_GENERAL)) | - (opt_slow_log && open_log_table(QUERY_LOG_SLOW))) - return 1; return 0; } @@ -1268,7 +1187,7 @@ int LOGGER::set_handlers(uint error_log_printer, /* error log table is not supported yet */ DBUG_ASSERT(error_log_printer < LOG_TABLE); - lock(); + lock_exclusive(); if ((slow_log_printer & LOG_TABLE || general_log_printer & LOG_TABLE) && !is_log_tables_initialized) @@ -1290,72 +1209,6 @@ int LOGGER::set_handlers(uint error_log_printer, } -/* - Close log table of a given type (general or slow log) - - SYNOPSIS - close_log_table() - - log_table_type type of the log table to close: QUERY_LOG_GENERAL - or QUERY_LOG_SLOW - lock_in_use Set to TRUE if the caller owns LOCK_open. FALSE otherwise. - - DESCRIPTION - - The function closes a log table. It is invoked (1) when we need to reopen - log tables (e.g. FLUSH LOGS or TRUNCATE on the log table is being - executed) or (2) during shutdown. -*/ - -void Log_to_csv_event_handler:: - close_log_table(uint log_table_type, bool lock_in_use) -{ - THD *log_thd, *curr= current_thd; - TABLE_LIST *table; - - if (!logger.is_log_table_enabled(log_table_type)) - return; /* do nothing */ - - switch (log_table_type) { - case QUERY_LOG_GENERAL: - log_thd= general_log_thd; - table= &general_log; - break; - case QUERY_LOG_SLOW: - log_thd= slow_log_thd; - table= &slow_log; - break; - default: - assert(0); // Impossible - } - - /* - Set thread stack start for the logger thread. See comment in - open_log_table() for details. - */ - if (curr) - log_thd->thread_stack= curr->thread_stack; - else - log_thd->thread_stack= (char*) &log_thd; - - /* close the table */ - log_thd->store_globals(); - table->table->file->ha_rnd_end(); - table->table->file->ha_release_auto_increment(); - /* discard logger mark before unlock*/ - table->table->locked_by_logger= FALSE; - close_thread_tables(log_thd, lock_in_use); - - if (curr) - curr->store_globals(); - else - { - my_pthread_setspecific_ptr(THR_THD, 0); - my_pthread_setspecific_ptr(THR_MALLOC, 0); - } -} - - /* Save position of binary log transaction cache. @@ -2097,6 +1950,8 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host, struct tm start; uint time_buff_len= 0; + (void) pthread_mutex_lock(&LOCK_log); + /* Test if someone closed between the is_open test and lock */ if (is_open()) { @@ -2141,6 +1996,7 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host, goto err; } + (void) pthread_mutex_unlock(&LOCK_log); return FALSE; err: @@ -2149,6 +2005,7 @@ err: write_error= 1; sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } + (void) pthread_mutex_unlock(&LOCK_log); return TRUE; } @@ -2191,8 +2048,13 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, bool error= 0; DBUG_ENTER("MYSQL_QUERY_LOG::write"); + (void) pthread_mutex_lock(&LOCK_log); + if (!is_open()) + { + (void) pthread_mutex_unlock(&LOCK_log); DBUG_RETURN(0); + } if (is_open()) { // Safety agains reopen @@ -2296,6 +2158,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, } } } + (void) pthread_mutex_unlock(&LOCK_log); DBUG_RETURN(error); } diff --git a/sql/log.h b/sql/log.h index d92e0117bcc..3b1a0950daa 100644 --- a/sql/log.h +++ b/sql/log.h @@ -212,6 +212,7 @@ public: return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0, WRITE_CACHE); } + private: time_t last_time; }; @@ -398,7 +399,7 @@ public: const char *sql_text, uint sql_text_len)= 0; virtual bool log_error(enum loglevel level, const char *format, va_list args)= 0; - virtual bool log_general(time_t event_time, const char *user_host, + virtual bool log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, @@ -412,27 +413,7 @@ int check_if_log_table(uint db_len, const char *db, uint table_name_len, class Log_to_csv_event_handler: public Log_event_handler { - /* - We create artificial THD for each of the logs. This is to avoid - locking issues: we don't want locks on the log tables reside in the - THD's of the query. The reason is the locking order and duration. - */ - THD *general_log_thd, *slow_log_thd; - /* - This is for the thread, which called tmp_close_log_tables. The thread - will be allowed to write-lock the log tables (as it explicitly disabled - logging). This is used for such operations as REPAIR, which require - exclusive lock on the log tables. - NOTE: there can be only one priviliged thread, as one should - lock logger with logger.lock() before calling tmp_close_log_tables(). - So no other thread could get privileged status at the same time. - */ - THD *privileged_thread; friend class LOGGER; - TABLE_LIST general_log, slow_log; - -private: - bool open_log_table(uint log_type); public: Log_to_csv_event_handler(); @@ -447,18 +428,13 @@ public: const char *sql_text, uint sql_text_len); virtual bool log_error(enum loglevel level, const char *format, va_list args); - virtual bool log_general(time_t event_time, const char *user_host, + virtual bool log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, - CHARSET_INFO *client_cs); - void tmp_close_log_tables(THD *thd); - void close_log_table(uint log_type, bool lock_in_use); - bool reopen_log_table(uint log_type); - THD* get_privileged_thread() - { - return privileged_thread; - } + CHARSET_INFO *client_cs); + + int activate_log(THD *thd, uint log_type); }; @@ -484,7 +460,7 @@ public: const char *sql_text, uint sql_text_len); virtual bool log_error(enum loglevel level, const char *format, va_list args); - virtual bool log_general(time_t event_time, const char *user_host, + virtual bool log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, @@ -499,7 +475,7 @@ public: /* Class which manages slow, general and error log event handlers */ class LOGGER { - pthread_mutex_t LOCK_logger; + rw_lock_t LOCK_logger; /* flag to check whether logger mutex is initialized */ uint inited; @@ -519,21 +495,10 @@ public: LOGGER() : inited(0), table_log_handler(NULL), file_log_handler(NULL), is_log_tables_initialized(FALSE) {} - void lock() { (void) pthread_mutex_lock(&LOCK_logger); } - void unlock() { (void) pthread_mutex_unlock(&LOCK_logger); } - void tmp_close_log_tables(THD *thd); - bool is_log_table_enabled(uint log_table_type) - { - switch (log_table_type) { - case QUERY_LOG_SLOW: - return table_log_handler && table_log_handler->slow_log.table != 0; - case QUERY_LOG_GENERAL: - return table_log_handler && table_log_handler->general_log.table != 0; - default: - DBUG_ASSERT(0); - return FALSE; /* make compiler happy */ - } - } + void lock_shared() { rw_rdlock(&LOCK_logger); } + void lock_exclusive() { rw_wrlock(&LOCK_logger); } + void unlock() { rw_unlock(&LOCK_logger); } + bool is_log_table_enabled(uint log_table_type); /* We want to initialize all log mutexes as soon as possible, but we cannot do it in constructor, as safe_mutex relies on @@ -543,20 +508,6 @@ public: void init_base(); void init_log_tables(); bool flush_logs(THD *thd); - THD *get_general_log_thd() - { - if (table_log_handler) - return (THD *) table_log_handler->general_log_thd; - else - return NULL; - } - THD *get_slow_log_thd() - { - if (table_log_handler) - return (THD *) table_log_handler->slow_log_thd; - else - return NULL; - } /* Perform basic logger cleanup. this will leave e.g. error log open. */ void cleanup_base(); /* Free memory. Nothing could be logged after this function is called */ @@ -568,10 +519,6 @@ public: bool general_log_print(THD *thd,enum enum_server_command command, const char *format, va_list args); - void close_log_table(uint log_type, bool lock_in_use); - bool reopen_log_table(uint log_type); - bool reopen_log_tables(); - /* we use this function to setup all enabled log event handlers */ int set_handlers(uint error_log_printer, uint slow_log_printer, @@ -593,19 +540,6 @@ public: return file_log_handler->get_mysql_log(); return NULL; } - THD* get_privileged_thread() - { - if (table_log_handler) - return table_log_handler->get_privileged_thread(); - else - return NULL; - } - bool is_privileged_thread(THD *thd) - { - return thd == get_general_log_thd() || - thd == get_slow_log_thd() || - thd == get_privileged_thread(); - } }; enum enum_binlog_format { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7b7bc81957e..2fe70980ea8 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -944,6 +944,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); bool is_update_query(enum enum_sql_command command); +bool is_log_table_write_query(enum enum_sql_command command); bool alloc_query(THD *thd, const char *packet, uint packet_length); void mysql_init_select(LEX *lex); void mysql_reset_thd_for_next_command(THD *thd); @@ -1123,7 +1124,8 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, uint key_length, uint db_flags, int *error); void release_table_share(TABLE_SHARE *share, enum release_type type); TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name); -TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); +TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, + uint lock_flags); TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem, bool *refresh, uint flags); bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in); @@ -1231,6 +1233,11 @@ void reset_status_vars(); /* information schema */ extern LEX_STRING INFORMATION_SCHEMA_NAME; +/* log tables */ +extern LEX_STRING MYSQL_SCHEMA_NAME; +extern LEX_STRING GENERAL_LOG_NAME; +extern LEX_STRING SLOW_LOG_NAME; + extern const LEX_STRING partition_keywords[]; ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name); ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx); @@ -1557,6 +1564,10 @@ bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, void close_system_tables(THD *thd, Open_tables_state *backup); TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table); +TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table, + Open_tables_state *backup); +void close_performance_schema_table(THD *thd, Open_tables_state *backup); + bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables, bool have_lock = FALSE); bool close_cached_connection_tables(THD *thd, bool wait_for_refresh, LEX_STRING *connect_string, @@ -1891,11 +1902,13 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, #define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004 #define MYSQL_OPEN_TEMPORARY_ONLY 0x0008 #define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0010 +#define MYSQL_LOCK_PERF_SCHEMA 0x0020 void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); -void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); +void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table, + bool always_unlock); void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock); void mysql_lock_downgrade_write(THD *thd, TABLE *table, thr_lock_type new_lock_type); diff --git a/sql/set_var.cc b/sql/set_var.cc index 7f3e808090d..d21a4c18716 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2053,21 +2053,15 @@ end: bool sys_var_log_state::update(THD *thd, set_var *var) { - bool res= 0; + bool res; pthread_mutex_lock(&LOCK_global_system_variables); if (!var->save_result.ulong_value) - logger.deactivate_log_handler(thd, log_type); - else { - if ((res= logger.activate_log_handler(thd, log_type))) - { - my_error(ER_CANT_ACTIVATE_LOG, MYF(0), - log_type == QUERY_LOG_GENERAL ? "general" : - "slow query"); - goto err; - } + logger.deactivate_log_handler(thd, log_type); + res= false; } -err: + else + res= logger.activate_log_handler(thd, log_type); pthread_mutex_unlock(&LOCK_global_system_variables); return res; } @@ -2143,7 +2137,7 @@ bool update_sys_var_str_path(THD *thd, sys_var_str *var_str, } pthread_mutex_lock(&LOCK_global_system_variables); - logger.lock(); + logger.lock_exclusive(); if (file_log && log_state) file_log->close(0); @@ -2206,7 +2200,7 @@ static void sys_default_slow_log_path(THD *thd, enum_var_type type) bool sys_var_log_output::update(THD *thd, set_var *var) { pthread_mutex_lock(&LOCK_global_system_variables); - logger.lock(); + logger.lock_exclusive(); logger.init_slow_log(var->save_result.ulong_value); logger.init_general_log(var->save_result.ulong_value); *value= var->save_result.ulong_value; @@ -2219,7 +2213,7 @@ bool sys_var_log_output::update(THD *thd, set_var *var) void sys_var_log_output::set_default(THD *thd, enum_var_type type) { pthread_mutex_lock(&LOCK_global_system_variables); - logger.lock(); + logger.lock_exclusive(); logger.init_slow_log(LOG_FILE); logger.init_general_log(LOG_FILE); *value= LOG_FILE; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 682eee06e02..966e841ccbf 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5936,8 +5936,8 @@ ER_WARN_DEPRECATED_SYNTAX_WITH_VER ER_CANT_WRITE_LOCK_LOG_TABLE eng "You can't write-lock a log table. Only read access is possible" ger "Eine Log-Tabelle kann nicht schreibgesperrt werden. Es ist ohnehin nur Lesezugriff mglich" -ER_CANT_READ_LOCK_LOG_TABLE - eng "You can't use usual read lock with log tables. Try READ LOCAL instead" +ER_CANT_LOCK_LOG_TABLE + eng "You can't use locks with log tables." ger "Log-Tabellen knnen nicht mit normalen Lesesperren gesperrt werden. Verwenden Sie statt dessen READ LOCAL" ER_FOREIGN_DUPLICATE_KEY 23000 S1009 eng "Upholding foreign key constraints for table '%.192s', entry '%-.192s', key %d would lead to a duplicate entry" diff --git a/sql/slave.cc b/sql/slave.cc index 2e8e3f582de..96a105b06e4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -977,7 +977,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, thd->proc_info = "Opening master dump table"; tables.lock_type = TL_WRITE; - if (!open_ltable(thd, &tables, TL_WRITE)) + if (!open_ltable(thd, &tables, TL_WRITE, 0)) { sql_print_error("create_table_from_dump: could not open created table"); goto err; diff --git a/sql/sp.cc b/sql/sp.cc index aed4976f839..372aa9c6780 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -406,7 +406,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK) goto done; - if (table->s->fields != MYSQL_PROC_FIELD_COUNT) + if (table->s->fields < MYSQL_PROC_FIELD_COUNT) { ret= SP_GET_FIELD_FAILED; goto done; @@ -695,7 +695,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) strxnmov(definer, sizeof(definer)-1, thd->lex->definer->user.str, "@", thd->lex->definer->host.str, NullS); - if (table->s->fields != MYSQL_PROC_FIELD_COUNT) + if (table->s->fields < MYSQL_PROC_FIELD_COUNT) { ret= SP_GET_FIELD_FAILED; goto done; @@ -1067,7 +1067,7 @@ sp_show_status_routine(THD *thd, int type, const char *name_pattern) tables.db= (char*)"mysql"; tables.table_name= tables.alias= (char*)"proc"; - if (! (table= open_ltable(thd, &tables, TL_READ))) + if (! (table= open_ltable(thd, &tables, TL_READ, 0))) { res= SP_OPEN_TABLE_FAILED; goto done; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 67fa380d313..91f1570f653 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1602,7 +1602,7 @@ bool change_password(THD *thd, const char *host, const char *user, } #endif - if (!(table= open_ltable(thd, &tables, TL_WRITE))) + if (!(table= open_ltable(thd, &tables, TL_WRITE, 0))) DBUG_RETURN(1); VOID(pthread_mutex_lock(&acl_cache->lock)); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f1319010270..cf3ef111780 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -902,8 +902,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, bool found=0; for (TABLE_LIST *table= tables; table; table= table->next_local) { - if ((!table->table || !table->table->s->log_table) && - remove_table_from_cache(thd, table->db, table->table_name, + if (remove_table_from_cache(thd, table->db, table->table_name, RTFC_OWNED_BY_THD_FLAG)) found=1; } @@ -951,8 +950,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, are employed by CREATE TABLE as in this case table simply does not exist yet. */ - if (!table->s->log_table && - (table->needs_reopen_or_name_lock() && table->db_stat)) + if (table->needs_reopen_or_name_lock() && table->db_stat) { found=1; DBUG_PRINT("signal", ("Waiting for COND_refresh")); @@ -1679,8 +1677,28 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) } -/* - Close temporary table and unlink from thd->temporary tables +/** + Drop a temporary table. + + Try to locate the table in the list of thd->temporary_tables. + If the table is found: + - if the table is in thd->locked_tables, unlock it and + remove it from the list of locked tables. Currently only transactional + temporary tables are present in the locked_tables list. + - Close the temporary table, remove its .FRM + - remove the table from the list of temporary tables + + This function is used to drop user temporary tables, as well as + internal tables created in CREATE TEMPORARY TABLE ... SELECT + or ALTER TABLE. Even though part of the work done by this function + is redundant when the table is internal, as long as we + link both internal and user temporary tables into the same + thd->temporary_tables list, it's impossible to tell here whether + we're dealing with an internal or a user temporary table. + + @retval TRUE the table was not found in the list of temporary tables + of this thread + @retval FALSE the table was found and dropped successfully. */ bool close_temporary_table(THD *thd, TABLE_LIST *table_list) @@ -1689,6 +1707,11 @@ bool close_temporary_table(THD *thd, TABLE_LIST *table_list) if (!(table= find_temporary_table(thd, table_list))) return 1; + /* + If LOCK TABLES list is not empty and contains this table, + unlock the table and remove the table from this list. + */ + mysql_lock_remove(thd, thd->locked_tables, table, FALSE); close_temporary_table(thd, table, 1, 1); return 0; } @@ -1835,7 +1858,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) !memcmp(list->s->table_cache_key.str, key, key_length)) { if (unlock && thd->locked_tables) - mysql_lock_remove(thd, thd->locked_tables,list); + mysql_lock_remove(thd, thd->locked_tables, list, TRUE); VOID(hash_delete(&open_cache,(uchar*) list)); // Close table } else @@ -1861,8 +1884,13 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) @note This routine assumes that table to be closed is open only by calling thread so we needn't wait until other threads - will close the table. It also assumes that table to be - dropped is already unlocked. + will close the table. Also unless called under implicit or + explicit LOCK TABLES mode it assumes that table to be + dropped is already unlocked. In the former case it will + also remove lock on the table. But one should not rely on + this behaviour as it may change in future. + Currently, however, this function is never called for a + table that was locked with LOCK TABLES. */ void drop_open_table(THD *thd, TABLE *table, const char *db_name, @@ -2468,8 +2496,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, &state)) { /* - Here we flush tables marked for flush. However we never flush log - tables here. They are flushed only on FLUSH LOGS. + Here we flush tables marked for flush. Normally, table->s->version contains the value of refresh_version from the moment when this table was (re-)opened and added to the cache. @@ -2486,7 +2513,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, c1: name lock t2; -- blocks c2: open t1; -- blocks */ - if (table->needs_reopen_or_name_lock() && !table->s->log_table) + if (table->needs_reopen_or_name_lock()) { DBUG_PRINT("note", ("Found table '%s.%s' with different refresh version", @@ -2840,7 +2867,7 @@ void close_data_files_and_morph_locks(THD *thd, const char *db, !strcmp(table->s->db.str, db)) { if (thd->locked_tables) - mysql_lock_remove(thd, thd->locked_tables, table); + mysql_lock_remove(thd, thd->locked_tables, table, TRUE); table->open_placeholder= 1; close_handle_and_leave_table_as_lock(table); } @@ -2962,10 +2989,9 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, for (; table ; table=table->next) { /* - Reopen marked for flush. But close log tables. They are flushed only - explicitly on FLUSH LOGS + Reopen marked for flush. */ - if (table->needs_reopen_or_name_lock() && !table->s->log_table) + if (table->needs_reopen_or_name_lock()) { found=1; if (table->db_stat) @@ -2979,7 +3005,7 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, instances of this table. */ mysql_lock_abort(thd, table, TRUE); - mysql_lock_remove(thd, thd->locked_tables, table); + mysql_lock_remove(thd, thd->locked_tables, table, TRUE); /* We want to protect the table from concurrent DDL operations (like RENAME TABLE) until we will re-open and re-lock it. @@ -3012,10 +3038,6 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, Wait until all threads has closed the tables in the list We have also to wait if there is thread that has a lock on this table even if the table is closed - NOTE: log tables are handled differently by the logging routines. - E.g. general_log is always opened and locked by the logger - and the table handler used by the logger, will be skipped by - this check. */ bool table_is_used(TABLE *table, bool wait_for_name_lock) @@ -3034,10 +3056,10 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) search= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state)) { - DBUG_PRINT("info", ("share: 0x%lx locked_by_logger: %d " + DBUG_PRINT("info", ("share: 0x%lx " "open_placeholder: %d locked_by_name: %d " "db_stat: %u version: %lu", - (ulong) search->s, search->locked_by_logger, + (ulong) search->s, search->open_placeholder, search->locked_by_name, search->db_stat, search->s->version)); @@ -3049,12 +3071,9 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) - If we are in flush table and we didn't execute the flush - If the table engine is open and it's an old version (We must wait until all engines are shut down to use the table) - However we fo not wait if we encountered a table, locked by the logger. - Log tables are managed separately by logging routines. */ - if (!search->locked_by_logger && - (search->locked_by_name && wait_for_name_lock || - (search->is_name_opened() && search->needs_reopen_or_name_lock()))) + if ( (search->locked_by_name && wait_for_name_lock) || + (search->is_name_opened() && search->needs_reopen_or_name_lock())) DBUG_RETURN(1); } } while ((table=table->next)); @@ -3131,7 +3150,7 @@ TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name) if (!strcmp(table->s->table_name.str, table_name) && !strcmp(table->s->db.str, db)) { - mysql_lock_remove(thd, thd->locked_tables,table); + mysql_lock_remove(thd, thd->locked_tables, table, TRUE); if (!found) { found= table; @@ -3766,6 +3785,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, thd Thread handler table_list Table to open is first table in this list lock_type Lock to use for open + lock_flags Flags passed to mysql_lock_table NOTE This function don't do anything like SP/SF/views/triggers analysis done @@ -3781,7 +3801,8 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, table_list->table table */ -TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) +TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, + uint lock_flags) { TABLE *table; bool refresh; @@ -3809,8 +3830,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK) - if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, 0, - &refresh))) + if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, + lock_flags, &refresh))) table= 0; } } @@ -4149,11 +4170,6 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) DBUG_ASSERT(thd->lock == 0); // You must lock everything at once TABLE **start,**ptr; uint lock_flag= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN; - - /* Ignore GLOBAL READ LOCK and GLOBAL READ_ONLY if called from a logger */ - if (logger.is_privileged_thread(thd)) - lock_flag|= (MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK | - MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY); if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count))) DBUG_RETURN(-1); @@ -7182,7 +7198,6 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, else if (in_use != thd) { DBUG_PRINT("info", ("Table was in use by other thread")); - in_use->some_tables_deleted=1; if (table->is_name_opened()) { DBUG_PRINT("info", ("Found another active instance of the table")); @@ -7618,7 +7633,7 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, if (!table) goto error; - DBUG_ASSERT(table->s->system_table); + DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM); table->use_all_columns(); table->reginfo.lock_type= tables->lock_type; @@ -7685,12 +7700,92 @@ open_system_table_for_update(THD *thd, TABLE_LIST *one_table) { DBUG_ENTER("open_system_table_for_update"); - TABLE *table= open_ltable(thd, one_table, one_table->lock_type); + TABLE *table= open_ltable(thd, one_table, one_table->lock_type, 0); if (table) { - DBUG_ASSERT(table->s->system_table); + DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM); table->use_all_columns(); } DBUG_RETURN(table); } + +/** + Open a performance schema table. + Opening such tables is performed internally in the server + implementation, and is a 'nested' open, since some tables + might be already opened by the current thread. + The thread context before this call is saved, and is restored + when calling close_performance_schema_table(). + @param thd The current thread + @param one_table Performance schema table to open + @param backup [out] Temporary storage used to save the thread context +*/ +TABLE * +open_performance_schema_table(THD *thd, TABLE_LIST *one_table, + Open_tables_state *backup) +{ + uint flags= ( MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK + | MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY + | MYSQL_LOCK_PERF_SCHEMA ); + + DBUG_ENTER("open_performance_schema_table"); + + thd->reset_n_backup_open_tables_state(backup); + + TABLE *table= open_ltable(thd, one_table, one_table->lock_type, flags); + if (table) + { + DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_PERFORMANCE); + /* Make sure all columns get assigned to a default value */ + table->use_all_columns(); + table->no_replicate= 1; + } + + DBUG_RETURN(table); +} + +/** + Close a performance schema table. + The last table opened by open_performance_schema_table() + is closed, then the thread context is restored. + @param thd The current thread + @param backup [in] the context to restore. +*/ +void close_performance_schema_table(THD *thd, Open_tables_state *backup) +{ + bool found_old_table; + + if (thd->lock) + { + /* + Note: + We do not create explicitly a separate transaction for the + performance table I/O, but borrow the current transaction. + lock + unlock will autocommit the change done in the + performance schema table: this is the expected result. + The current transaction should not be affected by this code. + TODO: Note that if a transactional engine is used for log tables, + this code will need to be revised, as a separate transaction + might be needed. + */ + mysql_unlock_tables(thd, thd->lock); + thd->lock= 0; + } + + safe_mutex_assert_not_owner(&LOCK_open); + + pthread_mutex_lock(&LOCK_open); + + found_old_table= false; + while (thd->open_tables) + found_old_table|= close_thread_table(thd, &thd->open_tables); + + if (found_old_table) + broadcast_refresh(); + + pthread_mutex_unlock(&LOCK_open); + + thd->restore_backup_open_tables_state(backup); +} + diff --git a/sql/sql_class.h b/sql/sql_class.h index 71c13e001ee..ff4f3022c2b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -765,13 +765,25 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1, class Open_tables_state { public: - /* - open_tables - list of regular tables in use by this thread - temporary_tables - list of temp tables in use by this thread - handler_tables - list of tables that were opened with HANDLER OPEN - and are still in use by this thread + /** + List of regular tables in use by this thread. Contains temporary and + base tables that were opened with @see open_tables(). */ - TABLE *open_tables, *temporary_tables, *handler_tables, *derived_tables; + TABLE *open_tables; + /** + List of temporary tables used by this thread. Contains user-level + temporary tables, created with CREATE TEMPORARY TABLE, and + internal temporary tables, created, e.g., to resolve a SELECT, + or for an intermediate table used in ALTER. + XXX Why are internal temporary tables added to this list? + */ + TABLE *temporary_tables; + /** + List of tables that were opened with HANDLER OPEN and are + still in use by this thread. + */ + TABLE *handler_tables; + TABLE *derived_tables; /* During a MySQL session, one can lock tables in two modes: automatic or manual. In automatic mode all necessary tables are locked just before @@ -2438,6 +2450,7 @@ public: #define CF_HAS_ROW_COUNT 2 #define CF_STATUS_COMMAND 4 #define CF_SHOW_TABLE_COMMAND 8 +#define CF_WRITE_LOGS_COMMAND 16 /* Functions in sql_class.cc */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 7c868092921..7d8fc119cf9 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -906,9 +906,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) char path[FN_REFLEN]; TABLE *table; bool error; - uint closed_log_tables= 0, lock_logger= 0; uint path_length; - uint log_type; DBUG_ENTER("mysql_truncate"); bzero((char*) &create_info,sizeof(create_info)); @@ -960,18 +958,6 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) DBUG_RETURN(TRUE); } - log_type= check_if_log_table(table_list->db_length, table_list->db, - table_list->table_name_length, - table_list->table_name, 1); - /* close log tables in use */ - if (log_type) - { - lock_logger= 1; - logger.lock(); - logger.close_log_table(log_type, FALSE); - closed_log_tables= closed_log_tables | log_type; - } - // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this // crashes, replacement works. *(path + path_length - reg_ext_length)= // '\0'; @@ -997,14 +983,6 @@ end: VOID(pthread_mutex_lock(&LOCK_open)); unlock_table_name(thd, table_list); VOID(pthread_mutex_unlock(&LOCK_open)); - - if (opt_slow_log && (closed_log_tables & QUERY_LOG_SLOW)) - logger.reopen_log_table(QUERY_LOG_SLOW); - - if (opt_log && (closed_log_tables & QUERY_LOG_GENERAL)) - logger.reopen_log_table(QUERY_LOG_GENERAL); - if (lock_logger) - logger.unlock(); } else if (error) { diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 5ebeba6109a..8bdb2e59ed5 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -137,6 +137,9 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, level= MYSQL_ERROR::WARN_LEVEL_ERROR; } + if (thd->handle_error(code, level)) + DBUG_RETURN(NULL); + if (thd->spcont && thd->spcont->handle_error(code, level, thd)) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b747c706f75..dc5db54e128 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2254,7 +2254,7 @@ pthread_handler_t handle_delayed_insert(void *arg) } /* open table */ - if (!(di->table=open_ltable(thd,&di->table_list,TL_WRITE_DELAYED))) + if (!(di->table=open_ltable(thd, &di->table_list, TL_WRITE_DELAYED, 0))) { thd->fatal_error(); // Abort waiting inserts goto err; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8ab4dee12ac..055dc1e8424 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2367,12 +2367,129 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl) /** - Update the parsed tree with information about triggers that - may be fired when executing this statement. + @brief Set the initial purpose of this TABLE_LIST object in the list of used + tables. + + We need to track this information on table-by-table basis, since when this + table becomes an element of the pre-locked list, it's impossible to identify + which SQL sub-statement it has been originally used in. + + E.g.: + + User request: SELECT * FROM t1 WHERE f1(); + FUNCTION f1(): DELETE FROM t2; RETURN 1; + BEFORE DELETE trigger on t2: INSERT INTO t3 VALUES (old.a); + + For this user request, the pre-locked list will contain t1, t2, t3 + table elements, each needed for different DML. + + The trigger event map is updated to reflect INSERT, UPDATE, DELETE, + REPLACE, LOAD DATA, CREATE TABLE .. SELECT, CREATE TABLE .. + REPLACE SELECT statements, and additionally ON DUPLICATE KEY UPDATE + clause. */ void st_lex::set_trg_event_type_for_tables() { + uint8 new_trg_event_map= 0; + + /* + Some auxiliary operations + (e.g. GRANT processing) create TABLE_LIST instances outside + the parser. Additionally, some commands (e.g. OPTIMIZE) change + the lock type for a table only after parsing is done. Luckily, + these do not fire triggers and do not need to pre-load them. + For these TABLE_LISTs set_trg_event_type is never called, and + trg_event_map is always empty. That means that the pre-locking + algorithm will ignore triggers defined on these tables, if + any, and the execution will either fail with an assert in + sql_trigger.cc or with an error that a used table was not + pre-locked, in case of a production build. + + TODO: this usage pattern creates unnecessary module dependencies + and should be rewritten to go through the parser. + Table list instances created outside the parser in most cases + refer to mysql.* system tables. It is not allowed to have + a trigger on a system table, but keeping track of + initialization provides extra safety in case this limitation + is circumvented. + */ + + switch (sql_command) { + case SQLCOM_LOCK_TABLES: + /* + On a LOCK TABLE, all triggers must be pre-loaded for this TABLE_LIST + when opening an associated TABLE. + */ + new_trg_event_map= static_cast + (1 << static_cast(TRG_EVENT_INSERT)) | + static_cast + (1 << static_cast(TRG_EVENT_UPDATE)) | + static_cast + (1 << static_cast(TRG_EVENT_DELETE)); + break; + /* + Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE + clause, it will be handled later in this method. + */ + case SQLCOM_INSERT: /* fall through */ + case SQLCOM_INSERT_SELECT: + /* + LOAD DATA ... INFILE is expected to fire BEFORE/AFTER INSERT + triggers. + If the statement also has REPLACE clause, it will be + handled later in this method. + */ + case SQLCOM_LOAD: /* fall through */ + /* + REPLACE is semantically equivalent to INSERT. In case + of a primary or unique key conflict, it deletes the old + record and inserts a new one. So we also may need to + fire ON DELETE triggers. This functionality is handled + later in this method. + */ + case SQLCOM_REPLACE: /* fall through */ + case SQLCOM_REPLACE_SELECT: + /* + CREATE TABLE ... SELECT defaults to INSERT if the table or + view already exists. REPLACE option of CREATE TABLE ... + REPLACE SELECT is handled later in this method. + */ + case SQLCOM_CREATE_TABLE: + new_trg_event_map|= static_cast + (1 << static_cast(TRG_EVENT_INSERT)); + break; + /* Basic update and multi-update */ + case SQLCOM_UPDATE: /* fall through */ + case SQLCOM_UPDATE_MULTI: + new_trg_event_map|= static_cast + (1 << static_cast(TRG_EVENT_UPDATE)); + break; + /* Basic delete and multi-delete */ + case SQLCOM_DELETE: /* fall through */ + case SQLCOM_DELETE_MULTI: + new_trg_event_map|= static_cast + (1 << static_cast(TRG_EVENT_DELETE)); + break; + default: + break; + } + + switch (duplicates) { + case DUP_UPDATE: + new_trg_event_map|= static_cast + (1 << static_cast(TRG_EVENT_UPDATE)); + break; + case DUP_REPLACE: + new_trg_event_map|= static_cast + (1 << static_cast(TRG_EVENT_DELETE)); + break; + case DUP_ERROR: + default: + break; + } + + /* Do not iterate over sub-selects, only the tables in the outermost SELECT_LEX can be modified, if any. @@ -2381,7 +2498,17 @@ void st_lex::set_trg_event_type_for_tables() while (tables) { - tables->set_trg_event_type(this); + /* + This is a fast check to filter out statements that do + not change data, or tables on the right side, in case of + INSERT .. SELECT, CREATE TABLE .. SELECT and so on. + Here we also filter out OPTIMIZE statement and non-updateable + views, for which lock_type is TL_UNLOCK or TL_READ after + parsing. + */ + if (static_cast(tables->lock_type) >= + static_cast(TL_WRITE_ALLOW_WRITE)) + tables->trg_event_map= new_trg_event_map; tables= tables->next_local; } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 93887db88e1..c98d22d9091 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -197,8 +197,8 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA; - sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA; - sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA; + sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND; + sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND; sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA; @@ -211,7 +211,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA; - sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA; + sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; @@ -250,6 +250,14 @@ void init_update_queries(void) */ sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT; sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT; + + /* + The following admin table operations are allowed + on log tables. + */ + sql_command_flags[SQLCOM_REPAIR]= CF_WRITE_LOGS_COMMAND; + sql_command_flags[SQLCOM_OPTIMIZE]= CF_WRITE_LOGS_COMMAND; + sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND; } @@ -259,6 +267,17 @@ bool is_update_query(enum enum_sql_command command) return (sql_command_flags[command] & CF_CHANGES_DATA) != 0; } +/** + Check if a sql command is allowed to write to log tables. + @param command The SQL command + @return true if writing is allowed +*/ +bool is_log_table_write_query(enum enum_sql_command command) +{ + DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); + return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0; +} + void execute_init_command(THD *thd, sys_var_str *init_command_var, rw_lock_t *var_mutex) { @@ -493,7 +512,7 @@ int mysql_table_dump(THD *thd, LEX_STRING *db, char *tbl_name) if (lower_case_table_names) my_casedn_str(files_charset_info, tbl_name); - if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) + if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT, 0))) DBUG_RETURN(1); if (check_one_table_access(thd, SELECT_ACL, table_list)) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index a44e20b8daf..0d088063462 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1617,7 +1617,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl DBUG_RETURN(TRUE); /* need to open before acquiring LOCK_plugin or it will deadlock */ - if (! (table = open_ltable(thd, &tables, TL_WRITE))) + if (! (table = open_ltable(thd, &tables, TL_WRITE, 0))) DBUG_RETURN(TRUE); pthread_mutex_lock(&LOCK_plugin); @@ -1674,7 +1674,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) tables.table_name= tables.alias= (char *)"plugin"; /* need to open before acquiring LOCK_plugin or it will deadlock */ - if (! (table= open_ltable(thd, &tables, TL_WRITE))) + if (! (table= open_ltable(thd, &tables, TL_WRITE, 0))) DBUG_RETURN(TRUE); pthread_mutex_lock(&LOCK_plugin); diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index f5e1b8988f3..750bcd50479 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -37,7 +37,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) TABLE_LIST *ren_table= 0; int to_table; char *rename_log_table[2]= {NULL, NULL}; - int disable_logs= 0; DBUG_ENTER("mysql_rename_tables"); /* @@ -79,12 +78,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) ren_table->table_name_length, ren_table->table_name, 1))) { - /* - Log table encoutered we will need to disable and lock logs - for duration of rename. - */ - disable_logs= TRUE; - /* as we use log_table_rename as an array index, we need it to start with 0, while QUERY_LOG_SLOW == 1 and QUERY_LOG_GENERAL == 2. @@ -136,12 +129,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) rename_log_table[1]); DBUG_RETURN(1); } - - if (disable_logs) - { - logger.lock(); - logger.tmp_close_log_tables(thd); - } } pthread_mutex_lock(&LOCK_open); @@ -200,13 +187,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) pthread_mutex_unlock(&LOCK_open); err: - /* enable logging back if needed */ - if (disable_logs) - { - if (logger.reopen_log_tables()) - error= TRUE; - logger.unlock(); - } start_waiting_global_read_lock(thd); DBUG_RETURN(error); } diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index ac5ea6f4ac4..911372d5f4e 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -366,7 +366,7 @@ insert_server(THD *thd, FOREIGN_SERVER *server) tables.alias= tables.table_name= (char*) "servers"; /* need to open before acquiring THR_LOCK_plugin or it will deadlock */ - if (! (table= open_ltable(thd, &tables, TL_WRITE))) + if (! (table= open_ltable(thd, &tables, TL_WRITE, 0))) goto end; /* insert the server into the table */ @@ -588,7 +588,7 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) if ((error= delete_server_record_in_cache(server_options))) goto end; - if (! (table= open_ltable(thd, &tables, TL_WRITE))) + if (! (table= open_ltable(thd, &tables, TL_WRITE, 0))) { error= my_errno; goto end; @@ -705,7 +705,7 @@ int update_server(THD *thd, FOREIGN_SERVER *existing, FOREIGN_SERVER *altered) tables.db= (char*)"mysql"; tables.alias= tables.table_name= (char*)"servers"; - if (!(table= open_ltable(thd, &tables, TL_WRITE))) + if (!(table= open_ltable(thd, &tables, TL_WRITE, 0))) { error= my_errno; goto end; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5b8cb93baab..fdd75fbe844 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2176,9 +2176,6 @@ void calc_sum_of_all_status(STATUS_VAR *to) } -/* INFORMATION_SCHEMA name */ -LEX_STRING INFORMATION_SCHEMA_NAME= { C_STRING_WITH_LEN("information_schema")}; - /* This is only used internally, but we need it here as a forward reference */ extern ST_SCHEMA_TABLE schema_tables[]; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 54b115af19f..7ffb83bc266 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1513,7 +1513,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table->db_type= share->db_type(); /* Disable drop of enabled log tables */ - if (share && share->log_table && + if (share && (share->table_category == TABLE_CATEGORY_PERFORMANCE) && check_if_log_table(table->db_length, table->db, table->table_name_length, table->table_name, 1)) { @@ -3966,7 +3966,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, Item *item; Protocol *protocol= thd->protocol; LEX *lex= thd->lex; - int result_code, disable_logs= 0; + int result_code; DBUG_ENTER("mysql_admin_table"); if (end_active_trans(thd)) @@ -4014,22 +4014,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (view_operator_func == NULL) table->required_type=FRMTYPE_TABLE; - /* - If we want to perform an admin operation on the log table - (E.g. rename) and lock_type >= TL_READ_NO_INSERT disable - log tables - */ - - if (check_if_log_table(table->db_length, table->db, - table->table_name_length, - table->table_name, 1) && - lock_type >= TL_READ_NO_INSERT) - { - disable_logs= 1; - logger.lock(); - logger.tmp_close_log_tables(thd); - } - open_and_lock_tables(thd, table); thd->no_warnings_for_error= 0; table->next_global= save_next_global; @@ -4099,8 +4083,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, } /* Close all instances of the table to allow repair to rename files */ - if (lock_type == TL_WRITE && table->table->s->version && - !table->table->s->log_table) + if (lock_type == TL_WRITE && table->table->s->version) { pthread_mutex_lock(&LOCK_open); const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open, @@ -4258,7 +4241,7 @@ send_result_message: close_thread_tables(thd); if (!result_code) // recreation went ok { - if ((table->table= open_ltable(thd, table, lock_type)) && + if ((table->table= open_ltable(thd, table, lock_type, 0)) && ((result_code= table->table->file->analyze(thd, check_opt)) > 0)) result_code= 0; // analyze went ok } @@ -4324,10 +4307,9 @@ send_result_message: } if (table->table) { - /* in the below check we do not refresh the log tables */ if (fatal_error) table->table->s->version=0; // Force close of table - else if (open_for_modify && !table->table->s->log_table) + else if (open_for_modify) { if (table->table->s->tmp_table) table->table->file->info(HA_STATUS_CONST); @@ -4350,24 +4332,11 @@ send_result_message: } send_eof(thd); - if (disable_logs) - { - if (logger.reopen_log_tables()) - my_error(ER_CANT_ACTIVATE_LOG, MYF(0)); - logger.unlock(); - } DBUG_RETURN(FALSE); err: ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); // Shouldn't be needed - /* enable logging back if needed */ - if (disable_logs) - { - if (logger.reopen_log_tables()) - my_error(ER_CANT_ACTIVATE_LOG, MYF(0)); - logger.unlock(); - } if (table) table->table=0; DBUG_RETURN(TRUE); @@ -4812,7 +4781,7 @@ mysql_discard_or_import_tablespace(THD *thd, not complain when we lock the table */ thd->tablespace_op= TRUE; - if (!(table=open_ltable(thd,table_list,TL_WRITE))) + if (!(table=open_ltable(thd, table_list, TL_WRITE, 0))) { thd->tablespace_op=FALSE; DBUG_RETURN(-1); @@ -5728,7 +5697,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, #ifdef WITH_PARTITION_STORAGE_ENGINE if (alter_info->flags & ALTER_PARTITION) { - my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table"); + my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table"); DBUG_RETURN(TRUE); } #endif @@ -5817,7 +5786,7 @@ view_err: start_waiting_global_read_lock(thd); DBUG_RETURN(error); } - if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) + if (!(table=open_ltable(thd, table_list, TL_WRITE_ALLOW_READ, 0))) DBUG_RETURN(TRUE); table->use_all_columns(); @@ -6984,7 +6953,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, strxmov(table_name, table->db ,".", table->table_name, NullS); - t= table->table= open_ltable(thd, table, TL_READ); + t= table->table= open_ltable(thd, table, TL_READ, 0); thd->clear_error(); // these errors shouldn't get client protocol->prepare_for_resend(); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 8361fc64f33..10bb7844d88 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -472,7 +472,7 @@ int mysql_create_function(THD *thd,udf_func *udf) tables.db= (char*) "mysql"; tables.table_name= tables.alias= (char*) "func"; /* Allow creation of functions even if we can't open func table */ - if (!(table = open_ltable(thd,&tables,TL_WRITE))) + if (!(table = open_ltable(thd, &tables, TL_WRITE, 0))) goto err; table->use_all_columns(); restore_record(table, s->default_values); // Default values for fields @@ -547,7 +547,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) bzero((char*) &tables,sizeof(tables)); tables.db=(char*) "mysql"; tables.table_name= tables.alias= (char*) "func"; - if (!(table = open_ltable(thd,&tables,TL_WRITE))) + if (!(table = open_ltable(thd, &tables, TL_WRITE, 0))) goto err; table->use_all_columns(); table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d9a808bf8f7..81bb1c2dae9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7277,7 +7277,7 @@ join_table: so that [INNER | CROSS] JOIN is properly nested as other left-associative joins. */ - table_ref %prec TABLE_REF_PRIORITY normal_join table_ref + table_ref normal_join table_ref %prec TABLE_REF_PRIORITY { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; } diff --git a/sql/table.cc b/sql/table.cc index e6f9b1086c7..f52c81d7889 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -21,6 +21,18 @@ #include #include "my_md5.h" +/* INFORMATION_SCHEMA name */ +LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")}; + +/* MYSQL_SCHEMA name */ +LEX_STRING MYSQL_SCHEMA_NAME= {C_STRING_WITH_LEN("mysql")}; + +/* GENERAL_LOG name */ +LEX_STRING GENERAL_LOG_NAME= {C_STRING_WITH_LEN("general_log")}; + +/* SLOW_LOG name */ +LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")}; + /* Functions defined in this file */ void open_table_error(TABLE_SHARE *share, int error, int db_errno, @@ -31,6 +43,7 @@ static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, char **names); static uint find_field(Field **fields, uchar *record, uint start, uint length); +inline bool is_system_table_name(const char *name, uint length); /************************************************************************** Object_creation_ctx implementation. @@ -192,6 +205,49 @@ char *fn_rext(char *name) return name + strlen(name); } +TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name) +{ + DBUG_ASSERT(db != NULL); + DBUG_ASSERT(name != NULL); + + if ((db->length == INFORMATION_SCHEMA_NAME.length) && + (my_strcasecmp(system_charset_info, + INFORMATION_SCHEMA_NAME.str, + db->str) == 0)) + { + return TABLE_CATEGORY_INFORMATION; + } + + if ((db->length == MYSQL_SCHEMA_NAME.length) && + (my_strcasecmp(system_charset_info, + MYSQL_SCHEMA_NAME.str, + db->str) == 0)) + { + if (is_system_table_name(name->str, name->length)) + { + return TABLE_CATEGORY_SYSTEM; + } + + if ((name->length == GENERAL_LOG_NAME.length) && + (my_strcasecmp(system_charset_info, + GENERAL_LOG_NAME.str, + name->str) == 0)) + { + return TABLE_CATEGORY_PERFORMANCE; + } + + if ((name->length == SLOW_LOG_NAME.length) && + (my_strcasecmp(system_charset_info, + SLOW_LOG_NAME.str, + name->str) == 0)) + { + return TABLE_CATEGORY_PERFORMANCE; + } + } + + return TABLE_CATEGORY_USER; +} + /* Allocate a setup TABLE_SHARE structure @@ -297,7 +353,8 @@ void init_tmp_table_share(TABLE_SHARE *share, const char *key, bzero((char*) share, sizeof(*share)); init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); - share->tmp_table= INTERNAL_TMP_TABLE; + share->table_category= TABLE_CATEGORY_TEMPORARY; + share->tmp_table= INTERNAL_TMP_TABLE; share->db.str= (char*) key; share->db.length= strlen(key); share->table_cache_key.str= (char*) key; @@ -544,28 +601,11 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) *root_ptr= &share->mem_root; error= open_binary_frm(thd, share, head, file); *root_ptr= old_root; - - if (share->db.length == 5 && !(lower_case_table_names ? - my_strcasecmp(system_charset_info, share->db.str, "mysql") : - strcmp(share->db.str, "mysql"))) - { - /* - We can't mark all tables in 'mysql' database as system since we don't - allow to lock such tables for writing with any other tables (even with - other system tables) and some privilege tables need this. - */ - share->system_table= is_system_table_name(share->table_name.str, - share->table_name.length); - if (!share->system_table) - { - share->log_table= check_if_log_table(share->db.length, share->db.str, - share->table_name.length, - share->table_name.str, 0); - } - } error_given= 1; } + share->table_category= get_table_category(& share->db, & share->table_name); + if (!error) thd->status_var.opened_shares++; @@ -2854,135 +2894,6 @@ void st_table::reset_item_list(List *item_list) const } } - -/** - Set the initial purpose of this TABLE_LIST object in the list of - used tables. We need to track this information on table-by- - table basis, since when this table becomes an element of the - pre-locked list, it's impossible to identify which SQL - sub-statement it has been originally used in. - - E.g.: - - User request: SELECT * FROM t1 WHERE f1(); - FUNCTION f1(): DELETE FROM t2; RETURN 1; - BEFORE DELETE trigger on t2: INSERT INTO t3 VALUES (old.a); - - For this user request, the pre-locked list will contain t1, t2, t3 - table elements, each needed for different DML. - - This method is called immediately after parsing for tables - of the table list of the top-level select lex. - - The trigger event map is updated to reflect INSERT, UPDATE, DELETE, - REPLACE, LOAD DATA, CREATE TABLE .. SELECT, CREATE TABLE .. - REPLACE SELECT statements, and additionally ON DUPLICATE KEY UPDATE - clause. -*/ - -void -TABLE_LIST::set_trg_event_type(const st_lex *lex) -{ - enum trg_event_type trg_event; - - /* - Some auxiliary operations - (e.g. GRANT processing) create TABLE_LIST instances outside - the parser. Additionally, some commands (e.g. OPTIMIZE) change - the lock type for a table only after parsing is done. Luckily, - these do not fire triggers and do not need to pre-load them. - For these TABLE_LISTs set_trg_event_type is never called, and - trg_event_map is always empty. That means that the pre-locking - algorithm will ignore triggers defined on these tables, if - any, and the execution will either fail with an assert in - sql_trigger.cc or with an error that a used table was not - pre-locked, in case of a production build. - - TODO: this usage pattern creates unnecessary module dependencies - and should be rewritten to go through the parser. - Table list instances created outside the parser in most cases - refer to mysql.* system tables. It is not allowed to have - a trigger on a system table, but keeping track of - initialization provides extra safety in case this limitation - is circumvented. - */ - - /* - This is a fast check to filter out statements that do - not change data, or tables on the right side, in case of - INSERT .. SELECT, CREATE TABLE .. SELECT and so on. - Here we also filter out OPTIMIZE statement and non-updateable - views, for which lock_type is TL_UNLOCK or TL_READ after - parsing. - */ - if (static_cast(lock_type) < static_cast(TL_WRITE_ALLOW_WRITE)) - return; - - switch (lex->sql_command) { - /* - Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE - clause, it will be handled later in this method. - */ - case SQLCOM_INSERT: /* fall through */ - case SQLCOM_INSERT_SELECT: - /* - LOAD DATA ... INFILE is expected to fire BEFORE/AFTER INSERT - triggers. - If the statement also has REPLACE clause, it will be - handled later in this method. - */ - case SQLCOM_LOAD: /* fall through */ - /* - REPLACE is semantically equivalent to INSERT. In case - of a primary or unique key conflict, it deletes the old - record and inserts a new one. So we also may need to - fire ON DELETE triggers. This functionality is handled - later in this method. - */ - case SQLCOM_REPLACE: /* fall through */ - case SQLCOM_REPLACE_SELECT: - /* - CREATE TABLE ... SELECT defaults to INSERT if the table or - view already exists. REPLACE option of CREATE TABLE ... - REPLACE SELECT is handled later in this method. - */ - case SQLCOM_CREATE_TABLE: - trg_event= TRG_EVENT_INSERT; - break; - /* Basic update and multi-update */ - case SQLCOM_UPDATE: /* fall through */ - case SQLCOM_UPDATE_MULTI: - trg_event= TRG_EVENT_UPDATE; - break; - /* Basic delete and multi-delete */ - case SQLCOM_DELETE: /* fall through */ - case SQLCOM_DELETE_MULTI: - trg_event= TRG_EVENT_DELETE; - break; - default: - /* - OK to return, since value of 'duplicates' is irrelevant - for non-updating commands. - */ - return; - } - trg_event_map|= static_cast(1 << static_cast(trg_event)); - - switch (lex->duplicates) { - case DUP_UPDATE: - trg_event= TRG_EVENT_UPDATE; - break; - case DUP_REPLACE: - trg_event= TRG_EVENT_DELETE; - break; - case DUP_ERROR: - default: - return; - } - trg_event_map|= static_cast(1 << static_cast(trg_event)); -} - - /* calculate md5 of query diff --git a/sql/table.h b/sql/table.h index a276a9f32fd..e46036f3ee9 100644 --- a/sql/table.h +++ b/sql/table.h @@ -140,6 +140,100 @@ class Field_timestamp; class Field_blob; class Table_triggers_list; +/** + Category of table found in the table share. +*/ +enum enum_table_category +{ + /** + Unknown value. + */ + TABLE_UNKNOWN_CATEGORY=0, + + /** + Temporary table. + The table is visible only in the session. + Therefore, + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + do not apply to this table. + Note that LOCK TABLE FOR READ/WRITE + can be used on temporary tables. + Temporary tables are not part of the table cache. + */ + TABLE_CATEGORY_TEMPORARY=1, + + /** + User table. + These tables do honor: + - LOCK TABLE FOR READ/WRITE + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + User tables are cached in the table cache. + */ + TABLE_CATEGORY_USER=2, + + /** + System table, maintained by the server. + These tables do honor: + - LOCK TABLE FOR READ/WRITE + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + Typically, writes to system tables are performed by + the server implementation, not explicitly be a user. + System tables are cached in the table cache. + */ + TABLE_CATEGORY_SYSTEM=3, + + /** + Information schema tables. + These tables are an interface provided by the system + to inspect the system metadata. + These tables do *not* honor: + - LOCK TABLE FOR READ/WRITE + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + as there is no point in locking explicitely + an INFORMATION_SCHEMA table. + Nothing is directly written to information schema tables. + Note that this value is not used currently, + since information schema tables are not shared, + but implemented as session specific temporary tables. + */ + /* + TODO: Fixing the performance issues of I_S will lead + to I_S tables in the table cache, which should use + this table type. + */ + TABLE_CATEGORY_INFORMATION=4, + + /** + Performance schema tables. + These tables are an interface provided by the system + to inspect the system performance data. + These tables do *not* honor: + - LOCK TABLE FOR READ/WRITE + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + as there is no point in locking explicitely + a PERFORMANCE_SCHEMA table. + An example of PERFORMANCE_SCHEMA tables are: + - mysql.slow_log + - mysql.general_log, + which *are* updated even when there is either + a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect. + User queries do not write directly to these tables + (there are exceptions for log tables). + The server implementation perform writes. + Performance tables are cached in the table cache. + */ + TABLE_CATEGORY_PERFORMANCE=5 +}; +typedef enum enum_table_category TABLE_CATEGORY; + +TABLE_CATEGORY get_table_category(const LEX_STRING *db, + const LEX_STRING *name); + /* This structure is shared between different table objects. There is one instance of table share per one table in the database. @@ -148,6 +242,10 @@ class Table_triggers_list; typedef struct st_table_share { st_table_share() {} /* Remove gcc warning */ + + /** Category of this table. */ + TABLE_CATEGORY table_category; + /* hash of field names (contains pointers to elements of field array) */ HASH name_hash; /* hash of field names */ MEM_ROOT mem_root; @@ -259,18 +357,6 @@ typedef struct st_table_share */ int cached_row_logging_check; - /* - TRUE if this is a system table like 'mysql.proc', which we want to be - able to open and lock even when we already have some tables open and - locked. To avoid deadlocks we have to put certain restrictions on - locking of this table for writing. FALSE - otherwise. - */ - bool system_table; - /* - This flag is set for the log tables. Used during FLUSH instances to skip - log tables, while closing tables (since logs must be always available) - */ - bool log_table; #ifdef WITH_PARTITION_STORAGE_ENGINE bool auto_partitioned; const char *partition_info; @@ -334,6 +420,16 @@ typedef struct st_table_share set_table_cache_key(key_buff, key_length); } + inline bool honor_global_locks() + { + return ((table_category == TABLE_CATEGORY_USER) + || (table_category == TABLE_CATEGORY_SYSTEM)); + } + + inline bool require_write_privileges() + { + return (table_category == TABLE_CATEGORY_PERFORMANCE); + } } TABLE_SHARE; @@ -1052,7 +1148,6 @@ struct TABLE_LIST */ bool process_index_hints(TABLE *table); - void set_trg_event_type(const st_lex *lex); private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); diff --git a/sql/tztime.cc b/sql/tztime.cc index 0c717dd2ece..14192d06978 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -807,19 +807,6 @@ sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec) SECS_PER_MIN + sec; } - - /* - Works like sec_since_epoch but expects MYSQL_TIME structure as parameter. -*/ - -my_time_t -sec_since_epoch_TIME(MYSQL_TIME *t) -{ - return sec_since_epoch(t->year, t->month, t->day, - t->hour, t->minute, t->second); -} - - /* Converts local time in broken down MYSQL_TIME representation to my_time_t representation. @@ -1425,7 +1412,9 @@ Time_zone_offset::get_name() const static Time_zone_utc tz_UTC; static Time_zone_system tz_SYSTEM; +static Time_zone_offset tz_OFFSET0(0); +Time_zone *my_tz_OFFSET0= &tz_OFFSET0; Time_zone *my_tz_UTC= &tz_UTC; Time_zone *my_tz_SYSTEM= &tz_SYSTEM; diff --git a/sql/tztime.h b/sql/tztime.h index f7cc7042d79..ddd80b88bf2 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -59,6 +59,7 @@ public: extern Time_zone * my_tz_UTC; extern Time_zone * my_tz_SYSTEM; +extern Time_zone * my_tz_OFFSET0; extern Time_zone * my_tz_find(THD *thd, const String *name); extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap); extern void my_tz_free(); diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 34c1fcde58d..00ca2a6c07f 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -786,18 +786,6 @@ void ha_tina::update_status() } -bool ha_tina::check_if_locking_is_allowed(uint sql_command, - ulong type, TABLE *table, - uint count, uint current, - uint *system_count, - bool called_by_privileged_thread) -{ - if (!called_by_privileged_thread) - return check_if_log_table_locking_is_allowed(sql_command, type, table); - - return TRUE; -} - /* Open a database file. Keep in mind that tables are caches, so this will not be called for every request. Any sort of positions diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h index 5bb3e9a79a0..5ce09783b9b 100644 --- a/storage/csv/ha_tina.h +++ b/storage/csv/ha_tina.h @@ -131,11 +131,6 @@ public: */ ha_rows estimate_rows_upper_bound() { return HA_POS_ERROR; } - virtual bool check_if_locking_is_allowed(uint sql_command, - ulong type, TABLE *table, - uint count, uint current, - uint *system_count, - bool called_by_logger_thread); int open(const char *name, int mode, uint open_options); int close(void); int write_row(uchar * buf); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index c86459ae0a7..77334b2cfba 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -607,41 +607,7 @@ err: #endif /* HAVE_REPLICATION */ -bool ha_myisam::check_if_locking_is_allowed(uint sql_command, - ulong type, TABLE *table, - uint count, uint current, - uint *system_count, - bool called_by_privileged_thread) -{ - /* - To be able to open and lock for reading system tables like 'mysql.proc', - when we already have some tables opened and locked, and avoid deadlocks - we have to disallow write-locking of these tables with any other tables. - */ - if (table->s->system_table && - table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE) - (*system_count)++; - - /* 'current' is an index, that's why '<=' below. */ - if (*system_count > 0 && *system_count <= current) - { - my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0)); - return FALSE; - } - - /* - Deny locking of the log tables, which is incompatible with - concurrent insert. Unless called from a logger THD (general_log_thd - or slow_log_thd) or by a privileged thread. - */ - if (!called_by_privileged_thread) - return check_if_log_table_locking_is_allowed(sql_command, type, table); - - return TRUE; -} - - /* Name is here without an extension */ - +/* Name is here without an extension */ int ha_myisam::open(const char *name, int mode, uint test_if_locked) { MI_KEYDEF *keyinfo; diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 024675075c2..635f314b3da 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -60,11 +60,6 @@ class ha_myisam: public handler uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; } uint checksum() const; - virtual bool check_if_locking_is_allowed(uint sql_command, - ulong type, TABLE *table, - uint count, uint current, - uint *system_count, - bool called_by_logger_thread); int open(const char *name, int mode, uint test_if_locked); int close(void); int write_row(uchar * buf); diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c index 1165ea4bb32..08627ba7e92 100644 --- a/storage/myisam/mi_test1.c +++ b/storage/myisam/mi_test1.c @@ -258,7 +258,8 @@ static int run_test(const char *filename) continue; create_key(key,j); my_errno=0; - if ((error = mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))) + if ((error = mi_rkey(file,read_record,0,key,HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { if (verbose || (flags[j] >= 1 || (error && my_errno != HA_ERR_KEY_NOT_FOUND))) @@ -285,7 +286,7 @@ static int run_test(const char *filename) { create_key(key,i); my_errno=0; - error=mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT); + error=mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT); if (verbose || (error == 0 && flags[i] == 0 && unique_key) || (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND))) diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c index 96ee82e023c..99d0c23d2a4 100644 --- a/storage/myisam/mi_test2.c +++ b/storage/myisam/mi_test2.c @@ -263,7 +263,7 @@ int main(int argc, char *argv[]) if (!j) for (j=999 ; j>0 && key1[j] == 0 ; j--) ; sprintf(key,"%6d",j); - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) + if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) { printf("Test in loop: Can't find key: \"%s\"\n",key); goto err; @@ -291,7 +291,7 @@ int main(int argc, char *argv[]) if (j != 0) { sprintf(key,"%6d",j); - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) + if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) { printf("can't find key1: \"%s\"\n",key); goto err; @@ -325,7 +325,7 @@ int main(int argc, char *argv[]) if (j != 0) { sprintf(key,"%6d",j); - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) + if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) { printf("can't find key1: \"%s\"\n",key); goto err; @@ -377,7 +377,7 @@ int main(int argc, char *argv[]) DBUG_PRINT("progpos",("first - next -> last - prev -> first")); if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys); - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) + if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) goto err; if (mi_rsame(file,read_record2,-1)) goto err; @@ -422,7 +422,7 @@ int main(int argc, char *argv[]) } /* Check of mi_rnext_same */ - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) + if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) goto err; ant=1; while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10) @@ -496,7 +496,7 @@ int main(int argc, char *argv[]) goto err; if (bcmp(read_record2,read_record3,reclength)) printf("Can't find last record\n"); - +#ifdef NOT_ANYMORE if (!silent) puts("- Test read key-part"); strmov(key2,key); @@ -514,12 +514,14 @@ int main(int argc, char *argv[]) goto end; } } +#endif if (dupp_keys > 2) { if (!silent) printf("- Read key (first) - next - delete - next -> last\n"); DBUG_PRINT("progpos",("first - next - delete - next -> last")); - if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err; + if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) + goto err; if (mi_rnext(file,read_record3,0)) goto err; if (mi_delete(file,read_record3)) goto err; opt_delete++; @@ -555,7 +557,8 @@ int main(int argc, char *argv[]) if (!silent) printf("- Read first - delete - next -> last\n"); DBUG_PRINT("progpos",("first - delete - next -> last")); - if (mi_rkey(file,read_record3,0,key,0,HA_READ_KEY_EXACT)) goto err; + if (mi_rkey(file,read_record3,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) + goto err; if (mi_delete(file,read_record3)) goto err; opt_delete++; ant=1; @@ -618,10 +621,10 @@ int main(int argc, char *argv[]) copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key); copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2); min_key.key= key; - min_key.length= USE_WHOLE_KEY; + min_key.keypart_map= HA_WHOLE_KEY; min_key.flag= HA_READ_KEY_EXACT; max_key.key= key2; - max_key.length= USE_WHOLE_KEY; + max_key.keypart_map= HA_WHOLE_KEY; max_key.flag= HA_READ_AFTER_KEY; range_records= mi_records_in_range(file,(int) i, &min_key, &max_key); diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c index 982b999c3a5..ed9cd8e7b8c 100644 --- a/storage/myisam/mi_test3.c +++ b/storage/myisam/mi_test3.c @@ -243,8 +243,8 @@ int test_read(MI_INFO *file,int id) for (i=0 ; i < 100 ; i++) { find=rnd(100000); - if (!mi_rkey(file,record.id,1,(uchar*) &find, - sizeof(find),HA_READ_KEY_EXACT)) + if (!mi_rkey(file,record.id,1,(uchar*) &find, HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) found++; else { @@ -426,8 +426,8 @@ int test_update(MI_INFO *file,int id,int lock_type) { tmp=rnd(100000); int4store(find,tmp); - if (!mi_rkey(file,record.id,1,(uchar*) find, - sizeof(find),HA_READ_KEY_EXACT)) + if (!mi_rkey(file,record.id,1,(uchar*) find, HA_WHOLE_KEY, + HA_READ_KEY_EXACT)) found++; else {