Skip to content

Commit c23e205

Browse files
Alexey Botchkovvuvova
authored andcommitted
MDEV-21376 mysqldump should support wildcards.
Now --wildcards (-L) option is supported by mysqldump. So user can specify patterns for database names or table names to dump.
1 parent 6dd3dec commit c23e205

File tree

3 files changed

+1233
-40
lines changed

3 files changed

+1233
-40
lines changed

client/mysqldump.cc

Lines changed: 232 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_m
133133
opt_events= 0, opt_comments_used= 0,
134134
opt_alltspcs=0, opt_notspcs= 0, opt_logging,
135135
opt_header=0, opt_update_history= 0,
136-
opt_drop_trigger= 0, opt_dump_history= 0;
136+
opt_drop_trigger= 0, opt_dump_history= 0, opt_wildcards= 0;
137137
#define OPT_SYSTEM_ALL 1
138138
#define OPT_SYSTEM_USERS 2
139139
#define OPT_SYSTEM_PLUGINS 4
@@ -327,8 +327,14 @@ static struct my_option my_long_options[] =
327327
"Include all MariaDB specific create options.",
328328
&create_options, &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
329329
{"databases", 'B',
330-
"Dump several databases. Note the difference in usage; in this case no tables are given. All name arguments are regarded as database names. 'USE db_name;' will be included in the output.",
330+
"Dump several databases. Note the difference in usage; in this case no "
331+
"tables are given. All name arguments are regarded as database names. "
332+
"'USE db_name;' will be included in the output.",
331333
&opt_databases, &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
334+
{"wildcards", 'L', "Usage of wildcards in the table/database name. Without "
335+
"option \"databases\" wildcards are only recognized in table names. "
336+
"With the \"databases\" option - in databases names.",
337+
&opt_wildcards, &opt_wildcards, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
332338
#ifdef DBUG_OFF
333339
{"debug", '#', "This is a non-debug version. Catch this and exit.",
334340
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -441,7 +447,7 @@ static struct my_option my_long_options[] =
441447
{"ignore-database", OPT_IGNORE_DATABASE,
442448
"Do not dump the specified database. To specify more than one database to ignore, "
443449
"use the directive multiple times, once for each database. Only takes effect "
444-
"when used together with --all-databases|-A",
450+
"when used together with --all-databases|-A or --wildcards|-L --databases.",
445451
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
446452
{"ignore-table-data", OPT_IGNORE_DATA,
447453
"Do not dump the specified table data. To specify more than one table "
@@ -1344,10 +1350,11 @@ static int get_options(int *argc, char ***argv)
13441350
my_progname_short);
13451351
return(EX_USAGE);
13461352
}
1347-
if (ignore_database.records && !opt_alldbs)
1353+
if (ignore_database.records && !opt_alldbs && !(opt_wildcards && opt_databases))
13481354
{
13491355
fprintf(stderr,
1350-
"%s: --ignore-database can only be used together with --all-databases.\n",
1356+
"%s: --ignore-database can only be used together with --all-databases"
1357+
" or --wildcards --databases.\n",
13511358
my_progname_short);
13521359
return(EX_USAGE);
13531360
}
@@ -5530,6 +5537,29 @@ static my_bool include_database(const char *hash_key)
55305537
}
55315538

55325539

5540+
/* check database name if it's INFORMATION_SCHEMA or PERFORMANCE_SCHEMA. */
5541+
static bool is_IS_or_PS(const char *schema_name)
5542+
{
5543+
if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
5544+
!cmp_database(schema_name, INFORMATION_SCHEMA_DB_NAME))
5545+
return TRUE;
5546+
5547+
if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
5548+
!cmp_database(schema_name, PERFORMANCE_SCHEMA_DB_NAME))
5549+
return TRUE;
5550+
5551+
return FALSE;
5552+
}
5553+
5554+
5555+
/* check database name if it's SYS_SCHEMA. */
5556+
static bool is_SyS(const char *schema_name)
5557+
{
5558+
return (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION &&
5559+
!cmp_database(schema_name, SYS_SCHEMA_DB_NAME));
5560+
}
5561+
5562+
55335563
static int dump_all_databases()
55345564
{
55355565
MYSQL_ROW row;
@@ -5540,18 +5570,9 @@ static int dump_all_databases()
55405570
return 1;
55415571
while ((row= mysql_fetch_row(tableres)))
55425572
{
5543-
if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
5544-
!cmp_database(row[0], INFORMATION_SCHEMA_DB_NAME))
5545-
continue;
5546-
5547-
if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
5548-
!cmp_database(row[0], PERFORMANCE_SCHEMA_DB_NAME))
5573+
if (is_IS_or_PS(row[0]) || is_SyS(row[0]))
55495574
continue;
55505575

5551-
if (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION &&
5552-
!cmp_database(row[0], SYS_SCHEMA_DB_NAME))
5553-
continue;
5554-
55555576
if (include_database(row[0]))
55565577
if (dump_all_tables_in_db(row[0]))
55575578
result=1;
@@ -5568,16 +5589,7 @@ static int dump_all_databases()
55685589
}
55695590
while ((row= mysql_fetch_row(tableres)))
55705591
{
5571-
if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
5572-
!cmp_database(row[0], INFORMATION_SCHEMA_DB_NAME))
5573-
continue;
5574-
5575-
if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
5576-
!cmp_database(row[0], PERFORMANCE_SCHEMA_DB_NAME))
5577-
continue;
5578-
5579-
if (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION &&
5580-
!cmp_database(row[0], SYS_SCHEMA_DB_NAME))
5592+
if (is_IS_or_PS(row[0]) || is_SyS(row[0]))
55815593
continue;
55825594

55835595
if (include_database(row[0]))
@@ -6185,11 +6197,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
61856197
end= pos;
61866198

61876199
/* Can't LOCK TABLES in I_S / P_S, so don't try. */
6188-
if (lock_tables &&
6189-
!(mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
6190-
!cmp_database(db, INFORMATION_SCHEMA_DB_NAME)) &&
6191-
!(mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
6192-
!cmp_database(db, PERFORMANCE_SCHEMA_DB_NAME)))
6200+
if (lock_tables && !is_IS_or_PS(db))
61936201
{
61946202
if (mysql_real_query(mysql, lock_tables_query.str,
61956203
(ulong)lock_tables_query.length-1))
@@ -7334,6 +7342,175 @@ static void do_print_set_gtid_slave_pos(const char *set_gtid_pos,
73347342
fprintf(md_result_file, "%s", set_gtid_pos);
73357343
}
73367344

7345+
void dump_tables_for_database_wild(const char *db,
7346+
int n_patterns, char **patterns)
7347+
{
7348+
int num;
7349+
int number_of_tables= 0;
7350+
MYSQL_ROW row;
7351+
char *buff, quoted_buf[NAME_LEN*2+3];
7352+
MYSQL_RES *dbinfo;
7353+
char **tables_to_dump;
7354+
/* dbcopy - unquoted db; */
7355+
char dbcopy[2 * NAME_LEN + 30];
7356+
char hash_key[2*NAME_LEN+2]; /* "db.tablename" */
7357+
char *afterdot;
7358+
size_t len;
7359+
size_t buff_size= 108 + (NAME_LEN + 30)*n_patterns;
7360+
7361+
DBUG_ENTER("dump_tables_for_database_wild");
7362+
DBUG_ASSERT(n_patterns > 0);
7363+
7364+
7365+
if (*db == '`')
7366+
{
7367+
len= strlen(db);
7368+
memcpy(dbcopy, db + 1, len - 2);
7369+
dbcopy[len - 2] = 0;
7370+
}
7371+
else
7372+
{
7373+
strncpy(dbcopy, db, NAME_LEN + 1);
7374+
}
7375+
7376+
afterdot= strmov(hash_key, dbcopy);
7377+
*afterdot++= '.';
7378+
7379+
if (!(buff=(char*) my_malloc(PSI_NOT_INSTRUMENTED, buff_size, MYF(MY_WME))))
7380+
die(EX_MYSQLERR, "Couldn't allocate memory");
7381+
7382+
len= my_snprintf(buff, buff_size,
7383+
"SELECT table_name FROM INFORMATION_SCHEMA.TABLES"
7384+
" WHERE table_schema=%s", quote_for_equal(dbcopy, quoted_buf));
7385+
7386+
mysql_real_escape_string(mysql, quoted_buf,
7387+
patterns[0], (ulong)strlen(patterns[0]));
7388+
7389+
len+= my_snprintf(buff+len, buff_size,
7390+
" AND (table_name LIKE '%s'", quoted_buf);
7391+
7392+
for (num=1; num<n_patterns; num++)
7393+
{
7394+
mysql_real_escape_string(mysql, quoted_buf,
7395+
patterns[num], (ulong)strlen(patterns[num]));
7396+
len+= my_snprintf(buff+len, buff_size-len,
7397+
" OR table_name LIKE '%s'", quoted_buf);
7398+
}
7399+
7400+
my_snprintf(buff+len, buff_size-len, ") ORDER BY table_name");
7401+
7402+
if(mysql_query_with_error_report(mysql, &dbinfo, buff))
7403+
{
7404+
fprintf(stderr,
7405+
"%s: Error: '%s' when trying to find tables satisfying pattern\n",
7406+
my_progname_short, mysql_error(mysql));
7407+
goto free_buf_and_exit;
7408+
}
7409+
if (!(tables_to_dump= (char **) my_malloc(
7410+
PSI_NOT_INSTRUMENTED,
7411+
(dbinfo->row_count + (int) 1) * sizeof(char *), MYF(MY_WME))))
7412+
die(EX_MYSQLERR, "Couldn't allocate memory");
7413+
while ((row= mysql_fetch_row(dbinfo)))
7414+
{
7415+
char *end= strmov(afterdot, row[0]);
7416+
if (include_table((uchar*) hash_key,end - hash_key))
7417+
{
7418+
tables_to_dump[number_of_tables++]= row[0];
7419+
}
7420+
}
7421+
tables_to_dump[number_of_tables]= NULL;
7422+
if (number_of_tables > 0)
7423+
{
7424+
if (!opt_alltspcs && !opt_notspcs)
7425+
dump_tablespaces_for_tables(dbcopy, tables_to_dump, number_of_tables);
7426+
dump_selected_tables(dbcopy, tables_to_dump, number_of_tables);
7427+
}
7428+
mysql_free_result(dbinfo);
7429+
my_free(tables_to_dump);
7430+
7431+
free_buf_and_exit:
7432+
my_free(buff);
7433+
DBUG_VOID_RETURN;
7434+
}
7435+
7436+
7437+
/* pattern should be unquoted */
7438+
void dump_databases_wild(int n_patterns, char **db_patterns)
7439+
{
7440+
MYSQL_RES *dbinfo;
7441+
char *qwe_buff;
7442+
size_t qwe_buff_size= (NAME_LEN + 30)*n_patterns + 40;
7443+
size_t qwe_len;
7444+
MYSQL_ROW row;
7445+
int i;
7446+
char **databases_to_dump;
7447+
DBUG_ENTER("dump_databases_wild");
7448+
DBUG_ASSERT(n_patterns > 0);
7449+
7450+
if (!(qwe_buff= (char *) my_malloc(PSI_NOT_INSTRUMENTED,
7451+
qwe_buff_size, MYF(MY_WME))))
7452+
die(EX_MYSQLERR, "Couldn't allocate memory");
7453+
7454+
7455+
qwe_len= my_snprintf(qwe_buff, qwe_buff_size,
7456+
"SHOW DATABASES WHERE Database LIKE '%s'", db_patterns[0]);
7457+
for (i=1; i<n_patterns; i++)
7458+
qwe_len+= my_snprintf(qwe_buff + qwe_len, qwe_buff_size-qwe_len,
7459+
" OR Database LIKE '%s'", db_patterns[i]);
7460+
if (mysql_query_with_error_report(mysql, &dbinfo, qwe_buff))
7461+
{
7462+
fprintf(stderr,
7463+
"%s: Error: '%s' when trying to find databases satisfying pattern\n",
7464+
my_progname_short, mysql_error(mysql));
7465+
goto free_buf_and_exit;
7466+
}
7467+
7468+
if (!(databases_to_dump= (char **) my_malloc(
7469+
PSI_NOT_INSTRUMENTED,
7470+
(dbinfo->row_count + (int) 1) * sizeof(char *), MYF(MY_WME))))
7471+
die(EX_MYSQLERR, "Couldn't allocate memory");
7472+
7473+
i= 0;
7474+
while ((row= mysql_fetch_row(dbinfo)))
7475+
{
7476+
if (is_IS_or_PS(row[0]) || is_SyS(row[0]) || !include_database(row[0]))
7477+
continue;
7478+
7479+
databases_to_dump[i++]= row[0];
7480+
}
7481+
7482+
if (i == 0) /* No database found to dump. */
7483+
{
7484+
fprintf(stderr, "%s: Error: no databases matching the ", my_progname_short);
7485+
7486+
if (n_patterns > 1)
7487+
{
7488+
fprintf(stderr, "patterns ['%s'", db_patterns[0]);
7489+
for (i=1; i<n_patterns-1; i++)
7490+
fprintf(stderr, ", '%s'", db_patterns[i]);
7491+
fprintf(stderr, ", '%s']", db_patterns[i]);
7492+
}
7493+
else
7494+
fprintf(stderr, "pattern '%s'", db_patterns[0]);
7495+
7496+
fprintf(stderr, " found.\n");
7497+
goto free_result_and_exit;
7498+
}
7499+
7500+
databases_to_dump[i]= NULL;
7501+
if (!opt_alltspcs && !opt_notspcs)
7502+
dump_tablespaces_for_databases(databases_to_dump);
7503+
dump_databases(databases_to_dump);
7504+
7505+
free_result_and_exit:
7506+
my_free(databases_to_dump);
7507+
mysql_free_result(dbinfo);
7508+
free_buf_and_exit:
7509+
my_free(qwe_buff);
7510+
DBUG_VOID_RETURN;
7511+
}
7512+
7513+
73377514
int main(int argc, char **argv)
73387515
{
73397516
char bin_log_name[FN_REFLEN];
@@ -7498,19 +7675,34 @@ int main(int argc, char **argv)
74987675
}
74997676
}
75007677

7501-
if (argc > 1 && !opt_databases)
7678+
if (opt_wildcards &&(opt_databases || argc > 1))
75027679
{
7503-
/* Only one database and selected table(s) */
7504-
if (!opt_alltspcs && !opt_notspcs)
7505-
dump_tablespaces_for_tables(*argv, (argv + 1), (argc - 1));
7506-
dump_selected_tables(*argv, (argv + 1), (argc - 1));
7680+
if (argc > 1 && !opt_databases)
7681+
/* One database, tables matching the wildcard. */
7682+
dump_tables_for_database_wild(argv[0], argc-1, argv+1);
7683+
else if (argc > 0)
7684+
/* Databases matching the wildcards. */
7685+
dump_databases_wild(argc, argv);
7686+
else
7687+
die(EX_CONSCHECK,
7688+
"Incorrect usage of patterns \n");
75077689
}
7508-
else if (argc > 0)
7690+
else
75097691
{
7510-
/* One or more databases, all tables */
7511-
if (!opt_alltspcs && !opt_notspcs)
7512-
dump_tablespaces_for_databases(argv);
7513-
dump_databases(argv);
7692+
if (argc > 1 && !opt_databases)
7693+
{
7694+
/* Only one database and selected table(s) */
7695+
if (!opt_alltspcs && !opt_notspcs)
7696+
dump_tablespaces_for_tables(*argv, (argv + 1), (argc - 1));
7697+
dump_selected_tables(*argv, (argv + 1), (argc - 1));
7698+
}
7699+
else if (argc > 0)
7700+
{
7701+
/* One or more databases, all tables */
7702+
if (!opt_alltspcs && !opt_notspcs)
7703+
dump_tablespaces_for_databases(argv);
7704+
dump_databases(argv);
7705+
}
75147706
}
75157707
}
75167708

0 commit comments

Comments
 (0)