mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into bodhi.(none):/opt/local/work/mysql-5.1-runtime
This commit is contained in:
commit
28f1f1828d
8 changed files with 616 additions and 194 deletions
|
@ -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.
|
||||
query_str= cover_definer_clause_in_sp(row[2], strlen(row[2]));
|
||||
|
||||
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,
|
||||
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);
|
||||
|
||||
dump_triggers_for_table
|
||||
char name_buff[NAME_LEN * 4 + 3];
|
||||
|
||||
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
|
||||
DBUG_ENTER("dump_trigger_old");
|
||||
|
||||
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");
|
||||
|
||||
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 (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name)))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
if (switch_character_set_results(mysql, "binary"))
|
||||
DBUG_VOID_RETURN;
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/* 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.
|
||||
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.
|
||||
NOTE: the dump may be incorrect, as old SHOW TRIGGERS does not
|
||||
provide all the necessary information to restore trigger properly.
|
||||
*/
|
||||
|
||||
definer_begin= my_case_str(row[2], strlen(row[2]),
|
||||
C_STRING_WITH_LEN(" DEFINER"));
|
||||
|
||||
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]));
|
||||
|
||||
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_VOID_RETURN;
|
||||
}
|
||||
|
||||
my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
|
||||
dump_trigger_old(show_triggers_rs, &row, table_name);
|
||||
}
|
||||
mysql_free_result(res2);
|
||||
else
|
||||
{
|
||||
MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql);
|
||||
|
||||
if (!show_create_trigger_rs ||
|
||||
dump_trigger(show_create_trigger_rs, db_name, db_cl_name))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
mysql_free_result(show_create_trigger_rs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue