Commit a22a5104 authored by unknown's avatar unknown

Merge ramayana.hindu.god:/home/tsmith/m/bk/51

into  ramayana.hindu.god:/home/tsmith/m/bk/maint/51

parents b35cad86 6930ac54
...@@ -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,8 +1894,10 @@ static uint dump_events_for_db(char *db) ...@@ -1775,8 +1894,10 @@ 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)) {
if (switch_db_collation(sql_file, db_name_buff, delimiter,
db_cl_name, row[6], &db_cl_altered))
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -1785,6 +1906,24 @@ static uint dump_events_for_db(char *db) ...@@ -1785,6 +1906,24 @@ static uint dump_events_for_db(char *db)
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,6 +1936,9 @@ static uint dump_events_for_db(char *db) ...@@ -1797,6 +1936,9 @@ 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);
if (mysql_num_fields(event_res) >= 7)
{
restore_cs_variables(sql_file, delimiter); restore_cs_variables(sql_file, delimiter);
if (db_cl_altered) if (db_cl_altered)
...@@ -1806,6 +1948,7 @@ static uint dump_events_for_db(char *db) ...@@ -1806,6 +1948,7 @@ static uint dump_events_for_db(char *db)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
}
} /* end of event printing */ } /* end of event printing */
mysql_free_result(event_res); mysql_free_result(event_res);
...@@ -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,64 +2081,15 @@ static uint dump_routines_for_db(char *db) ...@@ -1938,64 +2081,15 @@ 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)
{
char *definer_end= my_case_str(definer_begin,
strlen(definer_begin),
C_STRING_WITH_LEN(" PROCEDURE"));
if (!definer_end) if (mysql_num_fields(routine_res) >= 6)
{
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(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);
}
}
/*
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, ";", if (switch_db_collation(sql_file, db_name_buff, ";",
db_cl_name, row[5], &db_cl_altered)) db_cl_name, row[5], &db_cl_altered))
{ {
...@@ -2006,6 +2100,26 @@ static uint dump_routines_for_db(char *db) ...@@ -2006,6 +2100,26 @@ static uint dump_routines_for_db(char *db)
row[3], /* character_set_client */ row[3], /* character_set_client */
row[3], /* character_set_results */ row[3], /* character_set_results */
row[4]); /* collation_connection */ row[4]); /* 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 stored
procedure/function properly.
*/
fprintf(sql_file,
"--\n"
"-- WARNING: old server version. "
"The following dump may be incomplete.\n"
"--\n");
}
switch_sql_mode(sql_file, ";", row[1]); switch_sql_mode(sql_file, ";", row[1]);
...@@ -2016,6 +2130,9 @@ static uint dump_routines_for_db(char *db) ...@@ -2016,6 +2130,9 @@ 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, ";");
if (mysql_num_fields(routine_res) >= 6)
{
restore_cs_variables(sql_file, ";"); restore_cs_variables(sql_file, ";");
if (db_cl_altered) if (db_cl_altered)
...@@ -2023,6 +2140,7 @@ static uint dump_routines_for_db(char *db) ...@@ -2023,6 +2140,7 @@ static uint dump_routines_for_db(char *db)
if (restore_db_collation(sql_file, db_name_buff, ";", db_cl_name)) if (restore_db_collation(sql_file, db_name_buff, ";", db_cl_name))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
}
my_free(query_str, MYF(MY_ALLOW_ZERO_PTR)); my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
} }
...@@ -2560,121 +2678,95 @@ continue_xml: ...@@ -2560,121 +2678,95 @@ continue_xml:
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)
dump_triggers_for_table
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
*/
static void dump_triggers_for_table(char *table, char *db_name)
{ {
char *result_table;
char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
char query_buff[QUERY_LENGTH];
uint old_opt_compatible_mode=opt_compatible_mode;
FILE *sql_file= md_result_file; FILE *sql_file= md_result_file;
MYSQL_RES *result;
MYSQL_ROW row;
char db_cl_name[MY_CS_NAME_SIZE]; char quoted_table_name_buf[NAME_LEN * 2 + 3];
int db_cl_altered; char *quoted_table_name= quote_name(table_name, quoted_table_name_buf, 1);
DBUG_ENTER("dump_triggers_for_table"); char name_buff[NAME_LEN * 4 + 3];
DBUG_PRINT("enter", ("db: %s, table: %s", db_name, table));
/* Do not use ANSI_QUOTES on triggers in dump */ DBUG_ENTER("dump_trigger_old");
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. */ fprintf(sql_file,
"--\n"
if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name))) "-- WARNING: old server version. "
DBUG_VOID_RETURN; "The following dump may be incomplete.\n"
"--\n");
if (switch_character_set_results(mysql, "binary")) if (opt_compact)
DBUG_VOID_RETURN; fprintf(sql_file, "/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n");
/* Dump triggers. */ fprintf(sql_file,
"DELIMITER ;;\n"
"/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n"
"/*!50003 CREATE */ ",
(*show_trigger_row)[6]);
while ((row= mysql_fetch_row(result))) if (mysql_num_fields(show_triggers_rs) > 7)
{ {
MYSQL_RES *res2; /*
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.
*/
my_snprintf(query_buff, sizeof (query_buff), size_t user_name_len;
"SHOW CREATE TRIGGER %s", char user_name_str[USERNAME_LENGTH + 1];
quote_name(row[0], name_buff, TRUE)); 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];
if (mysql_query_with_error_report(mysql, &res2, query_buff)) parse_user((*show_trigger_row)[7],
{ strlen((*show_trigger_row)[7]),
if (path) user_name_str, &user_name_len,
my_fclose(sql_file, MYF(MY_WME)); host_name_str, &host_name_len);
maybe_exit(EX_MYSQLERR);
DBUG_VOID_RETURN; 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));
} }
while ((row= mysql_fetch_row(res2))) fprintf(sql_file,
{ "/*!50003 TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n"
char *query_str= NULL; "DELIMITER ;\n",
char *definer_begin; 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)
Cover DEFINER-clause in version-specific comments. fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n");
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]), DBUG_VOID_RETURN;
C_STRING_WITH_LEN(" DEFINER")); }
if (definer_begin) static int dump_trigger(MYSQL_RES *show_create_trigger_rs,
{ const char *db_name,
char *definer_end= my_case_str(definer_begin, strlen(definer_begin), const char *db_cl_name)
C_STRING_WITH_LEN(" TRIGGER")); {
FILE *sql_file= md_result_file;
MYSQL_ROW row;
int db_cl_altered= FALSE;
if (definer_end) DBUG_ENTER("dump_trigger");
while ((row= mysql_fetch_row(show_create_trigger_rs)))
{ {
char *query_str_tail; char *query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2]));
/*
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, ";", if (switch_db_collation(sql_file, db_name, ";",
db_cl_name, row[5], &db_cl_altered)) db_cl_name, row[5], &db_cl_altered))
DBUG_VOID_RETURN; DBUG_RETURN(TRUE);
switch_cs_variables(sql_file, ";", switch_cs_variables(sql_file, ";",
row[3], /* character_set_client */ row[3], /* character_set_client */
...@@ -2695,18 +2787,102 @@ static void dump_triggers_for_table(char *table, char *db_name) ...@@ -2695,18 +2787,102 @@ static void dump_triggers_for_table(char *table, char *db_name)
if (db_cl_altered) if (db_cl_altered)
{ {
if (restore_db_collation(sql_file, 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)); my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
} }
mysql_free_result(res2);
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 int dump_triggers_for_table(char *table_name, char *db_name)
{
char name_buff[NAME_LEN*4+3];
char query_buff[QUERY_LENGTH];
uint old_opt_compatible_mode= opt_compatible_mode;
MYSQL_RES *show_triggers_rs;
MYSQL_ROW row;
char db_cl_name[MY_CS_NAME_SIZE];
DBUG_ENTER("dump_triggers_for_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;
/* 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_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(show_triggers_rs)))
{
my_snprintf(query_buff, sizeof (query_buff),
"SHOW CREATE TRIGGER %s",
quote_name(row[0], name_buff, TRUE));
if (mysql_query(mysql, query_buff))
{
/*
mysqldump is being run against old server, that does not support
SHOW CREATE TRIGGER statement. We should use SHOW TRIGGERS output.
NOTE: the dump may be incorrect, as old SHOW TRIGGERS does not
provide all the necessary information to restore trigger properly.
*/
dump_trigger_old(show_triggers_rs, &row, table_name);
} }
else
{
MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql);
mysql_free_result(result); 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(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
...@@ -37,14 +37,14 @@ set session long_query_time=1; ...@@ -37,14 +37,14 @@ set session long_query_time=1;
select sleep(2); select sleep(2);
sleep(2) sleep(2)
0 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 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 global slow_query_log= ON;
set session long_query_time=1; set session long_query_time=1;
select sleep(2); select sleep(2);
sleep(2) sleep(2)
0 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 start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text
TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 select sleep(2) TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 select sleep(2)
show global variables show global variables
......
...@@ -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
...@@ -28,7 +28,7 @@ connection con1; ...@@ -28,7 +28,7 @@ connection con1;
set session long_query_time=1; set session long_query_time=1;
select sleep(2); select sleep(2);
--replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME --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; connection default;
set global slow_query_log= ON; set global slow_query_log= ON;
...@@ -36,7 +36,7 @@ connection con1; ...@@ -36,7 +36,7 @@ connection con1;
set session long_query_time=1; set session long_query_time=1;
select sleep(2); select sleep(2);
--replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME --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; connection default;
show global variables show global variables
where Variable_name = 'log' or Variable_name = 'log_slow_queries' or where Variable_name = 'log' or Variable_name = 'log_slow_queries' or
......
...@@ -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);
} }
......
...@@ -1705,7 +1705,7 @@ void Item_ident_for_show::make_field(Send_field *tmp_field) ...@@ -1705,7 +1705,7 @@ void Item_ident_for_show::make_field(Send_field *tmp_field)
tmp_field->type=field->type(); tmp_field->type=field->type();
tmp_field->flags= field->table->maybe_null ? tmp_field->flags= field->table->maybe_null ?
(field->flags & ~NOT_NULL_FLAG) : field->flags; (field->flags & ~NOT_NULL_FLAG) : field->flags;
tmp_field->decimals= 0; tmp_field->decimals= field->decimals();
} }
/**********************************************/ /**********************************************/
......
...@@ -2484,6 +2484,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) ...@@ -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->row_type= share->row_type;
create_info->default_table_charset= share->table_charset; create_info->default_table_charset= share->table_charset;
create_info->table_charset= 0; create_info->table_charset= 0;
create_info->comment= share->comment;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -16077,7 +16077,6 @@ static void test_bug24179() ...@@ -16077,7 +16077,6 @@ static void test_bug24179()
/* /*
Bug#28075 "COM_DEBUG crashes mysqld" Bug#28075 "COM_DEBUG crashes mysqld"
Note: Test disabled because of failure in PushBuild.
*/ */
static void test_bug28075() static void test_bug28075()
...@@ -16106,7 +16105,7 @@ static void test_bug27876() ...@@ -16106,7 +16105,7 @@ static void test_bug27876()
int rc; int rc;
MYSQL_RES *result; MYSQL_RES *result;
char utf8_func[] = unsigned char utf8_func[] =
{ {
0xd1, 0x84, 0xd1, 0x83, 0xd0, 0xbd, 0xd0, 0xba, 0xd1, 0x84, 0xd1, 0x83, 0xd0, 0xbd, 0xd0, 0xba,
0xd1, 0x86, 0xd0, 0xb8, 0xd0, 0xb9, 0xd0, 0xba, 0xd1, 0x86, 0xd0, 0xb8, 0xd0, 0xb9, 0xd0, 0xba,
...@@ -16114,7 +16113,7 @@ static void test_bug27876() ...@@ -16114,7 +16113,7 @@ static void test_bug27876()
0x00 0x00
}; };
char utf8_param[] = unsigned char utf8_param[] =
{ {
0xd0, 0xbf, 0xd0, 0xb0, 0xd1, 0x80, 0xd0, 0xb0, 0xd0, 0xbf, 0xd0, 0xb0, 0xd1, 0x80, 0xd0, 0xb0,
0xd0, 0xbc, 0xd0, 0xb5, 0xd1, 0x82, 0xd1, 0x8a, 0xd0, 0xbc, 0xd0, 0xb5, 0xd1, 0x82, 0xd1, 0x8a,
...@@ -16334,7 +16333,54 @@ static void test_bug29692() ...@@ -16334,7 +16333,54 @@ static void test_bug29692()
mysql_close(conn); 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 Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -16626,6 +16672,7 @@ static struct my_tests_st my_tests[]= { ...@@ -16626,6 +16672,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug27592", test_bug27592 }, { "test_bug27592", test_bug27592 },
{ "test_bug29687", test_bug29687 }, { "test_bug29687", test_bug29687 },
{ "test_bug29692", test_bug29692 }, { "test_bug29692", test_bug29692 },
{ "test_bug29306", test_bug29306 },
{ 0, 0 } { 0, 0 }
}; };
......
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