summaryrefslogtreecommitdiff
path: root/client/mysqldump.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysqldump.c')
-rw-r--r--client/mysqldump.c295
1 files changed, 233 insertions, 62 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 907b6233590..5705571777a 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -57,6 +57,7 @@
#define EX_CONSCHECK 3
#define EX_EOM 4
#define EX_EOF 5 /* ferror for output file was got */
+#define EX_ILLEGAL_TABLE 6
/* index into 'show fields from table' */
@@ -142,14 +143,6 @@ const char *compatible_mode_names[]=
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
"", compatible_mode_names, NULL};
-#define TABLE_RULE_HASH_SIZE 16
-
-typedef struct st_table_rule_ent
-{
- char* key; /* dbname.tablename */
- uint key_len;
-} TABLE_RULE_ENT;
-
HASH ignore_table;
static struct my_option my_long_options[] =
@@ -476,7 +469,10 @@ static void write_header(FILE *sql_file, char *db_name)
if (opt_xml)
{
fputs("<?xml version=\"1.0\"?>\n", sql_file);
- fputs("<mysqldump>\n", sql_file);
+ fputs("<mysqldump ", sql_file);
+ fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
+ sql_file);
+ fputs(">\n", sql_file);
check_io(sql_file);
}
else if (!opt_compact)
@@ -543,30 +539,29 @@ static void write_footer(FILE *sql_file)
}
} /* write_footer */
+static void free_table_ent(char *key)
-static void free_table_ent(TABLE_RULE_ENT* e)
{
- my_free((gptr) e, MYF(0));
+ my_free((gptr) key, MYF(0));
}
-static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
- my_bool not_used __attribute__((unused)))
+byte* get_table_key(const char *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
{
- *len= e->key_len;
- return (byte*)e->key;
+ *length= strlen(entry);
+ return (byte*) entry;
}
void init_table_rule_hash(HASH* h)
{
- if(hash_init(h, charset_info, TABLE_RULE_HASH_SIZE, 0, 0,
- (hash_get_key) get_table_key,
- (hash_free_key) free_table_ent, 0))
+ if (hash_init(h, charset_info, 16, 0, 0,
+ (hash_get_key) get_table_key,
+ (hash_free_key) free_table_ent, 0))
exit(EX_EOM);
}
-
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -639,25 +634,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case (int) OPT_IGNORE_TABLE:
{
- uint len= (uint)strlen(argument);
- TABLE_RULE_ENT* e;
if (!strchr(argument, '.'))
{
fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
exit(1);
}
- /* len is always > 0 because we know the there exists a '.' */
- e= (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT) + len, MYF(MY_WME));
- if (!e)
- exit(EX_EOM);
- e->key= (char*)e + sizeof(TABLE_RULE_ENT);
- e->key_len= len;
- memcpy(e->key, argument, len);
-
if (!hash_inited(&ignore_table))
init_table_rule_hash(&ignore_table);
- if(my_hash_insert(&ignore_table, (byte*)e))
+ if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
exit(EX_EOM);
break;
}
@@ -828,7 +813,8 @@ static void DB_error(MYSQL *mysql, const char *when)
SYNOPSIS
mysql_query_with_error_report()
mysql_con connection to use
- res if non zero, result will be put there with mysql_store_result
+ res if non zero, result will be put there with
+ mysql_store_result()
query query to send to server
RETURN VALUES
@@ -981,14 +967,41 @@ static char *quote_name(const char *name, char *buff, my_bool force)
} /* quote_name */
+/*
+ Quote a table name so it can be used in "SHOW TABLES LIKE <tabname>"
+
+ SYNOPSIS
+ quote_for_like()
+ name name of the table
+ buff quoted name of the table
+
+ DESCRIPTION
+ Quote \, _, ' and % characters
+
+ Note: Because MySQL uses the C escape syntax in strings
+ (for example, '\n' to represent newline), you must double
+ any '\' that you use in your LIKE strings. For example, to
+ search for '\n', specify it as '\\n'. To search for '\', specify
+ it as '\\\\' (the backslashes are stripped once by the parser
+ and another time when the pattern match is done, leaving a
+ single backslash to be matched).
+
+ Example: "t\1" => "t\\\\1"
+*/
static char *quote_for_like(const char *name, char *buff)
{
char *to= buff;
*to++= '\'';
while (*name)
{
- if (*name == '\'' || *name == '_' || *name == '\\' || *name == '%')
+ if (*name == '\\')
+ {
+ *to++='\\';
+ *to++='\\';
+ *to++='\\';
+ }
+ else if (*name == '\'' || *name == '_' || *name == '%')
*to++= '\\';
*to++= *name++;
}
@@ -1074,6 +1087,40 @@ static void print_xml_tag1(FILE * xml_file, const char* sbeg,
/*
+ Print xml tag with for a field that is null
+
+ SYNOPSIS
+ print_xml_null_tag()
+ xml_file - output file
+ sbeg - line beginning
+ stag_atr - tag and attribute
+ sval - value of attribute
+ send - line ending
+
+ DESCRIPTION
+ Print tag with one attribute to the xml_file. Format is:
+ <stag_atr="sval" xsi:nil="true"/>
+ NOTE
+ sval MUST be a NULL terminated string.
+ sval string will be qouted before output.
+*/
+
+static void print_xml_null_tag(FILE * xml_file, const char* sbeg,
+ const char* stag_atr, const char* sval,
+ const char* send)
+{
+ fputs(sbeg, xml_file);
+ fputs("<", xml_file);
+ fputs(stag_atr, xml_file);
+ fputs("\"", xml_file);
+ print_quoted_xml(xml_file, sval, strlen(sval));
+ fputs("\" xsi:nil=\"true\" />", xml_file);
+ fputs(send, xml_file);
+ check_io(xml_file);
+}
+
+
+/*
Print xml tag with many attributes.
SYNOPSIS
@@ -1139,6 +1186,7 @@ static uint get_table_structure(char *table, char *db)
FILE *sql_file = md_result_file;
int len;
DBUG_ENTER("get_table_structure");
+ DBUG_PRINT("enter", ("db: %s, table: %s", db, table));
if (!insert_pat_inited)
{
@@ -1212,7 +1260,54 @@ static uint get_table_structure(char *table, char *db)
if (strcmp(field->name, "View") == 0)
{
if (verbose)
- fprintf(stderr, "-- It's a view, skipped\n");
+ fprintf(stderr, "-- It's a view, create dummy table for view\n");
+
+ mysql_free_result(tableRes);
+
+ /* Create a dummy table for the view. ie. a table which has the
+ same columns as the view should have. This table is dropped
+ just before the view is created. The table is used to handle the
+ case where a view references another view, which hasn't yet been
+ created(during the load of the dump). BUG#10927 */
+
+ /* Create temp table by selecting from the view */
+ my_snprintf(query_buff, sizeof(query_buff),
+ "CREATE TEMPORARY TABLE %s SELECT * FROM %s WHERE 0",
+ result_table, result_table);
+ if (mysql_query_with_error_report(sock, 0, query_buff))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+
+ /* Get CREATE statement for the temp table */
+ my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE TABLE %s",
+ result_table);
+ if (mysql_query_with_error_report(sock, 0, query_buff))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
+ tableRes= mysql_store_result(sock);
+ row= mysql_fetch_row(tableRes);
+
+ if (opt_drop)
+ fprintf(sql_file, "DROP VIEW IF EXISTS %s;\n",opt_quoted_table);
+
+ /* Print CREATE statement but remove TEMPORARY */
+ fprintf(sql_file, "CREATE %s;\n", row[1]+17);
+ check_io(sql_file);
+
+ mysql_free_result(tableRes);
+
+ /* Drop the temp table */
+ my_snprintf(buff, sizeof(buff),
+ "DROP TEMPORARY TABLE %s", result_table);
+ if (mysql_query_with_error_report(sock, 0, buff))
+ {
+ safe_exit(EX_MYSQLERR);
+ DBUG_RETURN(0);
+ }
was_views= 1;
DBUG_RETURN(0);
}
@@ -1592,6 +1687,26 @@ static void dump_table(uint numFields, char *table)
const char *table_type;
int error= 0;
+ /* Check --no-data flag */
+ if (dFlag)
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping dump data for table '%s', --no-data was used\n",
+ table);
+ return;
+ }
+
+ /* Check that there are any fields in the table */
+ if (numFields == 0)
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping dump data for table '%s', it has no fields\n",
+ table);
+ return;
+ }
+
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
@@ -1912,7 +2027,14 @@ static void dump_table(uint numFields, char *table)
}
}
else
- fputs("NULL", md_result_file);
+ {
+ /* The field value is NULL */
+ if (!opt_xml)
+ fputs("NULL", md_result_file);
+ else
+ print_xml_null_tag(md_result_file, "\t\t", "field name=",
+ field->name, "\n");
+ }
check_io(md_result_file);
}
}
@@ -2201,8 +2323,7 @@ static int dump_all_tables_in_db(char *database)
if (include_table(hash_key, end - hash_key))
{
numrows = get_table_structure(table, database);
- if (!dFlag && numrows > 0)
- dump_table(numrows,table);
+ dump_table(numrows,table);
my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
order_by= 0;
}
@@ -2327,27 +2448,61 @@ static int get_actual_table_name(const char *old_table_name,
static int dump_selected_tables(char *db, char **table_names, int tables)
{
- uint numrows;
- int i;
+ uint numrows, i;
char table_buff[NAME_LEN*+3];
+ char new_table_name[NAME_LEN];
+ DYNAMIC_STRING lock_tables_query;
+ HASH dump_tables;
+ char *table_name;
+ DBUG_ENTER("dump_selected_tables");
if (init_dumping(db))
return 1;
- if (lock_tables)
+
+ /* Init hash table for storing the actual name of tables to dump */
+ if (hash_init(&dump_tables, charset_info, 16, 0, 0,
+ (hash_get_key) get_table_key, (hash_free_key) free_table_ent,
+ 0))
+ exit(EX_EOM);
+
+ init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
+ for (; tables > 0 ; tables-- , table_names++)
{
- DYNAMIC_STRING query;
+ /* the table name passed on commandline may be wrong case */
+ if (!get_actual_table_name(*table_names,
+ new_table_name, sizeof(new_table_name)))
+ {
+ /* Add found table name to lock_tables_query */
+ if (lock_tables)
+ {
+ dynstr_append(&lock_tables_query,
+ quote_name(new_table_name, table_buff, 1));
+ dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
+ }
- init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
- for (i=0 ; i < tables ; i++)
+ /* Add found table name to dump_tables list */
+ if (my_hash_insert(&dump_tables,
+ (byte*)my_strdup(new_table_name, MYF(0))))
+ exit(EX_EOM);
+
+ }
+ else
{
- dynstr_append(&query, quote_name(table_names[i], table_buff, 1));
- dynstr_append(&query, " READ /*!32311 LOCAL */,");
+ my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0),
+ *table_names);
+ safe_exit(EX_ILLEGAL_TABLE);
+ /* We shall countinue here, if --force was given */
}
- if (mysql_real_query(sock, query.str, query.length-1))
+ }
+
+ if (lock_tables)
+ {
+ if (mysql_real_query(sock, lock_tables_query.str,
+ lock_tables_query.length-1))
DB_error(sock, "when doing LOCK TABLES");
/* We shall countinue here, if --force was given */
- dynstr_free(&query);
}
+ dynstr_free(&lock_tables_query);
if (flush_logs)
{
if (mysql_refresh(sock, REFRESH_LOG))
@@ -2356,25 +2511,28 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
if (opt_xml)
print_xml_tag1(md_result_file, "", "database name=", db, "\n");
- for (i=0 ; i < tables ; i++)
- {
- char new_table_name[NAME_LEN];
- /* the table name passed on commandline may be wrong case */
- if (!get_actual_table_name( table_names[i], new_table_name,
- sizeof(new_table_name)))
- {
- numrows= get_table_structure(new_table_name, db);
- dump_table(numrows, new_table_name);
- }
- my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
- order_by= 0;
+ /* Dump each selected table */
+ for (i= 0; i < dump_tables.records; i++)
+ {
+ table_name= hash_element(&dump_tables, i);
+ DBUG_PRINT("info",("Dumping table %s", table_name));
+ numrows= get_table_structure(table_name, db);
+ dump_table(numrows, table_name);
}
+
+ /* Dump each selected view */
if (was_views)
{
- for (i=0 ; i < tables ; i++)
- get_view_structure(table_names[i], db);
+ for(i=0; i < dump_tables.records; i++)
+ {
+ table_name= hash_element(&dump_tables, i);
+ get_view_structure(table_name, db);
+ }
}
+ hash_free(&dump_tables);
+ my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
+ order_by= 0;
if (opt_xml)
{
fputs("</database>\n", md_result_file);
@@ -2382,7 +2540,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
if (lock_tables)
mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
- return 0;
+ DBUG_RETURN(0);
} /* dump_selected_tables */
@@ -2403,6 +2561,7 @@ static int do_show_master_status(MYSQL *mysql_con)
row = mysql_fetch_row(master);
if (row && row[0] && row[1])
{
+ /* SHOW MASTER STATUS reports file and position */
if (opt_comments)
fprintf(md_result_file,
"\n--\n-- Position to start replication or point-in-time "
@@ -2412,6 +2571,14 @@ static int do_show_master_status(MYSQL *mysql_con)
comment_prefix, row[0], row[1]);
check_io(md_result_file);
}
+ else if (!ignore_errors)
+ {
+ /* SHOW MASTER STATUS reports nothing and --force is not enabled */
+ my_printf_error(0, "Error: Binlogging on server not active",
+ MYF(0), mysql_error(mysql_con));
+ mysql_free_result(master);
+ return 1;
+ }
mysql_free_result(master);
}
return 0;
@@ -2752,6 +2919,7 @@ static my_bool get_view_structure(char *table, char* db)
}
if (opt_drop)
{
+ fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
fprintf(sql_file, "DROP VIEW IF EXISTS %s;\n", opt_quoted_table);
check_io(sql_file);
}
@@ -2775,8 +2943,9 @@ int main(int argc, char **argv)
{
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
+ bzero((char*) &ignore_table, sizeof(ignore_table));
- MY_INIT(argv[0]);
+ MY_INIT("mysqldump");
if (get_options(&argc, &argv))
{
my_end(0);
@@ -2833,6 +3002,8 @@ err:
if (md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ if (hash_inited(&ignore_table))
+ hash_free(&ignore_table);
if (extended_insert)
dynstr_free(&extended_row);
if (insert_pat_inited)