struct table_load_params
{
std::string data_file; /* name of the file to load with LOAD DATA INFILE */
std::string sql_file; /* name of the file that contains CREATE TABLE or
CREATE VIEW */
std::string dbname; /* name of the database */
std::string tablename; /* name of the table */ bool tz_utc= false; /* true if the script sets the timezone to UTC */ bool is_view= false; /* true if the script is for a VIEW */
std::vector<std::string> triggers; /* CREATE TRIGGER statements */
ulonglong size= 0; /* size of the data file */
std::string sql_text; /* content of the SQL file, without triggers */
TableDDLInfo ddl_info; /* parsed CREATE TABLE statement */
staticstruct my_option my_long_options[] =
{
{"character-sets-dir", 0, "Directory for character set files.", (char**) &charsets_dir,
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"database", OPT_DATABASE, "Restore the specified database, ignoring others.To specify more than one " "database to include, use the directive multiple times, once for each database. " "Only takes effect when used together with --dir option", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"default-character-set", 0, "Set the default character set.", &default_charset,
&default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"dir", 0, "Restore all tables from backup directory created using mariadb-dump --dir",
&opt_dir, &opt_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"columns", 'c', "Use only these columns to import the data to. Give the column names in a comma separated list. This is same as giving columns to LOAD DATA INFILE.",
&opt_columns, &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"debug-check", 0, "Check memory and open file usage at exit.",
&debug_check_flag, &debug_check_flag, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"debug-info", 0, "Print some debug info at exit.",
&debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"default_auth", 0, "Default authentication client-side plugin to use.",
&opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delete", 'd', "First delete all rows from table.", &opt_delete,
&opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"fields-terminated-by", 0, "Fields in the input file are terminated by the given string.",
&fields_terminated, &fields_terminated, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"fields-enclosed-by", 0, "Fields in the import file are enclosed by the given character.",
&enclosed, &enclosed, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"fields-optionally-enclosed-by", 0, "Fields in the input file are optionally enclosed by the given character.",
&opt_enclosed, &opt_enclosed, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"fields-escaped-by", 0, "Fields in the input file are escaped by the given character.",
&escaped, &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f', "Continue even if we get an SQL error.",
&ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host. Defaults in the following order: " "$MARIADB_HOST, and then localhost",
¤t_host, ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ignore", 'i', "If duplicate unique key was found, keep old row.",
&ignore, &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-foreign-keys", 'k', "Disable foreign key checks while importing the data.",
&ignore_foreign_keys, &ignore_foreign_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-lines", 0, "Ignore first n lines of data infile.",
&opt_ignore_lines, &opt_ignore_lines, 0, GET_LL,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-database", OPT_IGNORE_DATABASE, "Do not restore the specified database. To specify more than one database " "to ignore, use the directive multiple times, once for each database. Only " "takes effect when used together with --dir option", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-table", OPT_IGNORE_TABLE, "Do not restore the specified table. To specify more than one table to " "ignore, use the directive multiple times, once for each table. Each " "table must be specified with both database and table names, e.g., " "--ignore-table=database.table. Only takes effect when used together with " "--dir option", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"innodb-optimize-keys", 0, "Create secondary indexes after data load (Innodb only).",
&opt_innodb_optimize_keys, &opt_innodb_optimize_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"lines-terminated-by", 0, "Lines in the input file are terminated by the given string.",
&lines_terminated, &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"local", 'L', "Read all files through the client.", &opt_local_file,
&opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"lock-tables", 'l', "Lock all tables for write (this disables threads).",
&lock_tables, &lock_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"low-priority", 0, "Use LOW_PRIORITY when updating the table.", &opt_low_priority,
&opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p', "Password to use when connecting to server. If password is not given it's asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef _WIN32
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0}, #endif
{"parallel", 'j', "Number of LOAD DATA jobs executed in parallel",
&opt_use_threads, &opt_use_threads, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"plugin_dir", 0, "Directory for client-side plugins.",
&opt_plugin_dir, &opt_plugin_dir, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in " "order of preference, my.cnf, $MYSQL_TCP_PORT, " #if MYSQL_PORT_DEFAULT == 0 "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
&opt_mysql_port,
&opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"replace", 'r', "If duplicate unique key was found, replace old row.",
&replace, &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"silent", 's', "Be more silent.", &silent, &silent, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "The socket file to use for connection.",
&opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"table", OPT_TABLES, "Restore the specified table ignoring others. Use --table=dbname.tablename with this option. " "To specify more than one table to include, use the directive multiple times, once for each " "table. Only takes effect when used together with --dir option", 0, 0, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include <sslopt-longopts.h>
{"use-threads", 0, "Synonym for --parallel option",
&opt_use_threads, &opt_use_threads, 0,
GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.", ¤t_user,
¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif
{"verbose", 'v', "Print info about the various stages.", &verbose,
&verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
staticvoid usage(void)
{
puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
puts("Copyright 2008-2011 Oracle and Monty Program Ab.");
puts("Copyright 2012-2019 MariaDB Corporation Ab.");
print_version();
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("\
Loads tables from text files in various formats. The base name of the\n\
text file must be the name of the table that should be used.\n\ If one uses sockets to connect to the MariaDB server, the server will open\n\ and read the text file directly. In other cases the client will open the text\n\
file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
static my_bool
get_one_option(conststruct my_option *opt, constchar *argument, constchar *filename)
{ switch(opt->id) { case'p': if (argument == disabled_my_option)
argument= (char*) ""; /* Don't require password */ if (argument)
{ /* Oneshouldnotreallychangetheargument,butwemakean exceptionforpasswords
*/ char *start= (char*) argument;
my_free(opt_password);
opt_password=my_strdup(PSI_NOT_INSTRUMENTED, argument,MYF(MY_FAE)); while (*argument)
*(char*) argument++= 'x'; /* Destroy argument */ if (*start)
start[1]=0; /* Cut length of argument */
tty_password= 0;
} else
tty_password= 1; break; #ifdef _WIN32 case'W':
opt_protocol = MYSQL_PROTOCOL_PIPE; break; #endif case OPT_MYSQL_PROTOCOL: if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
opt->name)) <= 0)
{
sf_leaking_memory= 1; /* no memory leak reports here */ exit(1);
} break; case'P': if (filename[0] == '\0')
{ /* Port given on command line, switch protocol to use TCP */
opt_protocol= MYSQL_PROTOCOL_TCP;
} break; case'S': if (filename[0] == '\0')
{ /* Socketgivenoncommandline,switchprotocoltouseSOCKETSt ExceptonWindowsif'protocol=pipe'hasbeenprovidedin theconfigfileorcommandline.
*/ if (opt_protocol != MYSQL_PROTOCOL_PIPE)
{
opt_protocol= MYSQL_PROTOCOL_SOCKET;
}
} break; case (int) OPT_IGNORE_TABLE: if (!strchr(argument, '.'))
{
fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n"); exit(1);
}
ignore_tables.insert(argument); break; case (int) OPT_TABLES: if (!strchr(argument, '.'))
{
fprintf(stderr, "Illegal use of option --table=<database>.<table>\n"); exit(1);
}
include_tables.insert(argument); break; case (int) OPT_IGNORE_DATABASE:
ignore_databases.insert(argument); break; case (int) OPT_DATABASE:
include_databases.insert(argument); break; case'#':
DBUG_PUSH(argument ? argument : "d:t:o");
debug_check_flag= 1; break; #include <sslopt-case.h> case'V': print_version(); exit(0); case'I': case'?':
usage(); exit(0);
} return0;
}
staticint get_options(int *argc, char ***argv)
{ int ho_error;
if (current_host == NULL)
current_host= getenv("MARIADB_HOST");
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR;
if (enclosed && opt_enclosed)
{
fprintf(stderr, "You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n"); return(1);
} if (replace && ignore)
{
fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n"); return(1);
} if (*argc < 2 && !opt_dir)
{
usage(); return1;
} if (!opt_dir)
{
current_db= *((*argv)++);
(*argc)--;
} if (tty_password)
opt_password=my_get_tty_password(NullS); return(0);
}
if (tz_utc && exec_sql(mysql, "SET TIME_ZONE='+00:00';"))
DBUG_RETURN(1); if (exec_sql(mysql,
std::string("ALTER TABLE ") + full_tablename + " DISABLE KEYS"))
DBUG_RETURN(1);
if (!opt_local_file)
strmake_buf(hard_path, filename); else
my_load_path(hard_path, filename, NULL); /* filename includes the path */
if (opt_delete)
{ if (verbose)
fprintf(stdout, "Deleting the old data from table %s\n", tablename.c_str());
snprintf(sql_statement, FN_REFLEN * 16 + 256, "DELETE FROM %s",
full_tablename.c_str()); if (exec_sql(mysql, sql_statement))
DBUG_RETURN(1);
}
bool recreate_secondary_keys= false; if (opt_innodb_optimize_keys && ddl_info.storage_engine == "InnoDB")
{ auto drop_secondary_keys_sql= ddl_info.drop_secondary_indexes_sql(); if (!drop_secondary_keys_sql.empty())
{
recreate_secondary_keys= true; if (exec_sql(mysql, drop_secondary_keys_sql))
DBUG_RETURN(1);
}
} if (exec_sql(mysql, "SET collation_database=binary"))
DBUG_RETURN(1);
to_unix_path(hard_path); if (verbose)
{
fprintf(stdout, "Loading data from %s file: %s into %s\n",
(opt_local_file) ? "LOCAL" : "SERVER", hard_path, tablename.c_str());
}
mysql_real_escape_string(mysql, escaped_name, hard_path,
(unsignedlong) strlen(hard_path));
snprintf(sql_statement, sizeof(sql_statement), "LOAD DATA %s %s INFILE '%s'",
opt_low_priority ? "LOW_PRIORITY" : "",
opt_local_file ? "LOCAL" : "", escaped_name);
end= strend(sql_statement); if (replace)
end= strmov(end, " REPLACE"); if (ignore)
end= strmov(end, " IGNORE");
end= strmov(end, " INTO TABLE ");
if (ddl_info.storage_engine == "MyISAM" || ddl_info.storage_engine == "Aria")
{ /* Avoid "table was not properly closed" warnings */ if (exec_sql(mysql, std::string("FLUSH TABLE ").append(full_tablename).c_str()))
DBUG_RETURN(1);
} if (recreate_secondary_keys)
{ auto create_secondary_keys_sql= ddl_info.add_secondary_indexes_sql(); if (!create_secondary_keys_sql.empty())
{ if (verbose)
{
fprintf(stdout, "Adding secondary indexes to table %s\n", ddl_info.table_name.c_str());
} if (exec_sql(mysql, create_secondary_keys_sql))
DBUG_RETURN(1);
}
} if (tz_utc)
{ if (exec_sql(mysql, "SET TIME_ZONE=@save_tz;"))
DBUG_RETURN(1);
} /* Restore constraints and triggers */ for (constauto &create_trigger_def : triggers)
{ if (exec_sql(mysql, create_trigger_def)) return1;
}
if (opt_innodb_optimize_keys && ddl_info.storage_engine == "InnoDB")
{
std::string constraints= ddl_info.add_constraints_sql(); if (!constraints.empty())
{ if (exec_sql(mysql, constraints)) return1;
}
}
DBUG_RETURN(0);
}
staticvoid lock_table(MYSQL *mysql, int tablecount, char **raw_tablename)
{
DYNAMIC_STRING query; int i; char tablename[FN_REFLEN];
if (verbose)
fprintf(stdout, "Locking tables for write\n");
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); for (i=0 ; i < tablecount ; i++)
{
fn_format(tablename, raw_tablename[i], "", "", 1 | 2);
dynstr_append(&query, tablename);
dynstr_append(&query, " WRITE,");
} if (mysql_real_query(mysql, query.str, (ulong)query.length-1))
db_error(mysql); /* We shall continue here, if --force was given */
dynstr_free(&query);
}
/* Checkserverversion,andreturntrueifbulkloadcanbeenabled WorksaroundMDEV-34703(fixedin10.11.11,11.4.5,11.7.2)
*/ staticbool can_enable_innodb_bulk_load(MYSQL* mysql)
{ auto ver = mysql_get_server_version(mysql); return ver >= 110702 ||
(ver >= 110405 && ver < 110500) ||
(ver >= 101111 && ver < 101200);
}
static MYSQL *db_connect(char *host, char *database, char *user, char *passwd)
{
MYSQL *mysql;
my_bool reconnect; if (verbose)
fprintf(stdout, "Connecting to %s\n", host ? host : "localhost"); if (opt_use_threads && !lock_tables)
{ if (!(mysql= mysql_init(NULL)))
{ return0;
}
} else if (!(mysql= mysql_init(NULL))) return0; if (opt_compress)
mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS); if (opt_local_file)
mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
(char*) &opt_local_file);
SET_SSL_OPTS(mysql); if (opt_protocol)
mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
if (opt_plugin_dir && *opt_plugin_dir)
mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
if (opt_default_auth && *opt_default_auth)
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqlimport"); if (!(mysql_real_connect(mysql,host,user,passwd,
database,opt_mysql_port,opt_mysql_unix_port,
opt_dir?CLIENT_MULTI_STATEMENTS:0)))
{
ignore_errors=0; /* NO RETURN FROM db_error */
db_error(mysql);
}
reconnect= 0;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); if (database)
{ if (verbose)
fprintf(stdout, "Selecting database %s\n", database); if (mysql_select_db(mysql, database))
{
ignore_errors= 0;
db_error(mysql);
}
} if (ignore_foreign_keys)
mysql_query(mysql, "set foreign_key_checks= 0;");
if (can_enable_innodb_bulk_load(mysql))
{ if (mysql_query(mysql, "set unique_checks=0;"))
db_error(mysql);
} if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
db_error(mysql); if (mysql_query(mysql, "set @save_tz=@@session.time_zone"))
db_error(mysql); if (mysql_query(mysql, "/*M!100200 set check_constraint_checks=0*/"))
db_error(mysql); return mysql;
}
staticvoid db_disconnect(char *host, MYSQL *mysql)
{ if (verbose)
fprintf(stdout, "Disconnecting from %s\n", host ? host : "localhost");
mysql_close(mysql);
}
staticvoid safe_exit(int error, MYSQL *mysql)
{
if (error && ignore_errors) return;
bool expected= false; if (!aborting.compare_exchange_strong(expected, true)) return;
if (thread_pool)
{ /* dirty exit. some threads are running,
memory is not freed, openssl not deinitialized */
DBUG_ASSERT(error); if (mysql)
{ /* Westillneedtellservertokillallconnections soitdoesnotkeepbusywithload.
*/
kill_tp_connections(mysql);
}
for (end= from+length; from != end; from++)
{
*to++= *from; if (*from == '\\')
end_backslashes^=1; /* find odd number of backslashes */ else
{ if (*from == '\'' && !end_backslashes)
*to++= *from; /* We want a duplicate of "'" for MySQL */
end_backslashes=0;
}
} /* Add missing backslashes if user has specified odd number of backs.*/ if (end_backslashes)
*to++= '\\'; return to;
}
/* sort files by size, descending. Put view definitions at the end of the list.*/
std::sort(files.begin(), files.end(),
[](const table_load_params &a, const table_load_params &b) -> bool
{ /* Sort views after base tables */ if (a.is_view && !b.is_view) returnfalse; if (!a.is_view && b.is_view) returntrue; /* Sort by size descending */ if (a.size > b.size) returntrue; if (a.size < b.size) returnfalse; /* If sizes are equal, sort by name */ return a.sql_file < b.sql_file;
});
}
#define MAX_THREADS 256
int main(int argc, char **argv)
{ int error=0;
MY_INIT(argv[0]);
sf_leaking_memory=1; /* don't report memory leaks on early exits */
/* We need to know if protocol-related options originate from CLI args */
my_defaults_mark_files = TRUE;
load_defaults_or_exit("my", load_default_groups, &argc, &argv); /* argv is changed in the program */
argv_to_free= argv; if (get_options(&argc, &argv))
{
free_defaults(argv_to_free); return(1);
}
if (opt_use_threads > MAX_THREADS)
{
fatal_error("Too many connections, max value for --parallel is %d\n",
MAX_THREADS);
}
sf_leaking_memory=0; /* from now on we cleanup properly */
std::vector<table_load_params> files_to_load;
if (opt_dir)
{
ignore_foreign_keys= 1; if (argc)
fatal_error("Invalid arguments for --dir option");
scan_backup_dir(opt_dir, files_to_load);
} else
{ for (char **t=argv; *t != NULL; t++)
{
table_load_params p(*t, "", current_db, 0);
files_to_load.push_back(p);
}
} if (files_to_load.empty())
{
fatal_error("No files to load"); return1;
}
MYSQL *mysql=
db_connect(current_host, current_db, current_user, opt_password); if (!mysql)
{
free_defaults(argv_to_free); return1;
} for (auto &f : files_to_load)
{ if (f.create_table_or_view(mysql))
set_exitcode(1);
}
if (opt_use_threads && !lock_tables)
{
init_tp_connections(opt_use_threads);
thread_pool= tpool::create_thread_pool_generic(opt_use_threads,opt_use_threads);
thread_pool->set_thread_callbacks(tpool_thread_init,tpool_thread_exit);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.