in client/mysqldump.c [4042:4701]
static void dump_table(char *table, char *db)
{
char ignore_flag;
char buf[200], table_buff[NAME_LEN+3];
DYNAMIC_STRING query_string;
DYNAMIC_STRING explain_query_string;
DYNAMIC_STRING extended_row;
char table_type[NAME_LEN];
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
int error= 0;
ulong rownr, row_break, total_length, init_length, row_length;
TYPE_STAT *bucket;
my_bool gather_stats= 0;
uint num_fields;
uint stat_field_offset= 0;
field_type_t stat_field_type= FBOBJ;
MYSQL_RES *res = NULL;
MYSQL_FIELD *field;
MYSQL_ROW row;
ha_checksum crc= 0;
DBUG_ENTER("dump_table");
/*
Make sure you get the create table info before the following check for
--no-data flag below. Otherwise, the create table info won't be printed.
*/
num_fields= get_table_structure(table, db, table_type, &ignore_flag);
/*
The "table" could be a view. If so, we don't do anything here.
*/
if (strcmp(table_type, "VIEW") == 0)
DBUG_VOID_RETURN;
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
/* Check --no-data flag */
if (opt_no_data)
{
verbose_msg("-- Skipping dump data for table '%s', --no-data was used\n",
table);
restore_secondary_keys(opt_quoted_table);
DBUG_VOID_RETURN;
}
DBUG_PRINT("info",
("ignore_flag: %x num_fields: %d", (int) ignore_flag,
num_fields));
/*
If the table type is a merge table or any type that has to be
_completely_ ignored and no data dumped
*/
if (ignore_flag & IGNORE_DATA)
{
verbose_msg("-- Warning: Skipping data for table '%s' because " \
"it's of type %s\n", table, table_type);
DBUG_VOID_RETURN;
}
/* Check that there are any fields in the table */
if (num_fields == 0)
{
verbose_msg("-- Skipping dump data for table '%s', it has no fields\n",
table);
DBUG_VOID_RETURN;
}
/*
Dump stats for fbobj_*, fbid, the top hashout and assoc_* tables, but
excluding assoc_count and assoc_info_queue.
*/
if (opt_dump_fbobj_assoc_stats) {
if (strncmp(table, "fbobj_", 6) == 0) {
gather_stats= 1;
stat_field_offset= FBOBJ_FBTYPE_FIELD;
stat_field_type= FBOBJ;
}
else if (strncmp(table, "assoc_", 6) == 0
&& (strcmp(table, "assoc_count") != 0)
&& (strcmp(table, "assoc_info_queue") != 0)) {
gather_stats= 1;
stat_field_offset= ASSOC_TYPE_FIELD;
stat_field_type= ASSOC;
}
else if (strcmp(table, "fbid") == 0) {
gather_stats= 1;
stat_field_offset= FBID_FBTYPE_FIELD;
stat_field_type= FBID;
}
else if (strcmp(table, "hashout_short_url") == 0
|| (strcmp(table, "hashout") == 0)
|| (strcmp(table, "hashout_xid_crow") == 0)
|| (strcmp(table, "hashout_xid") == 0)
|| (strcmp(table, "hashout_udid") == 0)) {
gather_stats= 1;
stat_field_offset= HASHOUT_APP_ID_FIELD;
stat_field_type= HASHOUT;
}
/* Protect against new tables that may not have the right schema. */
if (num_fields < stat_field_offset) {
gather_stats= 0;
fprintf(fbobj_assoc_stats_file, "-- Bad schema for: %s\n", table);
}
}
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
verbose_msg("-- Sending SELECT query...\n");
init_dynamic_string_checked(&query_string, "", 1024, 1024);
if (extended_insert)
init_dynamic_string_checked(&extended_row, "", 1024, 1024);
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
/*
Convert the path to native os format
and resolve to the full filepath.
*/
convert_dirname(tmp_path,path,NullS);
my_load_path(tmp_path, tmp_path, NULL);
fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME | MY_APPEND_EXT));
/* Must delete the file that 'INTO OUTFILE' will write to */
my_delete(filename, MYF(0));
/* convert to a unix path name to stick into the query */
to_unix_path(filename);
/* now build the query string */
dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ ");
if (server_supports_sql_no_fcache)
{
dynstr_append_checked(&query_string, "/*!50084 SQL_NO_FCACHE */ ");
}
dynstr_append_checked(&query_string, "* INTO OUTFILE '");
dynstr_append_checked(&query_string, filename);
dynstr_append_checked(&query_string, "'");
dynstr_append_checked(&query_string, " /*!50138 CHARACTER SET ");
dynstr_append_checked(&query_string, default_charset == mysql_universal_client_charset ?
my_charset_bin.name : /* backward compatibility */
default_charset);
dynstr_append_checked(&query_string, " */");
if (fields_terminated || enclosed || opt_enclosed || escaped)
dynstr_append_checked(&query_string, " FIELDS");
add_load_option(&query_string, " TERMINATED BY ", fields_terminated);
add_load_option(&query_string, " ENCLOSED BY ", enclosed);
add_load_option(&query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
add_load_option(&query_string, " ESCAPED BY ", escaped);
add_load_option(&query_string, " LINES TERMINATED BY ", lines_terminated);
dynstr_append_checked(&query_string, " FROM ");
dynstr_append_checked(&query_string, result_table);
if (where)
{
dynstr_append_checked(&query_string, " WHERE ");
dynstr_append_checked(&query_string, where);
}
if (order_by)
{
dynstr_append_checked(&query_string, " ORDER BY ");
dynstr_append_checked(&query_string, order_by);
}
struct compress_context *compress_ctx = NULL;
if (do_compress)
compress_ctx = start_pipe_and_compress_output(
filename, opt_compression_chunk_size, table);
if (mysql_real_query(mysql, query_string.str, query_string.length))
{
DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
dynstr_free(&query_string);
DBUG_VOID_RETURN;
}
if (do_compress)
finish_pipe_and_compress_output(compress_ctx);
}
else
{
print_comment(md_result_file, 0,
"\n--\n-- Dumping data for table %s\n--\n",
result_table);
dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ ");
if (server_supports_sql_no_fcache)
{
dynstr_append_checked(&query_string, "/*!50084 SQL_NO_FCACHE */ ");
}
dynstr_append_checked(&query_string, "* FROM ");
dynstr_append_checked(&query_string, result_table);
if (where)
{
print_comment(md_result_file, 0, "-- WHERE: %s\n", where);
dynstr_append_checked(&query_string, " WHERE ");
dynstr_append_checked(&query_string, where);
}
if (order_by)
{
print_comment(md_result_file, 0, "-- ORDER BY: %s\n", order_by);
dynstr_append_checked(&query_string, " ORDER BY ");
dynstr_append_checked(&query_string, order_by);
}
if (opt_print_ordering_key)
{
init_dynamic_string_checked(&explain_query_string, "EXPLAIN ", 1024, 1024);
dynstr_append_checked(&explain_query_string, query_string.str);
if (mysql_query(mysql, explain_query_string.str) ||
!(res = mysql_store_result(mysql)) ||
!(row = mysql_fetch_row(res)))
{
if(res)
mysql_free_result(res);
dynstr_free(&explain_query_string);
DB_error(mysql, "when trying to save the result of EXPLAIN SELECT *.");
goto err;
}
fprintf(md_result_file, "/* ORDERING KEY%s : %s */;\n",
opt_order_by_primary_desc ? " (DESC)" : "", row[5]);
if(res)
mysql_free_result(res);
dynstr_free(&explain_query_string);
}
if (!opt_xml && !opt_compact)
{
fputs("\n", md_result_file);
check_io(md_result_file);
}
if (mysql_query_with_error_report(mysql, 0, query_string.str))
{
DB_error(mysql, "when retrieving data from server");
goto err;
}
if (quick)
res=mysql_use_result(mysql);
else
res=mysql_store_result(mysql);
if (!res)
{
DB_error(mysql, "when retrieving data from server");
goto err;
}
verbose_msg("-- Retrieving rows...\n");
if (mysql_num_fields(res) != num_fields)
{
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
my_progname, result_table);
error= EX_CONSCHECK;
goto err;
}
if (opt_lock)
{
fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
check_io(md_result_file);
}
/* Moved disable keys to after lock per bug 15977 */
if (opt_disable_keys)
{
fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
opt_quoted_table);
check_io(md_result_file);
}
total_length= opt_net_buffer_length; /* Force row break */
row_break=0;
rownr=0;
init_length=(uint) insert_pat.length+4;
if (opt_xml)
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
NullS);
if (opt_autocommit)
{
fprintf(md_result_file, "set autocommit=0;\n");
check_io(md_result_file);
}
while ((row= mysql_fetch_row(res)))
{
ha_checksum row_crc= 0;
uint i;
ulong *lengths= mysql_fetch_lengths(res);
uint num_columns= mysql_num_fields(res);
rownr++;
if (gather_stats) {
row_length= 0;
for (i= 0; i < mysql_num_fields(res); i++)
row_length += lengths[i];
/* For fbid table, concatenate is_deleted to type*/
if (stat_field_type == FBID) {
if (num_columns <= FBID_IS_DELETED_FIELD) {
fprintf(fbobj_assoc_stats_file,
"-- FBID table has less than 5 columns.\n");
} else {
char type[(strlen(row[stat_field_offset]) +
strlen(row[FBID_IS_DELETED_FIELD])) + 1];
strcpy(type, row[stat_field_offset]);
strcat(type, row[FBID_IS_DELETED_FIELD]);
uint length= (lengths[stat_field_offset] +
lengths[FBID_IS_DELETED_FIELD]);
bucket= (TYPE_STAT*)my_hash_search(&fbobj_assoc_stats,
(uchar*)type,
length);
if (!bucket) {
bucket= (TYPE_STAT*) malloc(sizeof(TYPE_STAT));
bucket->type= (uchar*)my_strdup(type,MYF(MY_FAE));
bucket->type_len= length;
bucket->count= 0;
bucket->space= 0;
bucket->field_type= stat_field_type;
my_hash_insert(&fbobj_assoc_stats,(uchar*) bucket);
}
bucket->count++;
bucket->space += row_length;
}
} else {
if (num_columns <= stat_field_offset) {
fprintf(fbobj_assoc_stats_file,
"-- %s table has less than %d columns.\n",
table, stat_field_offset+1);
} else {
bucket= (TYPE_STAT*)my_hash_search(&fbobj_assoc_stats,
(uchar*)row[stat_field_offset],
lengths[stat_field_offset]);
if (!bucket) {
bucket= (TYPE_STAT*) malloc(sizeof(TYPE_STAT));
bucket->type= (uchar*)my_strdup(row[stat_field_offset],
MYF(MY_FAE));
bucket->type_len= lengths[stat_field_offset];
bucket->count= 0;
bucket->space= 0;
bucket->field_type= stat_field_type;
my_hash_insert(&fbobj_assoc_stats,(uchar*) bucket);
}
bucket->count++;
bucket->space += row_length;
}
}
}
if (!extended_insert && !opt_xml)
{
fputs(insert_pat.str,md_result_file);
check_io(md_result_file);
}
mysql_field_seek(res,0);
if (opt_xml)
{
fputs("\t<row>\n", md_result_file);
check_io(md_result_file);
}
for (i= 0; i < mysql_num_fields(res); i++)
{
int is_blob;
ulong length= lengths[i];
if (row[i] && opt_enable_checksum_table)
{
row_crc= my_checksum(row_crc, (uchar *)row[i], length);
}
if (!(field= mysql_fetch_field(res)))
die(EX_CONSCHECK,
"Not enough fields from table %s! Aborting.\n",
result_table);
/*
63 is my_charset_bin. If charsetnr is not 63,
we have not a BLOB but a TEXT column.
we'll dump in hex only BLOB columns.
*/
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
(field->type == MYSQL_TYPE_BIT ||
field->type == MYSQL_TYPE_STRING ||
field->type == MYSQL_TYPE_VAR_STRING ||
field->type == MYSQL_TYPE_VARCHAR ||
field->type == MYSQL_TYPE_BLOB ||
field->type == MYSQL_TYPE_LONG_BLOB ||
field->type == MYSQL_TYPE_MEDIUM_BLOB ||
field->type == MYSQL_TYPE_TINY_BLOB ||
field->type == MYSQL_TYPE_GEOMETRY)) ? 1 : 0;
if (extended_insert && !opt_xml)
{
if (i == 0)
dynstr_set_checked(&extended_row,"(");
else
dynstr_append_checked(&extended_row,",");
if (row[i])
{
if (length)
{
if (!(field->flags & NUM_FLAG))
{
/*
"length * 2 + 2" is OK for both HEX and non-HEX modes:
- In HEX mode we need exactly 2 bytes per character
plus 2 bytes for '0x' prefix.
- In non-HEX mode we need up to 2 bytes per character,
plus 2 bytes for leading and trailing '\'' characters.
Also we need to reserve 1 byte for terminating '\0'.
*/
dynstr_realloc_checked(&extended_row,length * 2 + 2 + 1);
if (opt_hex_blob && is_blob)
{
dynstr_append_checked(&extended_row, "0x");
extended_row.length+= mysql_hex_string(extended_row.str +
extended_row.length,
row[i], length);
DBUG_ASSERT(extended_row.length+1 <= extended_row.max_length);
/* mysql_hex_string() already terminated string by '\0' */
DBUG_ASSERT(extended_row.str[extended_row.length] == '\0');
}
else
{
dynstr_append_checked(&extended_row,"'");
extended_row.length +=
mysql_real_escape_string(&mysql_connection,
&extended_row.str[extended_row.length],
row[i],length);
extended_row.str[extended_row.length]='\0';
dynstr_append_checked(&extended_row,"'");
}
}
else
{
/* change any strings ("inf", "-inf", "nan") into NULL */
char *ptr= row[i];
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
my_isalpha(charset_info, ptr[1])))
dynstr_append_checked(&extended_row, "NULL");
else
{
if (field->type == MYSQL_TYPE_DECIMAL)
{
/* add " signs around */
dynstr_append_checked(&extended_row, "'");
dynstr_append_checked(&extended_row, ptr);
dynstr_append_checked(&extended_row, "'");
}
else
dynstr_append_checked(&extended_row, ptr);
}
}
}
else
dynstr_append_checked(&extended_row,"''");
}
else
dynstr_append_checked(&extended_row,"NULL");
}
else
{
if (i && !opt_xml)
{
fputc(',', md_result_file);
check_io(md_result_file);
}
if (row[i])
{
if (!(field->flags & NUM_FLAG))
{
if (opt_xml)
{
if (opt_hex_blob && is_blob && length)
{
/* Define xsi:type="xs:hexBinary" for hex encoded data */
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
field->name, "xsi:type=", "xs:hexBinary", NullS);
print_blob_as_hex(md_result_file, row[i], length);
}
else
{
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
field->name, NullS);
print_quoted_xml(md_result_file, row[i], length, 0);
}
fputs("</field>\n", md_result_file);
}
else if (opt_hex_blob && is_blob && length)
{
fputs("0x", md_result_file);
print_blob_as_hex(md_result_file, row[i], length);
}
else
unescape(md_result_file, row[i], length);
}
else
{
/* change any strings ("inf", "-inf", "nan") into NULL */
char *ptr= row[i];
if (opt_xml)
{
print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
field->name, NullS);
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
md_result_file);
fputs("</field>\n", md_result_file);
}
else if (my_isalpha(charset_info, *ptr) ||
(*ptr == '-' && my_isalpha(charset_info, ptr[1])))
fputs("NULL", md_result_file);
else if (field->type == MYSQL_TYPE_DECIMAL)
{
/* add " signs around */
fputc('\'', md_result_file);
fputs(ptr, md_result_file);
fputc('\'', md_result_file);
}
else
fputs(ptr, md_result_file);
}
}
else
{
/* 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);
}
}
if (opt_xml)
{
fputs("\t</row>\n", md_result_file);
check_io(md_result_file);
}
if (extended_insert)
{
ulong row_length;
dynstr_append_checked(&extended_row,")");
row_length= 2 + extended_row.length;
if (total_length + row_length < opt_net_buffer_length)
{
total_length+= row_length;
fputc(',',md_result_file); /* Always row break */
fputs(extended_row.str,md_result_file);
}
else
{
if (row_break)
fputs(";\n", md_result_file);
row_break=1; /* This is first row */
fputs(insert_pat.str,md_result_file);
fputs(extended_row.str,md_result_file);
total_length= row_length+init_length;
}
check_io(md_result_file);
}
else if (!opt_xml)
{
fputs(");\n", md_result_file);
check_io(md_result_file);
}
if (opt_enable_checksum_table)
{
// Cumulate the crc for the table
crc+= row_crc;
}
}
if (gather_stats) {
TYPE_STAT* stat;
fprintf(fbobj_assoc_stats_file, "-- Dumping FBObj/Assoc/Fbid/Hashout "
"stats for: %s\n", table);
for (uint i= 0; i < fbobj_assoc_stats.records; i++) {
stat= (TYPE_STAT*) my_hash_element(&fbobj_assoc_stats, i);
fprintf(fbobj_assoc_stats_file,"%d\t%s\t%lu\t%lu\n",
stat->field_type, stat->type, stat->count, stat->space);
}
my_hash_reset(&fbobj_assoc_stats);
}
/* XML - close table tag and supress regular output */
if (opt_xml)
fputs("\t</table_data>\n", md_result_file);
else if (extended_insert && row_break)
fputs(";\n", md_result_file); /* If not empty table */
fflush(md_result_file);
check_io(md_result_file);
if (mysql_errno(mysql))
{
my_snprintf(buf, sizeof(buf),
"%s: Error %d: %s when dumping table %s at row: %ld\n",
my_progname,
mysql_errno(mysql),
mysql_error(mysql),
result_table,
rownr);
fputs(buf,stderr);
error= EX_CONSCHECK;
goto err;
}
restore_secondary_keys(opt_quoted_table);
/* Moved enable keys to before unlock per bug 15977 */
if (opt_disable_keys)
{
fprintf(md_result_file,"/*!40000 ALTER TABLE %s ENABLE KEYS */;\n",
opt_quoted_table);
check_io(md_result_file);
}
if (opt_lock)
{
fputs("UNLOCK TABLES;\n", md_result_file);
check_io(md_result_file);
}
if (opt_autocommit)
{
fprintf(md_result_file, "commit;\n");
check_io(md_result_file);
}
mysql_free_result(res);
print_comment(md_result_file, 0,
"\n--\n-- Rows found for %s: %lu\n--\n",
table, rownr);
if (opt_enable_checksum_table)
{
print_comment(md_result_file, 0,
"\n--\n-- Checksum for %s: %u\n--\n\n",
table,
crc);
}
}
dynstr_free(&query_string);
if (extended_insert)
dynstr_free(&extended_row);
DBUG_VOID_RETURN;
err:
dynstr_free(&query_string);
if (extended_insert)
dynstr_free(&extended_row);
maybe_exit(error);
DBUG_VOID_RETURN;
} /* dump_table */