diff options
author | unknown <msvensson@pilot.(none)> | 2007-08-20 13:47:31 +0200 |
---|---|---|
committer | unknown <msvensson@pilot.(none)> | 2007-08-20 13:47:31 +0200 |
commit | 8ef4122511b924f5eabcb9e03feaddb00c113448 (patch) | |
tree | e791b3c227804891ea58b05aea712804aa698b25 | |
parent | a2e4cc6c774e0cecb1857125c67a08b2433277e1 (diff) | |
parent | 5dc6ba8255361053243010ff7ee24bfeb84d255d (diff) | |
download | mariadb-git-8ef4122511b924f5eabcb9e03feaddb00c113448.tar.gz |
Merge pilot.(none):/data/msvensson/mysql/work/my51-work
into pilot.(none):/data/msvensson/mysql/mysql-5.1-new-maint
strings/ctype-extra.c:
Auto merged
-rw-r--r-- | client/mysqldump.c | 554 | ||||
-rw-r--r-- | mysql-test/r/federated.result | 14 | ||||
-rw-r--r-- | mysql-test/r/lock.result | 70 | ||||
-rw-r--r-- | mysql-test/r/lock_multi.result | 10 | ||||
-rw-r--r-- | mysql-test/r/log_state.result | 4 | ||||
-rw-r--r-- | mysql-test/t/federated.test | 14 | ||||
-rw-r--r-- | mysql-test/t/lock.test | 65 | ||||
-rw-r--r-- | mysql-test/t/lock_multi.test | 35 | ||||
-rw-r--r-- | mysql-test/t/log_state.test | 4 | ||||
-rw-r--r-- | mysys/thr_lock.c | 40 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 1 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 53 |
13 files changed, 668 insertions, 198 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index c56c4423470..566760d2db3 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1236,6 +1236,125 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name) return mysql_real_query(mysql, query_buffer, query_length); } +/** + Rewrite CREATE TRIGGER statement, enclosing DEFINER clause in + version-specific comment. + + This function parses the CREATE TRIGGER statement and encloses + DEFINER-clause in version-specific comment: + input query: CREATE DEFINER=a@b TRIGGER ... + rewritten query: CREATE * / / *!50017 DEFINER=a@b * / / *!50003 TRIGGER ... + + @note This function will go away when WL#3995 is implemented. + + @param[in] trigger_def_str CREATE TRIGGER statement string. + @param[in] trigger_def_length length of the trigger_def_str. + + @return pointer to the new allocated query string. +*/ + +static char *cover_definer_clause_in_trigger(const char *trigger_def_str, + uint trigger_def_length) +{ + char *query_str= NULL; + char *definer_begin= my_case_str(trigger_def_str, trigger_def_length, + C_STRING_WITH_LEN(" DEFINER")); + char *definer_end; + + if (!definer_begin) + return NULL; + + definer_end= my_case_str(definer_begin, strlen(definer_begin), + C_STRING_WITH_LEN(" TRIGGER")); + + if (definer_end) + { + char *query_str_tail; + + /* + Allocate memory for new query string: original string + from SHOW statement and version-specific comments. + */ + query_str= alloc_query_str(trigger_def_length + 23); + + query_str_tail= strnmov(query_str, + trigger_def_str, + definer_begin - trigger_def_str); + + query_str_tail= strmov(query_str_tail, + "*/ /*!50017"); + + query_str_tail= strnmov(query_str_tail, + definer_begin, + definer_end - definer_begin); + + query_str_tail= strxmov(query_str_tail, + "*/ /*!50003", + definer_end, + NullS); + } + + return query_str; +} + +/** + Rewrite CREATE FUNCTION or CREATE PROCEDURE statement, enclosing DEFINER + clause in version-specific comment. + + This function parses the CREATE FUNCTION | PROCEDURE statement and + encloses DEFINER-clause in version-specific comment: + input query: CREATE DEFINER=a@b FUNCTION ... + rewritten query: CREATE * / / *!50020 DEFINER=a@b * / / *!50003 FUNCTION ... + + @note This function will go away when WL#3995 is implemented. + + @param[in] def_str CREATE FUNCTION|PROCEDURE statement string. + @param[in] def_length length of the def_str. + + @return pointer to the new allocated query string. +*/ + +static char *cover_definer_clause_in_sp(const char *def_str, + uint def_str_length) +{ + char *query_str= NULL; + char *definer_begin= my_case_str(def_str, def_str_length, + C_STRING_WITH_LEN(" DEFINER")); + char *definer_end; + + if (!definer_begin) + return NULL; + + definer_end= my_case_str(definer_begin, strlen(definer_begin), + C_STRING_WITH_LEN(" PROCEDURE")); + + if (!definer_end) + { + definer_end= my_case_str(definer_begin, strlen(definer_begin), + C_STRING_WITH_LEN(" FUNCTION")); + } + + if (definer_end) + { + char *query_str_tail; + + /* + Allocate memory for new query string: original string + from SHOW statement and version-specific comments. + */ + query_str= alloc_query_str(def_str_length + 23); + + query_str_tail= strnmov(query_str, def_str, definer_begin - def_str); + query_str_tail= strmov(query_str_tail, "*/ /*!50020"); + query_str_tail= strnmov(query_str_tail, definer_begin, + definer_end - definer_begin); + query_str_tail= strxmov(query_str_tail, "*/ /*!50003", + definer_end, NullS); + } + + return query_str; +} + /* Open a new .sql file to dump the table or view into @@ -1710,7 +1829,7 @@ static uint dump_events_for_db(char *db) MYSQL_ROW row, event_list_row; char db_cl_name[MY_CS_NAME_SIZE]; - int db_cl_altered; + int db_cl_altered= FALSE; DBUG_ENTER("dump_events_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); @@ -1775,16 +1894,36 @@ static uint dump_events_for_db(char *db) fprintf(sql_file, "DELIMITER %s\n", delimiter); - if (switch_db_collation(sql_file, db_name_buff, delimiter, db_cl_name, - row[6], &db_cl_altered)) + if (mysql_num_fields(event_res) >= 7) { - DBUG_RETURN(1); - } + if (switch_db_collation(sql_file, db_name_buff, delimiter, + db_cl_name, row[6], &db_cl_altered)) + { + DBUG_RETURN(1); + } - switch_cs_variables(sql_file, delimiter, - row[4], /* character_set_client */ - row[4], /* character_set_results */ - row[5]); /* collation_connection */ + switch_cs_variables(sql_file, delimiter, + row[4], /* character_set_client */ + row[4], /* character_set_results */ + row[5]); /* collation_connection */ + } + else + { + /* + mysqldump is being run against the server, that does not + provide character set information in SHOW CREATE + statements. + + NOTE: the dump may be incorrect, since character set + information is required in order to restore event properly. + */ + + fprintf(sql_file, + "--\n" + "-- WARNING: old server version. " + "The following dump may be incomplete.\n" + "--\n"); + } switch_sql_mode(sql_file, delimiter, row[1]); @@ -1797,13 +1936,17 @@ static uint dump_events_for_db(char *db) restore_time_zone(sql_file, delimiter); restore_sql_mode(sql_file, delimiter); - restore_cs_variables(sql_file, delimiter); - if (db_cl_altered) + if (mysql_num_fields(event_res) >= 7) { - if (restore_db_collation(sql_file, db_name_buff, delimiter, - db_cl_name)) - DBUG_RETURN(1); + restore_cs_variables(sql_file, delimiter); + + if (db_cl_altered) + { + if (restore_db_collation(sql_file, db_name_buff, delimiter, + db_cl_name)) + DBUG_RETURN(1); + } } } } /* end of event printing */ @@ -1871,7 +2014,7 @@ static uint dump_routines_for_db(char *db) MYSQL_ROW row, routine_list_row; char db_cl_name[MY_CS_NAME_SIZE]; - int db_cl_altered; + int db_cl_altered= FALSE; DBUG_ENTER("dump_routines_for_db"); DBUG_PRINT("enter", ("db: '%s'", db)); @@ -1938,74 +2081,45 @@ static uint dump_routines_for_db(char *db) } else if (strlen(row[2])) { - char *query_str= NULL; - char *definer_begin; - + char *query_str; if (opt_drop) fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n", routine_type[i], routine_name); - /* - Cover DEFINER-clause in version-specific comments. - - TODO: this is definitely a BAD IDEA to parse SHOW CREATE output. - However, we can not use INFORMATION_SCHEMA instead: - 1. INFORMATION_SCHEMA provides data in UTF8, but here we - need data in the original character set; - 2. INFORMATION_SCHEMA does not provide information about - routine parameters now. - */ - - definer_begin= my_case_str(row[2], strlen(row[2]), - C_STRING_WITH_LEN(" DEFINER")); + query_str= cover_definer_clause_in_sp(row[2], strlen(row[2])); - if (definer_begin) + if (mysql_num_fields(routine_res) >= 6) { - char *definer_end= my_case_str(definer_begin, - strlen(definer_begin), - C_STRING_WITH_LEN(" PROCEDURE")); - - if (!definer_end) + if (switch_db_collation(sql_file, db_name_buff, ";", + db_cl_name, row[5], &db_cl_altered)) { - definer_end= my_case_str(definer_begin, strlen(definer_begin), - C_STRING_WITH_LEN(" FUNCTION")); + DBUG_RETURN(1); } - if (definer_end) - { - char *query_str_tail; - - /* - Allocate memory for new query string: original string - from SHOW statement and version-specific comments. - */ - query_str= alloc_query_str(strlen(row[2]) + 23); - - query_str_tail= strnmov(query_str, row[2], - definer_begin - row[2]); - query_str_tail= strmov(query_str_tail, "*/ /*!50020"); - query_str_tail= strnmov(query_str_tail, definer_begin, - definer_end - definer_begin); - query_str_tail= strxmov(query_str_tail, "*/ /*!50003", - definer_end, NullS); - } + switch_cs_variables(sql_file, ";", + row[3], /* character_set_client */ + row[3], /* character_set_results */ + row[4]); /* collation_connection */ } - - /* - we need to change sql_mode only for the CREATE - PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name - */ - - if (switch_db_collation(sql_file, db_name_buff, ";", - db_cl_name, row[5], &db_cl_altered)) + else { - DBUG_RETURN(1); + /* + mysqldump is being run against the server, that does not + provide character set information in SHOW CREATE + statements. + + NOTE: the dump may be incorrect, since character set + information is required in order to restore stored + procedure/function properly. + */ + + fprintf(sql_file, + "--\n" + "-- WARNING: old server version. " + "The following dump may be incomplete.\n" + "--\n"); } - switch_cs_variables(sql_file, ";", - row[3], /* character_set_client */ - row[3], /* character_set_results */ - row[4]); /* collation_connection */ switch_sql_mode(sql_file, ";", row[1]); @@ -2016,12 +2130,16 @@ static uint dump_routines_for_db(char *db) (const char *) (query_str != NULL ? query_str : row[2])); restore_sql_mode(sql_file, ";"); - restore_cs_variables(sql_file, ";"); - if (db_cl_altered) + if (mysql_num_fields(routine_res) >= 6) { - if (restore_db_collation(sql_file, db_name_buff, ";", db_cl_name)) - DBUG_RETURN(1); + restore_cs_variables(sql_file, ";"); + + if (db_cl_altered) + { + if (restore_db_collation(sql_file, db_name_buff, ";", db_cl_name)) + DBUG_RETURN(1); + } } my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); @@ -2560,153 +2678,211 @@ continue_xml: DBUG_RETURN((uint) num_fields); } /* get_table_structure */ +static void dump_trigger_old(MYSQL_RES *show_triggers_rs, + MYSQL_ROW *show_trigger_row, + const char *table_name) +{ + FILE *sql_file= md_result_file; -/* + char quoted_table_name_buf[NAME_LEN * 2 + 3]; + char *quoted_table_name= quote_name(table_name, quoted_table_name_buf, 1); + + char name_buff[NAME_LEN * 4 + 3]; + + DBUG_ENTER("dump_trigger_old"); - dump_triggers_for_table + fprintf(sql_file, + "--\n" + "-- WARNING: old server version. " + "The following dump may be incomplete.\n" + "--\n"); + + if (opt_compact) + fprintf(sql_file, "/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n"); - Dumps the triggers given a table/db name. This should be called after - the tables have been dumped in case a trigger depends on the existence - of a table + fprintf(sql_file, + "DELIMITER ;;\n" + "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n" + "/*!50003 CREATE */ ", + (*show_trigger_row)[6]); + + if (mysql_num_fields(show_triggers_rs) > 7) + { + /* + mysqldump can be run against the server, that does not support + definer in triggers (there is no DEFINER column in SHOW TRIGGERS + output). So, we should check if we have this column before + accessing it. + */ + size_t user_name_len; + char user_name_str[USERNAME_LENGTH + 1]; + char quoted_user_name_str[USERNAME_LENGTH * 2 + 3]; + size_t host_name_len; + char host_name_str[HOSTNAME_LENGTH + 1]; + char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3]; + + parse_user((*show_trigger_row)[7], + strlen((*show_trigger_row)[7]), + user_name_str, &user_name_len, + host_name_str, &host_name_len); + + fprintf(sql_file, + "/*!50017 DEFINER=%s@%s */ ", + quote_name(user_name_str, quoted_user_name_str, FALSE), + quote_name(host_name_str, quoted_host_name_str, FALSE)); + } + + fprintf(sql_file, + "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n" + "DELIMITER ;\n", + quote_name((*show_trigger_row)[0], name_buff, 0), /* Trigger */ + (*show_trigger_row)[4], /* Timing */ + (*show_trigger_row)[1], /* Event */ + quoted_table_name, + (strchr(" \t\n\r", *((*show_trigger_row)[3]))) ? "" : " ", + (*show_trigger_row)[3] /* Statement */); + + if (opt_compact) + fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"); + + DBUG_VOID_RETURN; +} + +static int dump_trigger(MYSQL_RES *show_create_trigger_rs, + const char *db_name, + const char *db_cl_name) +{ + FILE *sql_file= md_result_file; + MYSQL_ROW row; + int db_cl_altered= FALSE; + + DBUG_ENTER("dump_trigger"); + + while ((row= mysql_fetch_row(show_create_trigger_rs))) + { + char *query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2])); + + + if (switch_db_collation(sql_file, db_name, ";", + db_cl_name, row[5], &db_cl_altered)) + DBUG_RETURN(TRUE); + + switch_cs_variables(sql_file, ";", + row[3], /* character_set_client */ + row[3], /* character_set_results */ + row[4]); /* collation_connection */ + + switch_sql_mode(sql_file, ";", row[1]); + + fprintf(sql_file, + "DELIMITER ;;\n" + "/*!50003 %s */;;\n" + "DELIMITER ;\n", + (const char *) (query_str != NULL ? query_str : row[2])); + + restore_sql_mode(sql_file, ";"); + restore_cs_variables(sql_file, ";"); + + if (db_cl_altered) + { + if (restore_db_collation(sql_file, db_name, ";", db_cl_name)) + DBUG_RETURN(TRUE); + } + + my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); + } + + DBUG_RETURN(FALSE); +} + +/** + Dump the triggers for a given table. + + This should be called after the tables have been dumped in case a trigger + depends on the existence of a table. + + @param[in] table_name + @param[in] db_name + + @return Error status. + @retval TRUE error has occurred. + @retval FALSE operation succeed. */ -static void dump_triggers_for_table(char *table, char *db_name) +static int dump_triggers_for_table(char *table_name, char *db_name) { - char *result_table; - char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; + char name_buff[NAME_LEN*4+3]; char query_buff[QUERY_LENGTH]; - uint old_opt_compatible_mode=opt_compatible_mode; - FILE *sql_file= md_result_file; - MYSQL_RES *result; + uint old_opt_compatible_mode= opt_compatible_mode; + MYSQL_RES *show_triggers_rs; MYSQL_ROW row; char db_cl_name[MY_CS_NAME_SIZE]; - int db_cl_altered; DBUG_ENTER("dump_triggers_for_table"); - DBUG_PRINT("enter", ("db: %s, table: %s", db_name, table)); + DBUG_PRINT("enter", ("db: %s, table_name: %s", db_name, table_name)); /* Do not use ANSI_QUOTES on triggers in dump */ opt_compatible_mode&= ~MASK_ANSI_QUOTES; - result_table= quote_name(table, table_buff, 1); - - my_snprintf(query_buff, sizeof(query_buff), - "SHOW TRIGGERS LIKE %s", - quote_for_like(table, name_buff)); - - if (mysql_query_with_error_report(mysql, &result, query_buff)) - { - if (path) - my_fclose(sql_file, MYF(MY_WME)); - DBUG_VOID_RETURN; - } /* Get database collation. */ + if (switch_character_set_results(mysql, "binary")) + DBUG_RETURN(TRUE); + if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name))) - DBUG_VOID_RETURN; + DBUG_RETURN(TRUE); - if (switch_character_set_results(mysql, "binary")) - DBUG_VOID_RETURN; + /* Get list of triggers. */ + + my_snprintf(query_buff, sizeof(query_buff), + "SHOW TRIGGERS LIKE %s", + quote_for_like(table_name, name_buff)); + + if (mysql_query_with_error_report(mysql, &show_triggers_rs, query_buff)) + DBUG_RETURN(TRUE); /* Dump triggers. */ - while ((row= mysql_fetch_row(result))) + while ((row= mysql_fetch_row(show_triggers_rs))) { - MYSQL_RES *res2; my_snprintf(query_buff, sizeof (query_buff), "SHOW CREATE TRIGGER %s", quote_name(row[0], name_buff, TRUE)); - if (mysql_query_with_error_report(mysql, &res2, query_buff)) + if (mysql_query(mysql, query_buff)) { - if (path) - my_fclose(sql_file, MYF(MY_WME)); - maybe_exit(EX_MYSQLERR); - DBUG_VOID_RETURN; - } - - while ((row= mysql_fetch_row(res2))) - { - char *query_str= NULL; - char *definer_begin; - /* - Cover DEFINER-clause in version-specific comments. - - TODO: this is definitely a BAD IDEA to parse SHOW CREATE output. - However, we can not use INFORMATION_SCHEMA instead: - 1. INFORMATION_SCHEMA provides data in UTF8, but here we - need data in the original character set; - 2. INFORMATION_SCHEMA does not provide information about - routine parameters now. - */ - - definer_begin= my_case_str(row[2], strlen(row[2]), - C_STRING_WITH_LEN(" DEFINER")); + mysqldump is being run against old server, that does not support + SHOW CREATE TRIGGER statement. We should use SHOW TRIGGERS output. - if (definer_begin) - { - char *definer_end= my_case_str(definer_begin, strlen(definer_begin), - C_STRING_WITH_LEN(" TRIGGER")); - - if (definer_end) - { - char *query_str_tail; - - /* - Allocate memory for new query string: original string - from SHOW statement and version-specific comments. - */ - query_str= alloc_query_str(strlen(row[2]) + 23); - - query_str_tail= strnmov(query_str, row[2], - definer_begin - row[2]); - query_str_tail= strmov(query_str_tail, "*/ /*!50017"); - query_str_tail= strnmov(query_str_tail, definer_begin, - definer_end - definer_begin); - query_str_tail= strxmov(query_str_tail, "*/ /*!50003", - definer_end, NullS); - } - } - - if (switch_db_collation(sql_file, db_name, ";", - db_cl_name, row[5], &db_cl_altered)) - DBUG_VOID_RETURN; - - switch_cs_variables(sql_file, ";", - row[3], /* character_set_client */ - row[3], /* character_set_results */ - row[4]); /* collation_connection */ - - switch_sql_mode(sql_file, ";", row[1]); - - fprintf(sql_file, - "DELIMITER ;;\n" - "/*!50003 %s */;;\n" - "DELIMITER ;\n", - (const char *) (query_str != NULL ? query_str : row[2])); + NOTE: the dump may be incorrect, as old SHOW TRIGGERS does not + provide all the necessary information to restore trigger properly. + */ - restore_sql_mode(sql_file, ";"); - restore_cs_variables(sql_file, ";"); + dump_trigger_old(show_triggers_rs, &row, table_name); + } + else + { + MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql); - if (db_cl_altered) + if (!show_create_trigger_rs || + dump_trigger(show_create_trigger_rs, db_name, db_cl_name)) { - if (restore_db_collation(sql_file, db_name, ";", db_cl_name)) - DBUG_VOID_RETURN; + DBUG_RETURN(TRUE); } - my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); + mysql_free_result(show_create_trigger_rs); } - mysql_free_result(res2); + } - mysql_free_result(result); + mysql_free_result(show_triggers_rs); if (switch_character_set_results(mysql, default_charset)) - DBUG_VOID_RETURN; + DBUG_RETURN(TRUE); /* make sure to set back opt_compatible mode to @@ -2714,7 +2890,7 @@ static void dump_triggers_for_table(char *table, char *db_name) */ opt_compatible_mode=old_opt_compatible_mode; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } static void add_load_option(DYNAMIC_STRING *str, const char *option, @@ -3737,7 +3913,7 @@ static int init_dumping(char *database, int init_func(char*)) /* Return 1 if we should copy the table */ -my_bool include_table(uchar* hash_key, uint len) +my_bool include_table(const char* hash_key, uint len) { return !hash_search(&ignore_table, (uchar*) hash_key, len); } @@ -3795,7 +3971,14 @@ static int dump_all_tables_in_db(char *database) order_by= 0; if (opt_dump_triggers && ! opt_xml && mysql_get_server_version(mysql) >= 50009) - dump_triggers_for_table(table, database); + { + if (dump_triggers_for_table(table, database)) + { + if (path) + my_fclose(md_result_file, MYF(MY_WME)); + maybe_exit(EX_MYSQLERR); + } + } } } if (opt_events && !opt_xml && @@ -4021,7 +4204,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables) dump_table(*pos, db); if (opt_dump_triggers && mysql_get_server_version(mysql) >= 50009) - dump_triggers_for_table(*pos, db); + { + if (dump_triggers_for_table(*pos, db)) + { + if (path) + my_fclose(md_result_file, MYF(MY_WME)); + maybe_exit(EX_MYSQLERR); + } + } } /* Dump each selected view */ diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index ca936cd5fde..8f1fe20ea3b 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1920,6 +1920,20 @@ a b 2 Curly drop table federated.t1; drop table federated.t1; + +Bug#18287 create federated table always times out, error 1159 ' ' + +Test that self-references work + +create table federated.t1 (a int primary key); +create table federated.t2 (a int primary key) +ENGINE=FEDERATED +connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +insert into federated.t1 (a) values (1); +select * from federated.t2; +a +1 +drop table federated.t1, federated.t2; CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8; CREATE TABLE federated.t1 (a INT PRIMARY KEY) ENGINE=FEDERATED diff --git a/mysql-test/r/lock.result b/mysql-test/r/lock.result index e2000a9ec91..6152e403637 100644 --- a/mysql-test/r/lock.result +++ b/mysql-test/r/lock.result @@ -96,4 +96,74 @@ ERROR HY000: You can't combine write-locking of system tables with other tables LOCK TABLES mysql.time_zone READ, mysql.proc WRITE; ERROR HY000: You can't combine write-locking of system tables with other tables or lock types DROP TABLE t1; + +Bug#5719 impossible to lock VIEW + +Just covering existing behaviour with tests. +Consistency has not been found here. + +drop view if exists v_bug5719; +drop table if exists t1, t2, t3; +create table t1 (a int); +create temporary table t2 (a int); +create table t3 (a int); +create view v_bug5719 as select 1; +lock table v_bug5719 write; +select * from t1; +ERROR HY000: Table 't1' was not locked with LOCK TABLES + +Allowed to select from a temporary talbe under LOCK TABLES + +select * from t2; +a +select * from t3; +ERROR HY000: Table 't3' was not locked with LOCK TABLES +select * from v_bug5719; +1 +1 +drop view v_bug5719; + +sic: did not left LOCK TABLES mode automatically + +select * from t1; +ERROR HY000: Table 't1' was not locked with LOCK TABLES +unlock tables; +create view v_bug5719 as select * from t1; +lock tables v_bug5719 write; +select * from v_bug5719; +a + +Allowed to use an underlying table under LOCK TABLES <view> + +select * from t1; +a + +Allowed to select from a temporary table under LOCK TABLES + +select * from t2; +a +select * from t3; +ERROR HY000: Table 't3' was not locked with LOCK TABLES +drop table t1; + +sic: left LOCK TABLES mode + +select * from t3; +a +select * from v_bug5719; +ERROR HY000: View 'test.v_bug5719' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +unlock tables; +drop view v_bug5719; + +When limitation to use temporary tables in views is removed, please +add a test that shows what happens under LOCK TABLES when a view +references a temporary table, is locked, and the underlying table +is dropped. + +create view v_bug5719 as select * from t2; +ERROR HY000: View's SELECT refers to a temporary table 't2' + +Cleanup. + +drop table t2, t3; End of 5.1 tests. diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 2445b3e0c69..a3f7ab4505c 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -95,3 +95,13 @@ alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; // unlock tables; drop table t1; +create table t1 (i int); +lock table t1 read; +update t1 set i= 10;; +select * from t1;; +kill query ID; +i +ERROR 70100: Query execution was interrupted +unlock tables; +drop table t1; +End of 5.1 tests diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 0c6be16b9b7..3a3ef584ce3 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -37,14 +37,14 @@ set session long_query_time=1; select sleep(2); sleep(2) 0 -select * from mysql.slow_log; +select * from mysql.slow_log where sql_text NOT LIKE '%slow_log%'; start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text set global slow_query_log= ON; set session long_query_time=1; select sleep(2); sleep(2) 0 -select * from mysql.slow_log; +select * from mysql.slow_log where sql_text NOT LIKE '%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) show global variables diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 6597c77e798..90f1fa36bb4 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1725,6 +1725,20 @@ drop table federated.t1; connection slave; drop table federated.t1; +--echo +--echo Bug#18287 create federated table always times out, error 1159 ' ' +--echo +--echo Test that self-references work +--echo +connection slave; +create table federated.t1 (a int primary key); +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval create table federated.t2 (a int primary key) + ENGINE=FEDERATED + connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; +insert into federated.t1 (a) values (1); +select * from federated.t2; +drop table federated.t1, federated.t2; # # BUG#29875 Disable support for transactions diff --git a/mysql-test/t/lock.test b/mysql-test/t/lock.test index 2b8b430f096..6069bbf7018 100644 --- a/mysql-test/t/lock.test +++ b/mysql-test/t/lock.test @@ -148,5 +148,70 @@ LOCK TABLES mysql.time_zone READ, mysql.proc WRITE; DROP TABLE t1; +--echo +--echo Bug#5719 impossible to lock VIEW +--echo +--echo Just covering existing behaviour with tests. +--echo Consistency has not been found here. +--echo +--disable_warnings +drop view if exists v_bug5719; +drop table if exists t1, t2, t3; +--enable_warnings +create table t1 (a int); +create temporary table t2 (a int); +create table t3 (a int); +create view v_bug5719 as select 1; +lock table v_bug5719 write; +--error ER_TABLE_NOT_LOCKED +select * from t1; +--echo +--echo Allowed to select from a temporary talbe under LOCK TABLES +--echo +select * from t2; +--error ER_TABLE_NOT_LOCKED +select * from t3; +select * from v_bug5719; +drop view v_bug5719; +--echo +--echo sic: did not left LOCK TABLES mode automatically +--echo +--error ER_TABLE_NOT_LOCKED +select * from t1; +unlock tables; +create view v_bug5719 as select * from t1; +lock tables v_bug5719 write; +select * from v_bug5719; +--echo +--echo Allowed to use an underlying table under LOCK TABLES <view> +--echo +select * from t1; +--echo +--echo Allowed to select from a temporary table under LOCK TABLES +--echo +select * from t2; +--error ER_TABLE_NOT_LOCKED +select * from t3; +drop table t1; +--echo +--echo sic: left LOCK TABLES mode +--echo +select * from t3; +--error ER_VIEW_INVALID +select * from v_bug5719; +unlock tables; +drop view v_bug5719; +--echo +--echo When limitation to use temporary tables in views is removed, please +--echo add a test that shows what happens under LOCK TABLES when a view +--echo references a temporary table, is locked, and the underlying table +--echo is dropped. +--echo +--error ER_VIEW_SELECT_TMPTABLE +create view v_bug5719 as select * from t2; +--echo +--echo Cleanup. +--echo +drop table t2, t3; --echo End of 5.1 tests. diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 4a6b4ff5e56..b7c406f9637 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -270,3 +270,38 @@ drop table t1; # End of 5.0 tests + +# +# Bug #21281 "Pending write lock is incorrectly removed when its +# statement being KILLed" +# +create table t1 (i int); +connection locker; +lock table t1 read; +connection writer; +--send update t1 set i= 10; +connection reader; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "update t1 set i= 10"; +--source include/wait_condition.inc +--send select * from t1; +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Locked" and info = "select * from t1"; +--source include/wait_condition.inc +let $ID= `select id from information_schema.processlist where state = "Locked" and info = "update t1 set i= 10"`; +--replace_result $ID ID +eval kill query $ID; +connection reader; +--reap +connection writer; +--error ER_QUERY_INTERRUPTED +--reap +connection locker; +unlock tables; +connection default; +drop table t1; + +--echo End of 5.1 tests diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test index b0bb818b783..c67da261ef1 100644 --- a/mysql-test/t/log_state.test +++ b/mysql-test/t/log_state.test @@ -28,7 +28,7 @@ connection con1; set session long_query_time=1; select sleep(2); --replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME -select * from mysql.slow_log; +select * from mysql.slow_log where sql_text NOT LIKE '%slow_log%'; connection default; set global slow_query_log= ON; @@ -36,7 +36,7 @@ connection con1; set session long_query_time=1; select sleep(2); --replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME -select * from mysql.slow_log; +select * from mysql.slow_log where sql_text NOT LIKE '%slow_log%'; connection default; show global variables where Variable_name = 'log' or Variable_name = 'log_slow_queries' or diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 20edffb49c2..a81ed925562 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -384,6 +384,9 @@ static inline my_bool have_specific_lock(THR_LOCK_DATA *data, } +static void wake_up_waiters(THR_LOCK *lock); + + static enum enum_thr_lock_result wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, my_bool in_wait_list) @@ -445,8 +448,13 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, else wait->last=data->prev; data->type= TL_UNLOCK; /* No lock */ + check_locks(data->lock, "killed or timed out wait_for_lock", 1); + wake_up_waiters(data->lock); + } + else + { + check_locks(data->lock, "aborted wait_for_lock", 0); } - check_locks(data->lock,"failed wait_for_lock",0); } else { @@ -776,6 +784,26 @@ void thr_unlock(THR_LOCK_DATA *data) lock->read_no_write_count--; data->type=TL_UNLOCK; /* Mark unlocked */ check_locks(lock,"after releasing lock",1); + wake_up_waiters(lock); + pthread_mutex_unlock(&lock->mutex); + DBUG_VOID_RETURN; +} + + +/** + @brief Wake up all threads which pending requests for the lock + can be satisfied. + + @param lock Lock for which threads should be woken up + +*/ + +static void wake_up_waiters(THR_LOCK *lock) +{ + THR_LOCK_DATA *data; + enum thr_lock_type lock_type; + + DBUG_ENTER("wake_up_waiters"); if (!lock->write.data) /* If no active write locks */ { @@ -827,11 +855,7 @@ void thr_unlock(THR_LOCK_DATA *data) data=lock->write_wait.data; /* Free this too */ } if (data->type >= TL_WRITE_LOW_PRIORITY) - { - check_locks(lock,"giving write lock",0); - pthread_mutex_unlock(&lock->mutex); - DBUG_VOID_RETURN; - } + goto end; /* Release possible read locks together with the write lock */ } if (lock->read_wait.data) @@ -886,8 +910,7 @@ void thr_unlock(THR_LOCK_DATA *data) free_all_read_locks(lock,0); } end: - check_locks(lock,"thr_unlock",0); - pthread_mutex_unlock(&lock->mutex); + check_locks(lock, "after waking up waiters", 0); DBUG_VOID_RETURN; } @@ -1101,6 +1124,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) lock->write_wait.last= data->prev; } } + wake_up_waiters(lock); pthread_mutex_unlock(&lock->mutex); DBUG_RETURN(found); } diff --git a/sql/item.cc b/sql/item.cc index 006595a39a9..76aad708d22 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1705,7 +1705,7 @@ void Item_ident_for_show::make_field(Send_field *tmp_field) tmp_field->type=field->type(); tmp_field->flags= field->table->maybe_null ? (field->flags & ~NOT_NULL_FLAG) : field->flags; - tmp_field->decimals= 0; + tmp_field->decimals= field->decimals(); } /**********************************************/ diff --git a/sql/table.cc b/sql/table.cc index 12fffe1dde7..27f9ccc418e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2484,6 +2484,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) create_info->row_type= share->row_type; create_info->default_table_charset= share->table_charset; create_info->table_charset= 0; + create_info->comment= share->comment; DBUG_VOID_RETURN; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index eac1ad413ea..3656364820e 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16077,7 +16077,6 @@ static void test_bug24179() /* Bug#28075 "COM_DEBUG crashes mysqld" - Note: Test disabled because of failure in PushBuild. */ static void test_bug28075() @@ -16106,7 +16105,7 @@ static void test_bug27876() int rc; MYSQL_RES *result; - char utf8_func[] = + unsigned char utf8_func[] = { 0xd1, 0x84, 0xd1, 0x83, 0xd0, 0xbd, 0xd0, 0xba, 0xd1, 0x86, 0xd0, 0xb8, 0xd0, 0xb9, 0xd0, 0xba, @@ -16114,7 +16113,7 @@ static void test_bug27876() 0x00 }; - char utf8_param[] = + unsigned char utf8_param[] = { 0xd0, 0xbf, 0xd0, 0xb0, 0xd1, 0x80, 0xd0, 0xb0, 0xd0, 0xbc, 0xd0, 0xb5, 0xd1, 0x82, 0xd1, 0x8a, @@ -16334,7 +16333,54 @@ static void test_bug29692() mysql_close(conn); } +/** + Bug#29306 Truncated data in MS Access with decimal (3,1) columns in a VIEW +*/ + +static void test_bug29306() +{ + MYSQL_FIELD *field; + int rc; + MYSQL_RES *res; + + DBUG_ENTER("test_bug29306"); + myheader("test_bug29306"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS tab17557"); + myquery(rc); + rc= mysql_query(mysql, "DROP VIEW IF EXISTS view17557"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE tab17557 (dd decimal (3,1))"); + myquery(rc); + rc= mysql_query(mysql, "CREATE VIEW view17557 as SELECT dd FROM tab17557"); + myquery(rc); + rc= mysql_query(mysql, "INSERT INTO tab17557 VALUES (7.6)"); + myquery(rc); + + /* Checking the view */ + res= mysql_list_fields(mysql, "view17557", NULL); + while ((field= mysql_fetch_field(res))) + { + if (! opt_silent) + { + printf("field name %s\n", field->name); + printf("field table %s\n", field->table); + printf("field decimals %d\n", field->decimals); + if (field->decimals < 1) + printf("Error! No decimals! \n"); + printf("\n\n"); + } + DIE_UNLESS(field->decimals == 1); + } + mysql_free_result(res); + + rc= mysql_query(mysql, "DROP TABLE tab17557"); + myquery(rc); + rc= mysql_query(mysql, "DROP VIEW view17557"); + myquery(rc); + DBUG_VOID_RETURN; +} /* Read and parse arguments and MySQL options from my.cnf */ @@ -16626,6 +16672,7 @@ static struct my_tests_st my_tests[]= { { "test_bug27592", test_bug27592 }, { "test_bug29687", test_bug29687 }, { "test_bug29692", test_bug29692 }, + { "test_bug29306", test_bug29306 }, { 0, 0 } }; |