Commit 28f1f182 authored by kostja@bodhi.(none)'s avatar kostja@bodhi.(none)

Merge bk-internal.mysql.com:/home/bk/mysql-5.1

into  bodhi.(none):/opt/local/work/mysql-5.1-runtime
parents 0afb19f5 256450d8
...@@ -1236,6 +1236,125 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name) ...@@ -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); 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 Open a new .sql file to dump the table or view into
...@@ -1710,7 +1829,7 @@ static uint dump_events_for_db(char *db) ...@@ -1710,7 +1829,7 @@ static uint dump_events_for_db(char *db)
MYSQL_ROW row, event_list_row; MYSQL_ROW row, event_list_row;
char db_cl_name[MY_CS_NAME_SIZE]; char db_cl_name[MY_CS_NAME_SIZE];
int db_cl_altered; int db_cl_altered= FALSE;
DBUG_ENTER("dump_events_for_db"); DBUG_ENTER("dump_events_for_db");
DBUG_PRINT("enter", ("db: '%s'", db)); DBUG_PRINT("enter", ("db: '%s'", db));
...@@ -1775,16 +1894,36 @@ static uint dump_events_for_db(char *db) ...@@ -1775,16 +1894,36 @@ static uint dump_events_for_db(char *db)
fprintf(sql_file, "DELIMITER %s\n", delimiter); fprintf(sql_file, "DELIMITER %s\n", delimiter);
if (switch_db_collation(sql_file, db_name_buff, delimiter, db_cl_name, if (mysql_num_fields(event_res) >= 7)
row[6], &db_cl_altered))
{ {
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, switch_cs_variables(sql_file, delimiter,
row[4], /* character_set_client */ row[4], /* character_set_client */
row[4], /* character_set_results */ row[4], /* character_set_results */
row[5]); /* collation_connection */ 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]); switch_sql_mode(sql_file, delimiter, row[1]);
...@@ -1797,13 +1936,17 @@ static uint dump_events_for_db(char *db) ...@@ -1797,13 +1936,17 @@ static uint dump_events_for_db(char *db)
restore_time_zone(sql_file, delimiter); restore_time_zone(sql_file, delimiter);
restore_sql_mode(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, restore_cs_variables(sql_file, delimiter);
db_cl_name))
DBUG_RETURN(1); if (db_cl_altered)
{
if (restore_db_collation(sql_file, db_name_buff, delimiter,
db_cl_name))
DBUG_RETURN(1);
}
} }
} }
} /* end of event printing */ } /* end of event printing */
...@@ -1871,7 +2014,7 @@ static uint dump_routines_for_db(char *db) ...@@ -1871,7 +2014,7 @@ static uint dump_routines_for_db(char *db)
MYSQL_ROW row, routine_list_row; MYSQL_ROW row, routine_list_row;
char db_cl_name[MY_CS_NAME_SIZE]; char db_cl_name[MY_CS_NAME_SIZE];
int db_cl_altered; int db_cl_altered= FALSE;
DBUG_ENTER("dump_routines_for_db"); DBUG_ENTER("dump_routines_for_db");
DBUG_PRINT("enter", ("db: '%s'", db)); DBUG_PRINT("enter", ("db: '%s'", db));
...@@ -1938,74 +2081,45 @@ static uint dump_routines_for_db(char *db) ...@@ -1938,74 +2081,45 @@ static uint dump_routines_for_db(char *db)
} }
else if (strlen(row[2])) else if (strlen(row[2]))
{ {
char *query_str= NULL; char *query_str;
char *definer_begin;
if (opt_drop) if (opt_drop)
fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n", fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n",
routine_type[i], routine_name); routine_type[i], routine_name);
/* query_str= cover_definer_clause_in_sp(row[2], strlen(row[2]));
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"));
if (definer_begin) if (mysql_num_fields(routine_res) >= 6)
{ {
char *definer_end= my_case_str(definer_begin, if (switch_db_collation(sql_file, db_name_buff, ";",
strlen(definer_begin), db_cl_name, row[5], &db_cl_altered))
C_STRING_WITH_LEN(" PROCEDURE"));
if (!definer_end)
{ {
definer_end= my_case_str(definer_begin, strlen(definer_begin), DBUG_RETURN(1);
C_STRING_WITH_LEN(" FUNCTION"));
} }
if (definer_end) switch_cs_variables(sql_file, ";",
{ row[3], /* character_set_client */
char *query_str_tail; row[3], /* character_set_results */
row[4]); /* collation_connection */
/*
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);
}
} }
else
/*
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))
{ {
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]); switch_sql_mode(sql_file, ";", row[1]);
...@@ -2016,12 +2130,16 @@ static uint dump_routines_for_db(char *db) ...@@ -2016,12 +2130,16 @@ static uint dump_routines_for_db(char *db)
(const char *) (query_str != NULL ? query_str : row[2])); (const char *) (query_str != NULL ? query_str : row[2]));
restore_sql_mode(sql_file, ";"); 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)) restore_cs_variables(sql_file, ";");
DBUG_RETURN(1);
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)); my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
...@@ -2560,153 +2678,211 @@ static uint get_table_structure(char *table, char *db, char *table_type, ...@@ -2560,153 +2678,211 @@ static uint get_table_structure(char *table, char *db, char *table_type,
DBUG_RETURN((uint) num_fields); DBUG_RETURN((uint) num_fields);
} /* get_table_structure */ } /* 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 fprintf(sql_file,
the tables have been dumped in case a trigger depends on the existence "DELIMITER ;;\n"
of a table "/*!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];
char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
char query_buff[QUERY_LENGTH]; char query_buff[QUERY_LENGTH];
uint old_opt_compatible_mode=opt_compatible_mode; uint old_opt_compatible_mode= opt_compatible_mode;
FILE *sql_file= md_result_file; MYSQL_RES *show_triggers_rs;
MYSQL_RES *result;
MYSQL_ROW row; MYSQL_ROW row;
char db_cl_name[MY_CS_NAME_SIZE]; char db_cl_name[MY_CS_NAME_SIZE];
int db_cl_altered;
DBUG_ENTER("dump_triggers_for_table"); 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 */ /* Do not use ANSI_QUOTES on triggers in dump */
opt_compatible_mode&= ~MASK_ANSI_QUOTES; 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. */ /* 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))) 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")) /* Get list of triggers. */
DBUG_VOID_RETURN;
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. */ /* 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), my_snprintf(query_buff, sizeof (query_buff),
"SHOW CREATE TRIGGER %s", "SHOW CREATE TRIGGER %s",
quote_name(row[0], name_buff, TRUE)); 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. mysqldump is being run against old server, that does not support
SHOW CREATE TRIGGER statement. We should use SHOW TRIGGERS output.
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"));
if (definer_begin) NOTE: the dump may be incorrect, as old SHOW TRIGGERS does not
{ provide all the necessary information to restore trigger properly.
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]));
restore_sql_mode(sql_file, ";"); dump_trigger_old(show_triggers_rs, &row, table_name);
restore_cs_variables(sql_file, ";"); }
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_RETURN(TRUE);
DBUG_VOID_RETURN;
} }
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)) if (switch_character_set_results(mysql, default_charset))
DBUG_VOID_RETURN; DBUG_RETURN(TRUE);
/* /*
make sure to set back opt_compatible mode to make sure to set back opt_compatible mode to
...@@ -2714,7 +2890,7 @@ static void dump_triggers_for_table(char *table, char *db_name) ...@@ -2714,7 +2890,7 @@ static void dump_triggers_for_table(char *table, char *db_name)
*/ */
opt_compatible_mode=old_opt_compatible_mode; opt_compatible_mode=old_opt_compatible_mode;
DBUG_VOID_RETURN; DBUG_RETURN(FALSE);
} }
static void add_load_option(DYNAMIC_STRING *str, const char *option, 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*)) ...@@ -3737,7 +3913,7 @@ static int init_dumping(char *database, int init_func(char*))
/* Return 1 if we should copy the table */ /* 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); return !hash_search(&ignore_table, (uchar*) hash_key, len);
} }
...@@ -3795,7 +3971,14 @@ static int dump_all_tables_in_db(char *database) ...@@ -3795,7 +3971,14 @@ static int dump_all_tables_in_db(char *database)
order_by= 0; order_by= 0;
if (opt_dump_triggers && ! opt_xml && if (opt_dump_triggers && ! opt_xml &&
mysql_get_server_version(mysql) >= 50009) 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 && if (opt_events && !opt_xml &&
...@@ -4021,7 +4204,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables) ...@@ -4021,7 +4204,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
dump_table(*pos, db); dump_table(*pos, db);
if (opt_dump_triggers && if (opt_dump_triggers &&
mysql_get_server_version(mysql) >= 50009) 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 */ /* Dump each selected view */
......
...@@ -1920,6 +1920,20 @@ a b ...@@ -1920,6 +1920,20 @@ a b
2 Curly 2 Curly
drop table federated.t1; drop table federated.t1;
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) DEFAULT CHARSET=utf8;
CREATE TABLE federated.t1 (a INT PRIMARY KEY) CREATE TABLE federated.t1 (a INT PRIMARY KEY)
ENGINE=FEDERATED ENGINE=FEDERATED
......
...@@ -96,4 +96,74 @@ ERROR HY000: You can't combine write-locking of system tables with other tables ...@@ -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; 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 ERROR HY000: You can't combine write-locking of system tables with other tables or lock types
DROP TABLE t1; 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. End of 5.1 tests.
...@@ -95,3 +95,13 @@ alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 ...@@ -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; // 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; unlock tables;
drop table t1; 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
...@@ -1725,6 +1725,20 @@ drop table federated.t1; ...@@ -1725,6 +1725,20 @@ drop table federated.t1;
connection slave; connection slave;
drop table federated.t1; 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 # BUG#29875 Disable support for transactions
......
...@@ -148,5 +148,70 @@ LOCK TABLES mysql.time_zone READ, mysql.proc WRITE; ...@@ -148,5 +148,70 @@ LOCK TABLES mysql.time_zone READ, mysql.proc WRITE;
DROP TABLE t1; 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. --echo End of 5.1 tests.
...@@ -270,3 +270,38 @@ drop table t1; ...@@ -270,3 +270,38 @@ drop table t1;
# End of 5.0 tests # 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
...@@ -384,6 +384,9 @@ static inline my_bool have_specific_lock(THR_LOCK_DATA *data, ...@@ -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 static enum enum_thr_lock_result
wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
my_bool in_wait_list) my_bool in_wait_list)
...@@ -445,8 +448,13 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, ...@@ -445,8 +448,13 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
else else
wait->last=data->prev; wait->last=data->prev;
data->type= TL_UNLOCK; /* No lock */ 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 else
{ {
...@@ -776,6 +784,26 @@ void thr_unlock(THR_LOCK_DATA *data) ...@@ -776,6 +784,26 @@ void thr_unlock(THR_LOCK_DATA *data)
lock->read_no_write_count--; lock->read_no_write_count--;
data->type=TL_UNLOCK; /* Mark unlocked */ data->type=TL_UNLOCK; /* Mark unlocked */
check_locks(lock,"after releasing lock",1); 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 */ if (!lock->write.data) /* If no active write locks */
{ {
...@@ -827,11 +855,7 @@ void thr_unlock(THR_LOCK_DATA *data) ...@@ -827,11 +855,7 @@ void thr_unlock(THR_LOCK_DATA *data)
data=lock->write_wait.data; /* Free this too */ data=lock->write_wait.data; /* Free this too */
} }
if (data->type >= TL_WRITE_LOW_PRIORITY) if (data->type >= TL_WRITE_LOW_PRIORITY)
{ goto end;
check_locks(lock,"giving write lock",0);
pthread_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN;
}
/* Release possible read locks together with the write lock */ /* Release possible read locks together with the write lock */
} }
if (lock->read_wait.data) if (lock->read_wait.data)
...@@ -886,8 +910,7 @@ void thr_unlock(THR_LOCK_DATA *data) ...@@ -886,8 +910,7 @@ void thr_unlock(THR_LOCK_DATA *data)
free_all_read_locks(lock,0); free_all_read_locks(lock,0);
} }
end: end:
check_locks(lock,"thr_unlock",0); check_locks(lock, "after waking up waiters", 0);
pthread_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -1101,6 +1124,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) ...@@ -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; lock->write_wait.last= data->prev;
} }
} }
wake_up_waiters(lock);
pthread_mutex_unlock(&lock->mutex); pthread_mutex_unlock(&lock->mutex);
DBUG_RETURN(found); DBUG_RETURN(found);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment