diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/CMakeLists.txt | 10 | ||||
-rw-r--r-- | client/client_priv.h | 3 | ||||
-rw-r--r-- | client/completion_hash.cc | 2 | ||||
-rw-r--r-- | client/mysql.cc | 99 | ||||
-rw-r--r-- | client/mysql_plugin.c | 5 | ||||
-rw-r--r-- | client/mysql_upgrade.c | 119 | ||||
-rw-r--r-- | client/mysqladmin.cc | 67 | ||||
-rw-r--r-- | client/mysqlbinlog.cc | 106 | ||||
-rw-r--r-- | client/mysqlcheck.c | 98 | ||||
-rw-r--r-- | client/mysqldump.c | 589 | ||||
-rw-r--r-- | client/mysqlimport.c | 13 | ||||
-rw-r--r-- | client/mysqlshow.c | 15 | ||||
-rw-r--r-- | client/mysqlslap.c | 40 | ||||
-rw-r--r-- | client/mysqltest.cc | 326 |
14 files changed, 1059 insertions, 433 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e3edacc351c..e4643ad9358 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -15,16 +15,20 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include + ${PCRE_INCLUDES} + ${CMAKE_SOURCE_DIR}/mysys_ssl ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/libmysql - ${CMAKE_SOURCE_DIR}/regex ${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/strings ${MY_READLINE_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) +## We will need libeay32.dll and ssleay32.dll when running client executables. +COPY_OPENSSL_DLLS(copy_openssl_client) + ADD_DEFINITIONS(${SSL_DEFINES}) MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc ${CMAKE_SOURCE_DIR}/sql/sql_string.cc) @@ -36,7 +40,7 @@ ENDIF(UNIX) MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test) SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS") -TARGET_LINK_LIBRARIES(mysqltest mysqlclient regex) +TARGET_LINK_LIBRARIES(mysqltest mysqlclient pcre pcreposix) SET_TARGET_PROPERTIES(mysqltest PROPERTIES ENABLE_EXPORTS TRUE) @@ -79,7 +83,7 @@ ENDIF(WIN32) ADD_EXECUTABLE(async_example async_example.c) TARGET_LINK_LIBRARIES(async_example mysqlclient) -SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin +SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin async_example PROPERTIES HAS_CXX TRUE) ADD_DEFINITIONS(-DHAVE_DLOPEN) diff --git a/client/client_priv.h b/client/client_priv.h index d89ca89c405..3905f323156 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -92,6 +92,9 @@ enum options_client OPT_REWRITE_DB, OPT_REPORT_PROGRESS, OPT_SKIP_ANNOTATE_ROWS_EVENTS, + OPT_SSL_CRL, OPT_SSL_CRLPATH, + OPT_USE_GTID, + OPT_GALERA_SST_MODE, OPT_MAX_CLIENT_OPTION /* should be always the last */ }; diff --git a/client/completion_hash.cc b/client/completion_hash.cc index 9ffb2082c06..c170b69de2d 100644 --- a/client/completion_hash.cc +++ b/client/completion_hash.cc @@ -49,7 +49,7 @@ int completion_hash_init(HashTable *ht, uint nSize) ht->initialized = 0; return FAILURE; } - init_alloc_root(&ht->mem_root, 8192, 0); + init_alloc_root(&ht->mem_root, 8192, 0, MYF(0)); ht->pHashFunction = hashpjw; ht->nTableSize = nSize; ht->initialized = 1; diff --git a/client/mysql.cc b/client/mysql.cc index 9d255b55430..89f9a75ec11 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -612,7 +612,6 @@ static COMMANDS commands[] = { { "OLD_PASSWORD", 0, 0, 0, ""}, { "ON", 0, 0, 0, ""}, { "ONE", 0, 0, 0, ""}, - { "ONE_SHOT", 0, 0, 0, ""}, { "OPEN", 0, 0, 0, ""}, { "OPTIMIZE", 0, 0, 0, ""}, { "OPTION", 0, 0, 0, ""}, @@ -922,6 +921,7 @@ static COMMANDS commands[] = { { "MAKE_SET", 0, 0, 0, ""}, { "MAKEDATE", 0, 0, 0, ""}, { "MAKETIME", 0, 0, 0, ""}, + { "MASTER_GTID_WAIT", 0, 0, 0, ""}, { "MASTER_POS_WAIT", 0, 0, 0, ""}, { "MAX", 0, 0, 0, ""}, { "MBRCONTAINS", 0, 0, 0, ""}, @@ -1182,12 +1182,9 @@ int main(int argc,char *argv[]) exit(1); } defaults_argv=argv; - if (get_options(argc, (char **) argv)) - { - free_defaults(defaults_argv); - my_end(0); - exit(1); - } + if ((status.exit_status= get_options(argc, (char **) argv))) + mysql_end(-1); + if (status.batch && !status.line_buff && !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin))) { @@ -1207,7 +1204,7 @@ int main(int argc,char *argv[]) } glob_buffer.realloc(512); completion_hash_init(&ht, 128); - init_alloc_root(&hash_mem_root, 16384, 0); + init_alloc_root(&hash_mem_root, 16384, 0, MYF(0)); bzero((char*) &mysql, sizeof(mysql)); if (sql_connect(current_host,current_db,current_user,opt_password, opt_silent)) @@ -1355,6 +1352,44 @@ sig_handler mysql_end(int sig) exit(status.exit_status); } +/* + set connection-specific options and call mysql_real_connect +*/ +static bool do_connect(MYSQL *mysql, const char *host, const char *user, + const char *password, const char *database, ulong flags) +{ + if (opt_secure_auth) + mysql_options(mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth); +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + if (opt_use_ssl) + { + mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, + opt_ssl_capath, opt_ssl_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } + mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); +#endif + if (opt_protocol) + mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); +#ifdef HAVE_SMEM + if (shared_memory_base_name) + mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); +#endif + 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_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysql"); + return mysql_real_connect(mysql, host, user, password, database, + opt_mysql_port, opt_mysql_unix_port, flags); +} + /* This function handles sigint calls @@ -1376,8 +1411,7 @@ sig_handler handle_sigint(int sig) } kill_mysql= mysql_init(kill_mysql); - if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password, - "", opt_mysql_port, opt_mysql_unix_port,0)) + if (!do_connect(kill_mysql,current_host, current_user, opt_password, "", 0)) { tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); goto err; @@ -1890,7 +1924,7 @@ static int get_options(int argc, char **argv) opt_net_buffer_length= *mysql_params->p_net_buffer_length; if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) - exit(ho_error); + return(ho_error); *mysql_params->p_max_allowed_packet= opt_max_allowed_packet; *mysql_params->p_net_buffer_length= opt_net_buffer_length; @@ -2849,7 +2883,7 @@ You can turn off this feature to get a quicker startup with -A\n\n"); mysql_free_result(fields); break; } - field_names[i][num_fields*2]= '\0'; + field_names[i][num_fields*2]= NULL; j=0; while ((sql_field=mysql_fetch_field(fields))) { @@ -3330,7 +3364,7 @@ com_go(String *buffer,char *line __attribute__((unused))) end: - /* Show warnings if any or error occured */ + /* Show warnings if any or error occurred */ if (show_warnings == 1 && (warnings >= 1 || error)) print_warnings(); @@ -3522,9 +3556,9 @@ print_table_data(MYSQL_RES *result) { uint length= column_names ? field->name_length : 0; if (quick) - length=max(length,field->length); + length= MY_MAX(length,field->length); else - length=max(length,field->max_length); + length= MY_MAX(length,field->max_length); if (length < 4 && !IS_NOT_NULL(field->flags)) length=4; // Room for "NULL" field->max_length=length; @@ -3545,8 +3579,8 @@ print_table_data(MYSQL_RES *result) field->name, field->name + name_length); uint display_length= field->max_length + name_length - numcells; - tee_fprintf(PAGER, " %-*s |",(int) min(display_length, - MAX_COLUMN_LENGTH), + tee_fprintf(PAGER, " %-*s |",(int) MY_MIN(display_length, + MAX_COLUMN_LENGTH), field->name); } (void) tee_fputs("\n", PAGER); @@ -3634,9 +3668,9 @@ static int get_field_disp_length(MYSQL_FIELD *field) uint length= column_names ? field->name_length : 0; if (quick) - length= max(length, field->length); + length= MY_MAX(length, field->length); else - length= max(length, field->max_length); + length= MY_MAX(length, field->max_length); if (length < 4 && !IS_NOT_NULL(field->flags)) length= 4; /* Room for "NULL" */ @@ -3652,6 +3686,7 @@ static int get_field_disp_length(MYSQL_FIELD *field) @returns The max number of characters in any row of this result */ + static int get_result_width(MYSQL_RES *result) { unsigned int len= 0; @@ -4585,23 +4620,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, } if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); - if (opt_secure_auth) - mysql_options(&mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth); if (using_opt_local_infile) mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile); -#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) - if (opt_use_ssl) - mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath, opt_ssl_cipher); - mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, - (char*)&opt_ssl_verify_server_cert); -#endif - if (opt_protocol) - mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif if (safe_updates) { char init_command[100]; @@ -4613,15 +4633,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); - 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); - - if (!mysql_real_connect(&mysql, host, user, password, - database, opt_mysql_port, opt_mysql_unix_port, - connect_flag | CLIENT_MULTI_STATEMENTS)) + if (!do_connect(&mysql, host, user, password, database, + connect_flag | CLIENT_MULTI_STATEMENTS)) { if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index bc9969c9b66..ebf04c9a8c3 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -15,14 +15,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include <my_global.h> #include <m_string.h> #include <mysql.h> #include <my_getopt.h> #include <my_dir.h> -#include <my_global.h> -#include <stdio.h> -#include <string.h> - #define SHOW_VERSION "1.0.0" #define PRINT_VERSION do { printf("%s Ver %s Distrib %s\n", \ diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index eaa10245a94..737f9c9c8d7 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -22,7 +22,7 @@ #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ -#define VER "1.3a" +#define VER "1.4" #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> @@ -36,8 +36,8 @@ # endif #endif -static int phase = 1; -static int phases_total = 4; +static int phase = 0; +static int phases_total = 6; static char mysql_path[FN_REFLEN]; static char mysqlcheck_path[FN_REFLEN]; @@ -47,6 +47,8 @@ static my_bool opt_not_used, opt_silent; static uint my_end_arg= 0; static char *opt_user= (char*)"root"; +static my_bool upgrade_from_mysql; + static DYNAMIC_STRING ds_args; static DYNAMIC_STRING conn_args; @@ -145,22 +147,22 @@ static struct my_option my_long_options[]= #include <sslopt-longopts.h> {"tmpdir", 't', "Directory for temporary files.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"upgrade-system-tables", 's', "Only upgrade the system tables " - "do not try to upgrade the data.", + {"upgrade-system-tables", 's', "Only upgrade the system tables in the mysql database. Tables in other databases are not checked or touched.", &opt_systables_only, &opt_systables_only, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #define USER_OPT (array_elements(my_long_options) - 6) {"user", 'u', "User for login if not current user.", &opt_user, &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Display more output about the process.", + {"verbose", 'v', "Display more output about the process; Using it twice will print connection argument; Using it 3 times will print out all CHECK, RENAME and ALTER TABLE during the check phase.", &opt_not_used, &opt_not_used, 0, GET_BOOL, NO_ARG, 1, 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}, - {"version-check", 'k', "Run this program only if its \'server version\' " - "matches the version of the server to which it's connecting, (enabled by " - "default); use --skip-version-check to avoid this check. Note: the \'server " - "version\' of the program is the version of the MySQL server with which it " - "was built/distributed.", &opt_version_check, &opt_version_check, 0, + {"version-check", 'k', + "Run this program only if its \'server version\' " + "matches the version of the server to which it's connecting. " + "Note: the \'server version\' of the program is the version of the MariaDB " + "server with which it was built/distributed.", + &opt_version_check, &opt_version_check, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"write-binlog", OPT_WRITE_BINLOG, "All commands including those, " "issued by mysqlcheck, are written to the binary log.", @@ -381,6 +383,9 @@ static int run_command(char* cmd, FILE *res_file; int error; + if (opt_verbose >= 4) + puts(cmd); + if (!(res_file= popen(cmd, "r"))) die("popen(\"%s\", \"r\") failed", cmd); @@ -605,7 +610,7 @@ static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value) if ((value_end= strchr(value_start, '\n')) == NULL) return 1; /* Unexpected result */ - len= (size_t) min(FN_REFLEN, value_end-value_start); + len= (size_t) MY_MIN(FN_REFLEN, value_end-value_start); strncpy(value, value_start, len); value[len]= '\0'; return 0; @@ -639,7 +644,7 @@ static int get_upgrade_info_file_name(char* name) /* Read the content of mysql_upgrade_info file and compare the version number form file against - version number wich mysql_upgrade was compiled for + version number which mysql_upgrade was compiled for NOTE This is an optimization to avoid running mysql_upgrade @@ -743,26 +748,31 @@ static void print_conn_args(const char *tool_name) in the server using "mysqlcheck --check-upgrade .." */ -static int run_mysqlcheck_upgrade(void) +static int run_mysqlcheck_upgrade(my_bool mysql_db_only) { + const char *what= mysql_db_only ? "mysql database" : "tables"; + const char *arg1= mysql_db_only ? "--databases" : "--all-databases"; + const char *arg2= mysql_db_only ? "mysql" : "--skip-database=mysql"; int retch; - if (opt_systables_only) + if (opt_systables_only && !mysql_db_only) { - verbose("Phase %d/%d: Checking and upgrading tables... Skipped", - phase++, phases_total); + verbose("Phase %d/%d: Checking and upgrading %s... Skipped", + ++phase, phases_total, what); return 0; } - verbose("Phase %d/%d: Checking and upgrading tables", phase++, phases_total); + verbose("Phase %d/%d: Checking and upgrading %s", ++phase, phases_total, what); print_conn_args("mysqlcheck"); retch= run_tool(mysqlcheck_path, NULL, /* Send output from mysqlcheck directly to screen */ defaults_file, "--check-upgrade", - "--all-databases", "--auto-repair", - !opt_silent || opt_verbose ? "--verbose": "", + !opt_silent || opt_verbose >= 1 ? "--verbose" : "", + opt_verbose >= 2 ? "--verbose" : "", + opt_verbose >= 3 ? "--verbose" : "", opt_silent ? "--silent": "", opt_write_binlog ? "--write-binlog" : "--skip-write-binlog", + arg1, arg2, "2>&1", NULL); return retch; @@ -793,18 +803,23 @@ static my_bool is_mysql() static int run_mysqlcheck_views(void) { const char *upgrade_views="--process-views=YES"; - if (is_mysql()) + if (upgrade_from_mysql) { + /* + this has to ignore opt_systables_only, because upgrade_from_mysql + is determined by analyzing systables. if we honor opt_systables_only + here, views won't be fixed by subsequent mysql_upgrade runs + */ upgrade_views="--process-views=UPGRADE_FROM_MYSQL"; - verbose("Phase %d/%d: Fixing views from mysql", phase++, phases_total); + verbose("Phase %d/%d: Fixing views from mysql", ++phase, phases_total); } else if (opt_systables_only) { - verbose("Phase %d/%d: Fixing views... Skipped", phase++, phases_total); + verbose("Phase %d/%d: Fixing views... Skipped", ++phase, phases_total); return 0; } else - verbose("Phase %d/%d: Fixing views", phase++, phases_total); + verbose("Phase %d/%d: Fixing views", ++phase, phases_total); print_conn_args("mysqlcheck"); return run_tool(mysqlcheck_path, @@ -825,11 +840,11 @@ static int run_mysqlcheck_fixnames(void) if (opt_systables_only) { verbose("Phase %d/%d: Fixing table and database names ... Skipped", - phase++, phases_total); + ++phase, phases_total); return 0; } verbose("Phase %d/%d: Fixing table and database names", - phase++, phases_total); + ++phase, phases_total); print_conn_args("mysqlcheck"); return run_tool(mysqlcheck_path, NULL, /* Send output from mysqlcheck directly to screen */ @@ -837,7 +852,9 @@ static int run_mysqlcheck_fixnames(void) "--all-databases", "--fix-db-names", "--fix-table-names", - opt_verbose ? "--verbose": "", + opt_verbose >= 1 ? "--verbose" : "", + opt_verbose >= 2 ? "--verbose" : "", + opt_verbose >= 3 ? "--verbose" : "", opt_silent ? "--silent": "", opt_write_binlog ? "--write-binlog" : "--skip-write-binlog", "2>&1", @@ -850,6 +867,7 @@ static const char *expected_errors[]= "ERROR 1060", /* Duplicate column name */ "ERROR 1061", /* Duplicate key name */ "ERROR 1054", /* Unknown column */ + "ERROR 1290", /* RR_OPTION_PREVENTS_STATEMENT */ 0 }; @@ -903,15 +921,35 @@ static void print_line(char* line) static int run_sql_fix_privilege_tables(void) { int found_real_errors= 0; + const char **query_ptr; + DYNAMIC_STRING ds_script; DYNAMIC_STRING ds_result; DBUG_ENTER("run_sql_fix_privilege_tables"); + if (init_dynamic_string(&ds_script, "", 65536, 1024)) + die("Out of memory"); + if (init_dynamic_string(&ds_result, "", 512, 512)) die("Out of memory"); verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'", - phase++, phases_total); - run_query(mysql_fix_privilege_tables, + ++phase, phases_total); + + /* + Individual queries can not be executed independently by invoking + a forked mysql client, because the script uses session variables + and prepared statements. + */ + for ( query_ptr= &mysql_fix_privilege_tables[0]; + *query_ptr != NULL; + query_ptr++ + ) + { + if (strcasecmp(*query_ptr, "flush privileges;\n")) + dynstr_append(&ds_script, *query_ptr); + } + + run_query(ds_script.str, &ds_result, /* Collect result */ TRUE); @@ -939,6 +977,7 @@ static int run_sql_fix_privilege_tables(void) } dynstr_free(&ds_result); + dynstr_free(&ds_script); DBUG_RETURN(found_real_errors); } @@ -1073,23 +1112,29 @@ int main(int argc, char **argv) if (opt_version_check && check_version_match()) die("Upgrade failed"); + upgrade_from_mysql= is_mysql(); + /* Run "mysqlcheck" and "mysql_fix_privilege_tables.sql" */ - if (run_mysqlcheck_views() || run_mysqlcheck_fixnames() || - run_mysqlcheck_upgrade() || run_sql_fix_privilege_tables()) - { - /* - The upgrade failed to complete in some way or another, - significant error message should have been printed to the screen - */ + if (run_mysqlcheck_upgrade(TRUE) || + run_mysqlcheck_views() || + run_sql_fix_privilege_tables() || + run_mysqlcheck_fixnames() || + run_mysqlcheck_upgrade(FALSE)) die("Upgrade failed" ); - } + + verbose("Phase %d/%d: Running 'FLUSH PRIVILEGES'", ++phase, phases_total); + if (run_query("FLUSH PRIVILEGES", NULL, TRUE)) + die("Upgrade failed" ); + verbose("OK"); /* Create a file indicating upgrade has been performed */ create_mysql_upgrade_info_file(); + DBUG_ASSERT(phase == phases_total); + end: free_used_memory(); my_end(my_end_arg); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index e7c6410978d..56d2784a1f5 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, Monty Program Ab. + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,9 +23,10 @@ #include <sys/stat.h> #include <mysql.h> #include <sql_common.h> -#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ +#include <welcome_copyright_notice.h> +#include <my_rnd.h> -#define ADMIN_VERSION "9.0" +#define ADMIN_VERSION "9.1" #define MAX_MYSQL_VAR 512 #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */ #define MAX_TRUNC_LENGTH 3 @@ -100,6 +101,7 @@ enum commands { ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD, ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS, ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE, + ADMIN_START_ALL_SLAVES, ADMIN_STOP_ALL_SLAVES, ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG, ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS, ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS, @@ -113,6 +115,7 @@ static const char *command_names[]= { "flush-hosts", "flush-tables", "password", "ping", "extended-status", "flush-status", "flush-privileges", "start-slave", "stop-slave", + "start-all-slaves", "stop-all-slaves", "flush-threads", "old-password", "flush-slow-log", "flush-table-statistics", "flush-index-statistics", "flush-user-statistics", "flush-client-statistics", @@ -341,8 +344,12 @@ int main(int argc,char *argv[]) } #ifdef HAVE_OPENSSL if (opt_use_ssl) + { mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); #endif @@ -361,6 +368,9 @@ int main(int argc,char *argv[]) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqladmin"); if (sql_connect(&mysql, option_wait)) { /* @@ -1118,26 +1128,67 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) } case ADMIN_START_SLAVE: - if (mysql_query(mysql, "START SLAVE")) + case ADMIN_START_ALL_SLAVES: + { + my_bool many_slaves= 0; + const char *query= "START SLAVE"; + if (command == ADMIN_START_ALL_SLAVES && mariadb_connection(mysql) && + mysql_get_server_version(mysql) >= 100000) + { + query="START ALL SLAVES"; + many_slaves= 1; + } + + if (mysql_query(mysql, query)) { my_printf_error(0, "Error starting slave: %s", error_flags, mysql_error(mysql)); return -1; } + else if (!many_slaves || mysql_warning_count(mysql) > 0) + { + if (!option_silent) + puts("Slave('s) started"); + } else - puts("Slave started"); + { + if (!option_silent) + puts("No slaves to start"); + } break; + } case ADMIN_STOP_SLAVE: - if (mysql_query(mysql, "STOP SLAVE")) + case ADMIN_STOP_ALL_SLAVES: + { + const char *query= "STOP SLAVE"; + my_bool many_slaves= 0; + + if (command == ADMIN_STOP_ALL_SLAVES && mariadb_connection(mysql) && + mysql_get_server_version(mysql) >= 100000) + { + query="STOP ALL SLAVES"; + many_slaves= 1; + } + + if (mysql_query(mysql, query)) { my_printf_error(0, "Error stopping slave: %s", error_flags, mysql_error(mysql)); return -1; } + else if (!many_slaves || mysql_warning_count(mysql) > 0) + { + /* We can't detect if there was any slaves to stop with STOP SLAVE */ + if (many_slaves && !option_silent) + puts("Slave('s) stopped"); + } else - puts("Slave stopped"); + { + if (!option_silent) + puts("All slaves was already stopped"); + } break; - + } case ADMIN_PING: mysql->reconnect=0; /* We want to know of reconnects */ if (!mysql_ping(mysql)) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 250dc609891..4be31421f9b 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -34,9 +34,11 @@ #define TABLE TABLE_CLIENT #include "client_priv.h" #include <my_time.h> +#include <sslopt-vars.h> /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ #include "sql_priv.h" #include "log_event.h" +#include "compat56.h" #include "sql_common.h" #include "my_dir.h" #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE @@ -48,6 +50,8 @@ #include "mysqld.h" +#include <algorithm> + Rpl_filter *binlog_filter= 0; #define BIN_LOG_HEADER_SIZE 4 @@ -277,8 +281,8 @@ public: int init() { - return init_dynamic_array(&file_names, sizeof(File_name_record), - 100, 100); + return my_init_dynamic_array(&file_names, sizeof(File_name_record), + 100, 100, MYF(0)); } void init_by_dir_name(const char *dir) @@ -1228,6 +1232,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, case WRITE_ROWS_EVENT: case DELETE_ROWS_EVENT: case UPDATE_ROWS_EVENT: + case WRITE_ROWS_EVENT_V1: + case UPDATE_ROWS_EVENT_V1: + case DELETE_ROWS_EVENT_V1: { Rows_log_event *e= (Rows_log_event*) ev; if (print_row_event(print_event_info, ev, e->get_table_id(), @@ -1386,6 +1393,7 @@ static struct my_option my_options[] = {"socket", 'S', "The socket file to use for connection.", &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#include <sslopt-longopts.h> {"start-datetime", OPT_START_DATETIME, "Start reading the binlog at first event having a datetime equal or " "posterior to the argument; the argument must be a date and time " @@ -1527,6 +1535,8 @@ static void cleanup() my_free(host); my_free(user); my_free(const_cast<char*>(dirname_for_local_load)); + my_free(start_datetime_str); + my_free(stop_datetime_str); delete binlog_filter; delete glob_description_event; @@ -1558,13 +1568,14 @@ the mysql command line client.\n\n"); static my_time_t convert_str_to_timestamp(const char* str) { - int was_cut; + MYSQL_TIME_STATUS status; MYSQL_TIME l_time; long dummy_my_timezone; uint dummy_in_dst_time_gap; + /* We require a total specification (date AND time) */ - if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &was_cut) != - MYSQL_TIMESTAMP_DATETIME || was_cut) + if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) || + l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings) { error("Incorrect date and time argument: %s", str); exit(1); @@ -1590,6 +1601,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), DBUG_PUSH(argument ? argument : default_dbug_option); break; #endif +#include <sslopt-case.h> case 'd': one_database = 1; break; @@ -1712,7 +1724,7 @@ static int parse_args(int *argc, char*** argv) exit(ho_error); if (debug_info_flag) my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; - if (debug_check_flag) + else if (debug_check_flag) my_end_arg= MY_CHECK_ERROR; return 0; } @@ -1739,6 +1751,18 @@ static Exit_status safe_connect() return ERROR_STOP; } +#ifdef HAVE_OPENSSL + if (opt_use_ssl) + { + mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, + opt_ssl_capath, opt_ssl_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } + mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); +#endif /*HAVE_OPENSSL*/ + if (opt_plugindir && *opt_plugindir) mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir); @@ -1752,6 +1776,9 @@ static Exit_status safe_connect() mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME, shared_memory_base_name); #endif + mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqlbinlog"); if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0)) { error("Failed on connect: %s", mysql_error(mysql)); @@ -1815,7 +1842,7 @@ static Exit_status check_master_version() { MYSQL_RES* res = 0; MYSQL_ROW row; - const char* version; + uint version; if (mysql_query(mysql, "SELECT VERSION()") || !(res = mysql_store_result(mysql))) @@ -1831,7 +1858,7 @@ static Exit_status check_master_version() goto err; } - if (!(version = row[0])) + if (!(version = atoi(row[0]))) { error("Could not find server version: " "Master reported NULL for the version."); @@ -1849,15 +1876,29 @@ static Exit_status check_master_version() "Master returned '%s'", mysql_error(mysql)); goto err; } + + /* + Announce our capabilities to the server, so it will send us all the events + that we know about. + */ + if (mysql_query(mysql, "SET @mariadb_slave_capability=" + STRINGIFY_ARG(MARIA_SLAVE_CAPABILITY_MINE))) + { + error("Could not inform master about capability. Master returned '%s'", + mysql_error(mysql)); + goto err; + } + delete glob_description_event; - switch (*version) { - case '3': + switch (version) { + case 3: glob_description_event= new Format_description_log_event(1); break; - case '4': + case 4: glob_description_event= new Format_description_log_event(3); break; - case '5': + case 5: + case 10: /* The server is soon going to send us its Format_description log event, unless it is a 5.0 server with 3.23 or 4.0 binlogs. @@ -1869,7 +1910,7 @@ static Exit_status check_master_version() default: glob_description_event= NULL; error("Could not find server version: " - "Master reported unrecognized MySQL version '%s'.", version); + "Master reported unrecognized MySQL version '%s'.", row[0]); goto err; } if (!glob_description_event || !glob_description_event->is_valid()) @@ -2020,6 +2061,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, if ((rev->ident_len != logname_len) || memcmp(rev->new_log_ident, logname, logname_len)) { + delete ev; DBUG_RETURN(OK_CONTINUE); } /* @@ -2028,6 +2070,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, log. If we are running with to_last_remote_log, we print it, because it serves as a useful marker between binlogs then. */ + delete ev; continue; } len= 1; // fake Rotate, so don't increment old_off @@ -2058,7 +2101,9 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, Exit_status retval; if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0) + { DBUG_RETURN(ERROR_STOP); + } retval= process_event(print_event_info, ev, old_off, logname); if (retval != OK_CONTINUE) @@ -2338,7 +2383,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, my_off_t length,tmp; for (length= start_position_mot ; length > 0 ; length-=tmp) { - tmp=min(length,sizeof(buff)); + tmp= MY_MIN(length,sizeof(buff)); if (my_b_read(file, buff, (uint) tmp)) { error("Failed reading from file."); @@ -2422,27 +2467,27 @@ int main(int argc, char** argv) my_init_time(); // for time functions tzset(); // set tzname - init_alloc_root(&s_mem_root, 16384, 0); + init_alloc_root(&s_mem_root, 16384, 0, MYF(0)); if (load_defaults("my", load_groups, &argc, &argv)) exit(1); + defaults_argv= argv; + if (!(binlog_filter= new Rpl_filter)) { error("Failed to create Rpl_filter"); - exit(1); + goto err; } - defaults_argv= argv; parse_args(&argc, (char***)&argv); if (!argc || opt_version) { if (!argc) usage(); - cleanup(); - free_defaults(defaults_argv); - my_end(my_end_arg); - exit(!opt_version); + if (!opt_version) + retval= ERROR_STOP; + goto err; } if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC) @@ -2462,12 +2507,18 @@ int main(int argc, char** argv) if (!dirname_for_local_load) { if (init_tmpdir(&tmpdir, 0)) - exit(1); + { + retval= ERROR_STOP; + goto err; + } dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME); } if (load_processor.init()) - exit(1); + { + retval= ERROR_STOP; + goto err; + } if (dirname_for_local_load) load_processor.init_by_dir_name(dirname_for_local_load); else @@ -2537,12 +2588,20 @@ int main(int argc, char** argv) free_defaults(defaults_argv); my_free_open_file_info(); load_processor.destroy(); + mysql_server_end(); /* We cannot free DBUG, it is used in global destructors after exit(). */ my_end(my_end_arg | MY_DONT_FREE_DBUG); exit(retval == ERROR_STOP ? 1 : 0); /* Keep compilers happy. */ DBUG_RETURN(retval == ERROR_STOP ? 1 : 0); + +err: + cleanup(); + free_defaults(defaults_argv); + my_end(my_end_arg); + exit(retval == ERROR_STOP ? 1 : 0); + DBUG_RETURN(retval == ERROR_STOP ? 1 : 0); } @@ -2567,3 +2626,4 @@ void *sql_alloc(size_t size) #include "sql_string.cc" #include "sql_list.cc" #include "rpl_filter.cc" +#include "compat56.cc" diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index a07fc773726..0c34ef35966 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2011, Oracle and/or its affiliates. + Copyright (c) 2001, 2013, Oracle and/or its affiliates. Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify @@ -18,7 +18,7 @@ /* By Jani Tolonen, 2001-04-20, MySQL Development Team */ -#define CHECK_VERSION "2.7.2-MariaDB" +#define CHECK_VERSION "2.7.4-MariaDB" #include "client_priv.h" #include <m_ctype.h> @@ -43,7 +43,7 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0, opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0, tty_password= 0, opt_frm= 0, debug_info_flag= 0, debug_check_flag= 0, opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0, - opt_do_tables= 1; + opt_persistent_all= 0, opt_do_tables= 1; static my_bool opt_write_binlog= 1, opt_flush_tables= 0; static uint verbose = 0, opt_mysql_port=0; static int my_end_arg; @@ -52,6 +52,7 @@ static char *opt_password = 0, *current_user = 0, *default_charset= 0, *current_host= 0; static char *opt_plugin_dir= 0, *opt_default_auth= 0; static int first_error = 0; +static char *opt_skip_database; DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds; DYNAMIC_ARRAY views4repair; static char *shared_memory_base_name=0; @@ -159,6 +160,10 @@ static struct my_option my_long_options[] = {"password", 'p', "Password to use when connecting to server. If password is not given, it's solicited on the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"persistent", 'Z', + "When using ANALYZE TABLE use the PERSISTENT FOR ALL option.", + &opt_persistent_all, &opt_persistent_all, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -190,6 +195,9 @@ static struct my_option my_long_options[] = #endif {"silent", 's', "Print only error messages.", &opt_silent, &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"skip_database", 0, "Don't process the database specified as argument", + &opt_skip_database, &opt_skip_database, 0, GET_STR, REQUIRED_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}, @@ -204,8 +212,8 @@ static struct my_option my_long_options[] = {"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.", 0, 0, 0, GET_NO_ARG, - NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Print info about the various stages; Using it 3 times will print out all CHECK, RENAME and ALTER TABLE during the check phase.", + 0, 0, 0, GET_NO_ARG, 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}, {"process-views", 0, @@ -266,8 +274,11 @@ static void usage(void) puts("mysqlrepair: The default option will be -r"); puts("mysqlanalyze: The default option will be -a"); puts("mysqloptimize: The default option will be -o\n"); - puts("Please consult the MariaDB/MySQL knowledgebase at"); - puts("http://kb.askmonty.org/v/mysqlcheck for latest information about"); + printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); + printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n", + my_progname); + puts("Please consult the MariaDB Knowledge Base at"); + puts("https://mariadb.com/kb/en/mysqlcheck for latest information about"); puts("this program."); print_defaults("my", load_default_groups); puts(""); @@ -732,8 +743,10 @@ static int process_all_tables_in_db(char *database) } /* process_all_tables_in_db */ -static int run_query(const char *query) +static int run_query(const char *query, my_bool log_query) { + if (verbose >=3 && log_query) + puts(query); if (mysql_query(sock, query)) { fprintf(stderr, "Failed to %s\n", query); @@ -755,7 +768,7 @@ static int fix_table_storage_name(const char *name) my_snprintf(qbuf, sizeof(qbuf), "RENAME TABLE %`s TO %`s", name, name + 9); - rc= run_query(qbuf); + rc= run_query(qbuf, 1); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); DBUG_RETURN(rc); @@ -771,7 +784,7 @@ static int fix_database_storage_name(const char *name) DBUG_RETURN(1); my_snprintf(qbuf, sizeof(qbuf), "ALTER DATABASE %`s UPGRADE DATA DIRECTORY " "NAME", name); - rc= run_query(qbuf); + rc= run_query(qbuf, 1); if (verbose) printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); DBUG_RETURN(rc); @@ -788,12 +801,16 @@ static int rebuild_table(char *name) if (!query) DBUG_RETURN(1); ptr= strxmov(query, "ALTER TABLE ", name, " FORCE", NullS); + if (verbose >= 3) + puts(query); if (mysql_real_query(sock, query, (ulong)(ptr - query))) { fprintf(stderr, "Failed to %s\n", query); fprintf(stderr, "Error: %s\n", mysql_error(sock)); rc= 1; } + if (verbose) + printf("%-50s %s\n", name, rc ? "FAILED" : "FIXED"); my_free(query); DBUG_RETURN(rc); } @@ -802,6 +819,9 @@ static int process_one_db(char *database) { DBUG_ENTER("process_one_db"); + if (opt_skip_database && !strcmp(database, opt_skip_database)) + DBUG_RETURN(0); + if (verbose) puts(database); if (what_to_do == DO_FIX_NAMES) @@ -840,7 +860,7 @@ static int use_db(char *database) static int disable_binlog() { const char *stmt= "SET SQL_LOG_BIN=0"; - return run_query(stmt); + return run_query(stmt, 0); } static int handle_request_for_tables(char *tables, size_t length, @@ -890,6 +910,7 @@ static int handle_request_for_tables(char *tables, size_t length, case DO_ANALYZE: DBUG_ASSERT(!view); op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG"; + if (opt_persistent_all) end = strmov(end, " PERSISTENT FOR ALL"); break; case DO_OPTIMIZE: DBUG_ASSERT(!view); @@ -917,12 +938,14 @@ static int handle_request_for_tables(char *tables, size_t length, org= ptr= strmov(strmov(query, op), tab_view); ptr= fix_table_name(ptr, tables); - strmake(table_name_buff, org, min((int) sizeof(table_name_buff)-1, - (int) (ptr - org))); + strmake(table_name_buff, org, MY_MIN((int) sizeof(table_name_buff)-1, + (int) (ptr - org))); table_name= table_name_buff; ptr= strxmov(ptr, " ", options, NullS); query_length= (size_t) (ptr - query); } + if (verbose >= 3) + puts(query); if (mysql_real_query(sock, query, query_length)) { sprintf(message, "when executing '%s%s... %s'", op, tab_view, options); @@ -1019,31 +1042,9 @@ static void print_result() printf("%s\n%-9s: %s", row[0], row[2], row[3]); if (opt_auto_repair && strcmp(row[2],"note")) { - const char *alter_txt= strstr(row[3], "ALTER TABLE"); found_error=1; - if (alter_txt) - { + if (opt_auto_repair && strstr(row[3], "ALTER TABLE") != NULL) table_rebuild=1; - if (!strncmp(row[3], KEY_PARTITIONING_CHANGED_STR, - strlen(KEY_PARTITIONING_CHANGED_STR)) && - strstr(alter_txt, "PARTITION BY")) - { - if (strlen(alter_txt) >= MAX_ALTER_STR_SIZE) - { - printf("Error: Alter command too long (>= %d)," - " please do \"%s\" or dump/reload to fix it!\n", - MAX_ALTER_STR_SIZE, - alter_txt); - table_rebuild= 0; - prev_alter[0]= 0; - } - else - { - strncpy(prev_alter, alter_txt, MAX_ALTER_STR_SIZE-1); - prev_alter[MAX_ALTER_STR_SIZE-1]= 0; - } - } - } } } else @@ -1057,7 +1058,7 @@ static void print_result() if (table_rebuild) { if (prev_alter[0]) - insert_dynamic(&alter_table_cmds, (uchar*) prev_alter); + insert_dynamic(&alter_table_cmds, prev_alter); else insert_table_name(&tables4rebuild, prev, length_of_db); } @@ -1081,8 +1082,12 @@ static int dbConnect(char *host, char *user, char *passwd) mysql_options(&mysql_connection, MYSQL_OPT_COMPRESS, NullS); #ifdef HAVE_OPENSSL if (opt_use_ssl) + { mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); @@ -1096,6 +1101,9 @@ static int dbConnect(char *host, char *user, char *passwd) mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth); mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); + mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqlcheck"); if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd, NULL, opt_mysql_port, opt_mysql_unix_port, 0))) { @@ -1172,10 +1180,14 @@ int main(int argc, char **argv) } if (opt_auto_repair && - (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64) || - my_init_dynamic_array(&views4repair, sizeof(char)*(NAME_LEN*2+2),16,64) || - my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,64) || - my_init_dynamic_array(&alter_table_cmds, MAX_ALTER_STR_SIZE, 0, 1))) + (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16, + 64, MYF(0)) || + my_init_dynamic_array(&views4repair, sizeof(char)*(NAME_LEN*2+2),16, + 64, MYF(0)) || + my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16, + 64, MYF(0)) || + my_init_dynamic_array(&alter_table_cmds, MAX_ALTER_STR_SIZE, 0, 1, + MYF(0)))) goto end; if (opt_alldbs) @@ -1201,7 +1213,7 @@ int main(int argc, char **argv) for (i = 0; i < tables4rebuild.elements ; i++) rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i)); for (i = 0; i < alter_table_cmds.elements ; i++) - run_query((char*) dynamic_array_ptr(&alter_table_cmds, i)); + run_query((char*) dynamic_array_ptr(&alter_table_cmds, i), 1); if (!opt_silent && views4repair.elements) puts("\nRepairing views"); for (i = 0; i < views4repair.elements ; i++) @@ -1210,7 +1222,7 @@ int main(int argc, char **argv) handle_request_for_tables(name, fixed_name_length(name), TRUE, TRUE); } } - ret= test(first_error); + ret= MY_TEST(first_error); end: dbDisconnect(current_host); diff --git a/client/mysqldump.c b/client/mysqldump.c index 16b39b77cf1..153761ed510 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -39,7 +39,7 @@ ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ -#define DUMP_VERSION "10.14" +#define DUMP_VERSION "10.15" #include <my_global.h> #include <my_sys.h> @@ -87,6 +87,9 @@ /* Chars needed to store LONGLONG, excluding trailing '\0'. */ #define LONGLONG_LEN 20 +/* Max length GTID position that we will output. */ +#define MAX_GTID_LENGTH 1024 + static void add_load_option(DYNAMIC_STRING *str, const char *option, const char *option_value); static ulong find_set(TYPELIB *lib, const char *x, size_t length, @@ -94,7 +97,7 @@ static ulong find_set(TYPELIB *lib, const char *x, size_t length, static char *alloc_query_str(ulong size); static void field_escape(DYNAMIC_STRING* in, const char *from); -static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, +static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_med= 1, quick= 1, extended_insert= 1, lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0, opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0, @@ -134,10 +137,23 @@ static ulong opt_compatible_mode= 0; #define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2 static uint opt_mysql_port= 0, opt_master_data; static uint opt_slave_data; +static uint opt_use_gtid; static uint my_end_arg; static char * opt_mysql_unix_port=0; static int first_error=0; +/* + multi_source is 0 if old server or 2 if server that support multi source + This is choosen this was as multi_source has 2 extra columns first in + SHOW ALL SLAVES STATUS. +*/ +static uint multi_source= 0; static DYNAMIC_STRING extended_row; +static DYNAMIC_STRING dynamic_where; +static MYSQL_RES *get_table_name_result= NULL; +static MEM_ROOT glob_root; +static MYSQL_RES *routine_res, *routine_list_res; + + #include <sslopt-vars.h> FILE *md_result_file= 0; FILE *stderror_file=0; @@ -193,6 +209,8 @@ const char *compatible_mode_names[]= TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1, "", compatible_mode_names, NULL}; +#define MED_ENGINES "MRG_MyISAM, MRG_ISAM, CONNECT, OQGRAPH, SPIDER, VP, FEDERATED" + HASH ignore_table; static struct my_option my_long_options[] = @@ -226,8 +244,8 @@ static struct my_option my_long_options[] = &opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (char**) &charsets_dir, - (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"comments", 'i', "Write additional information.", &opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -264,8 +282,8 @@ static struct my_option my_long_options[] = {"debug", '#', "This is a non-debug version. Catch this and exit.", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log.", (char**) &default_dbug_option, - (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", &debug_check_flag, &debug_check_flag, 0, @@ -340,6 +358,13 @@ static struct my_option my_long_options[] = {"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}, + {"gtid", OPT_USE_GTID, "Used together with --master-data=1 or --dump-slave=1." + "When enabled, the output from those options will set the GTID position " + "instead of the binlog file and offset; the file/offset will appear only as " + "a comment. When disabled, the GTID position will still appear in the " + "output, but only commented.", + &opt_use_gtid, &opt_use_gtid, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, " @@ -412,6 +437,9 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-data", 'd', "No row information.", &opt_no_data, &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-data-med", 0, "No row information for engines that " + "Manage External Data (" MED_ENGINES ").", &opt_no_data_med, + &opt_no_data_med, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"no-set-names", 'N', "Same as --skip-set-charset.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"opt", OPT_OPTIMIZE, @@ -866,7 +894,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), &err_ptr, &err_len); if (err_len) { - strmake(buff, err_ptr, min(sizeof(buff) - 1, err_len)); + strmake(buff, err_ptr, MY_MIN(sizeof(buff) - 1, err_len)); fprintf(stderr, "Invalid mode to --compatible: %s\n", buff); exit(1); } @@ -1192,6 +1220,90 @@ check_consistent_binlog_pos(char *binlog_pos_file, char *binlog_pos_offset) return (found == 2); } + +/* + Get the GTID position corresponding to a given old-style binlog position. + This uses BINLOG_GTID_POS(). The advantage is that the GTID position can + be obtained completely non-blocking in this way (without the need for + FLUSH TABLES WITH READ LOCK), as the old-style position can be obtained + with START TRANSACTION WITH CONSISTENT SNAPSHOT. + + Returns 0 if ok, non-zero if error. +*/ +static int +get_binlog_gtid_pos(char *binlog_pos_file, char *binlog_pos_offset, + char *out_gtid_pos) +{ + DYNAMIC_STRING query; + MYSQL_RES *res; + MYSQL_ROW row; + int err; + char file_buf[FN_REFLEN*2+1], offset_buf[LONGLONG_LEN*2+1]; + size_t len_pos_file= strlen(binlog_pos_file); + size_t len_pos_offset= strlen(binlog_pos_offset); + + if (len_pos_file >= FN_REFLEN || len_pos_offset > LONGLONG_LEN) + return 0; + mysql_real_escape_string(mysql, file_buf, binlog_pos_file, len_pos_file); + mysql_real_escape_string(mysql, offset_buf, binlog_pos_offset, len_pos_offset); + init_dynamic_string_checked(&query, "SELECT BINLOG_GTID_POS('", 256, 1024); + dynstr_append_checked(&query, file_buf); + dynstr_append_checked(&query, "', '"); + dynstr_append_checked(&query, offset_buf); + dynstr_append_checked(&query, "')"); + + err= mysql_query_with_error_report(mysql, &res, query.str); + dynstr_free(&query); + if (err) + return err; + + err= 1; + if ((row= mysql_fetch_row(res))) + { + strmake(out_gtid_pos, row[0], MAX_GTID_LENGTH-1); + err= 0; + } + mysql_free_result(res); + + return err; +} + + +/* + Get the GTID position on a master or slave. + The parameter MASTER is non-zero to get the position on a master + (@@gtid_binlog_pos) or zero for a slave (@@gtid_slave_pos). + + This uses the @@gtid_binlog_pos or @@gtid_slave_pos, so requires FLUSH TABLES + WITH READ LOCK or similar to be consistent. + + Returns 0 if ok, non-zero for error. +*/ +static int +get_gtid_pos(char *out_gtid_pos, int master) +{ + MYSQL_RES *res; + MYSQL_ROW row; + int found; + + if (mysql_query_with_error_report(mysql, &res, + (master ? + "SELECT @@GLOBAL.gtid_binlog_pos" : + "SELECT @@GLOBAL.gtid_slave_pos"))) + return 1; + + found= 0; + if ((row= mysql_fetch_row(res))) + { + strmake(out_gtid_pos, row[0], MAX_GTID_LENGTH-1); + found++; + } + mysql_free_result(res); + + return (found != 1); +} + + static char *my_case_str(const char *str, size_t str_len, const char *token, @@ -1477,14 +1589,26 @@ static void free_resources() { if (md_result_file && md_result_file != stdout) my_fclose(md_result_file, MYF(0)); + if (get_table_name_result) + mysql_free_result(get_table_name_result); + if (routine_res) + mysql_free_result(routine_res); + if (routine_list_res) + mysql_free_result(routine_list_res); + if (mysql) + { + mysql_close(mysql); + mysql= 0; + } + my_free(order_by); my_free(opt_password); my_free(current_host); + free_root(&glob_root, MYF(0)); if (my_hash_inited(&ignore_table)) my_hash_free(&ignore_table); - if (extended_insert) - dynstr_free(&extended_row); - if (insert_pat_inited) - dynstr_free(&insert_pat); + dynstr_free(&extended_row); + dynstr_free(&dynamic_where); + dynstr_free(&insert_pat); if (defaults_argv) free_defaults(defaults_argv); mysql_library_end(); @@ -1501,8 +1625,6 @@ static void maybe_exit(int error) ignore_errors= 1; /* don't want to recurse, if something fails below */ if (opt_slave_data) do_start_slave_sql(mysql); - if (mysql) - mysql_close(mysql); free_resources(); exit(error); } @@ -1523,8 +1645,12 @@ static int connect_to_db(char *host, char *user,char *passwd) mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS); #ifdef HAVE_OPENSSL if (opt_use_ssl) + { mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); #endif @@ -1542,6 +1668,9 @@ static int connect_to_db(char *host, char *user,char *passwd) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth); + mysql_options(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(&mysql_connection, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqldump"); mysql= &mysql_connection; /* So we can mysql_close() it properly */ if (!mysql_real_connect(&mysql_connection,host,user,passwd, NULL,opt_mysql_port,opt_mysql_unix_port, 0)) @@ -1588,6 +1717,7 @@ static void dbDisconnect(char *host) { verbose_msg("-- Disconnecting from %s...\n", host ? host : "localhost"); mysql_close(mysql); + mysql= 0; } /* dbDisconnect */ @@ -2294,7 +2424,6 @@ static uint dump_routines_for_db(char *db) char *routine_name; int i; FILE *sql_file= md_result_file; - MYSQL_RES *routine_res, *routine_list_res; MYSQL_ROW row, routine_list_row; char db_cl_name[MY_CS_NAME_SIZE]; @@ -2349,7 +2478,11 @@ static uint dump_routines_for_db(char *db) routine_type[i], routine_name); if (mysql_query_with_error_report(mysql, &routine_res, query_buff)) + { + mysql_free_result(routine_list_res); + routine_list_res= 0; DBUG_RETURN(1); + } while ((row= mysql_fetch_row(routine_res))) { @@ -2367,7 +2500,8 @@ static uint dump_routines_for_db(char *db) print_comment(sql_file, 1, "-- does %s have permissions on mysql.proc?\n\n", current_user); - maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", current_user, query_buff); + maybe_die(EX_MYSQLERR,"%s has insufficent privileges to %s!", + current_user, query_buff); } else if (strlen(row[2])) { @@ -2390,6 +2524,9 @@ static uint dump_routines_for_db(char *db) if (switch_db_collation(sql_file, db, ";", db_cl_name, row[5], &db_cl_altered)) { + mysql_free_result(routine_res); + mysql_free_result(routine_list_res); + routine_res= routine_list_res= 0; DBUG_RETURN(1); } @@ -2435,17 +2572,24 @@ static uint dump_routines_for_db(char *db) if (db_cl_altered) { if (restore_db_collation(sql_file, db, ";", db_cl_name)) + { + mysql_free_result(routine_res); + mysql_free_result(routine_list_res); + routine_res= routine_list_res= 0; DBUG_RETURN(1); + } } } } } /* end of routine printing */ mysql_free_result(routine_res); + routine_res= 0; } /* end of list of routines */ } mysql_free_result(routine_list_res); + routine_list_res= 0; } /* end of for i (0 .. 1) */ if (opt_xml) @@ -2567,13 +2711,20 @@ static uint get_table_structure(char *table, char *db, char *table_type, if (switch_character_set_results(mysql, "binary") || mysql_query_with_error_report(mysql, &result, buff) || switch_character_set_results(mysql, default_charset)) + { + my_free(order_by); + order_by= 0; DBUG_RETURN(0); + } if (path) { if (!(sql_file= open_sql_file_for_table(table, O_WRONLY))) + { + my_free(order_by); + order_by= 0; DBUG_RETURN(0); - + } write_header(sql_file, db); } @@ -3143,10 +3294,6 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, continue; } - query_str= cover_definer_clause(row[2], strlen(row[2]), - C_STRING_WITH_LEN("50017"), - C_STRING_WITH_LEN("50003"), - C_STRING_WITH_LEN(" TRIGGER")); if (switch_db_collation(sql_file, db_name, ";", db_cl_name, row[5], &db_cl_altered)) DBUG_RETURN(TRUE); @@ -3158,12 +3305,18 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, switch_sql_mode(sql_file, ";", row[1]); + query_str= cover_definer_clause(row[2], strlen(row[2]), + C_STRING_WITH_LEN("50017"), + C_STRING_WITH_LEN("50003"), + C_STRING_WITH_LEN(" TRIGGER")); fprintf(sql_file, "DELIMITER ;;\n" "/*!50003 %s */;;\n" "DELIMITER ;\n", (const char *) (query_str != NULL ? query_str : row[2])); + my_free(query_str); + restore_sql_mode(sql_file, ";"); restore_cs_variables(sql_file, ";"); @@ -3172,8 +3325,6 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, if (restore_db_collation(sql_file, db_name, ";", db_cl_name)) DBUG_RETURN(TRUE); } - - my_free(query_str); } DBUG_RETURN(FALSE); @@ -3264,13 +3415,14 @@ static int dump_triggers_for_table(char *table_name, char *db_name) { MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql); - if (!show_create_trigger_rs || - dump_trigger(sql_file, show_create_trigger_rs, db_name, db_cl_name)) - goto done; - + int error= (!show_create_trigger_rs || + dump_trigger(sql_file, show_create_trigger_rs, db_name, + db_cl_name)); mysql_free_result(show_create_trigger_rs); + if (error) + goto done; } - + } if (opt_xml) @@ -3517,12 +3669,14 @@ static void dump_table(char *table, char *db) { dynstr_append_checked(&query_string, " ORDER BY "); dynstr_append_checked(&query_string, order_by); + my_free(order_by); + order_by= 0; } if (mysql_real_query(mysql, query_string.str, query_string.length)) { - DB_error(mysql, "when executing 'SELECT INTO OUTFILE'"); dynstr_free(&query_string); + DB_error(mysql, "when executing 'SELECT INTO OUTFILE'"); DBUG_VOID_RETURN; } } @@ -3548,6 +3702,8 @@ static void dump_table(char *table, char *db) dynstr_append_checked(&query_string, " ORDER BY "); dynstr_append_checked(&query_string, order_by); + my_free(order_by); + order_by= 0; } if (!opt_xml && !opt_compact) @@ -3557,6 +3713,7 @@ static void dump_table(char *table, char *db) } if (mysql_query_with_error_report(mysql, 0, query_string.str)) { + dynstr_free(&query_string); DB_error(mysql, "when retrieving data from server"); goto err; } @@ -3566,6 +3723,7 @@ static void dump_table(char *table, char *db) res=mysql_store_result(mysql); if (!res) { + dynstr_free(&query_string); DB_error(mysql, "when retrieving data from server"); goto err; } @@ -3881,23 +4039,22 @@ err: static char *getTableName(int reset) { - static MYSQL_RES *res= NULL; - MYSQL_ROW row; + MYSQL_ROW row; - if (!res) + if (!get_table_name_result) { - if (!(res= mysql_list_tables(mysql,NullS))) + if (!(get_table_name_result= mysql_list_tables(mysql,NullS))) return(NULL); } - if ((row= mysql_fetch_row(res))) + if ((row= mysql_fetch_row(get_table_name_result))) return((char*) row[0]); if (reset) - mysql_data_seek(res,0); /* We want to read again */ + mysql_data_seek(get_table_name_result,0); /* We want to read again */ else { - mysql_free_result(res); - res= NULL; + mysql_free_result(get_table_name_result); + get_table_name_result= NULL; } return(NULL); } /* getTableName */ @@ -3914,46 +4071,44 @@ static int dump_all_tablespaces() static int dump_tablespaces_for_tables(char *db, char **table_names, int tables) { - DYNAMIC_STRING where; int r; int i; char name_buff[NAME_LEN*2+3]; mysql_real_escape_string(mysql, name_buff, db, (ulong)strlen(db)); - init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN (" + init_dynamic_string_checked(&dynamic_where, " AND TABLESPACE_NAME IN (" "SELECT DISTINCT TABLESPACE_NAME FROM" " INFORMATION_SCHEMA.PARTITIONS" " WHERE" " TABLE_SCHEMA='", 256, 1024); - dynstr_append_checked(&where, name_buff); - dynstr_append_checked(&where, "' AND TABLE_NAME IN ("); + dynstr_append_checked(&dynamic_where, name_buff); + dynstr_append_checked(&dynamic_where, "' AND TABLE_NAME IN ("); for (i=0 ; i<tables ; i++) { mysql_real_escape_string(mysql, name_buff, table_names[i], (ulong)strlen(table_names[i])); - dynstr_append_checked(&where, "'"); - dynstr_append_checked(&where, name_buff); - dynstr_append_checked(&where, "',"); + dynstr_append_checked(&dynamic_where, "'"); + dynstr_append_checked(&dynamic_where, name_buff); + dynstr_append_checked(&dynamic_where, "',"); } - dynstr_trunc(&where, 1); - dynstr_append_checked(&where,"))"); + dynstr_trunc(&dynamic_where, 1); + dynstr_append_checked(&dynamic_where,"))"); - DBUG_PRINT("info",("Dump TS for Tables where: %s",where.str)); - r= dump_tablespaces(where.str); - dynstr_free(&where); + DBUG_PRINT("info",("Dump TS for Tables where: %s",dynamic_where.str)); + r= dump_tablespaces(dynamic_where.str); + dynstr_free(&dynamic_where); return r; } static int dump_tablespaces_for_databases(char** databases) { - DYNAMIC_STRING where; int r; int i; - init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN (" + init_dynamic_string_checked(&dynamic_where, " AND TABLESPACE_NAME IN (" "SELECT DISTINCT TABLESPACE_NAME FROM" " INFORMATION_SCHEMA.PARTITIONS" " WHERE" @@ -3964,16 +4119,16 @@ static int dump_tablespaces_for_databases(char** databases) char db_name_buff[NAME_LEN*2+3]; mysql_real_escape_string(mysql, db_name_buff, databases[i], (ulong)strlen(databases[i])); - dynstr_append_checked(&where, "'"); - dynstr_append_checked(&where, db_name_buff); - dynstr_append_checked(&where, "',"); + dynstr_append_checked(&dynamic_where, "'"); + dynstr_append_checked(&dynamic_where, db_name_buff); + dynstr_append_checked(&dynamic_where, "',"); } - dynstr_trunc(&where, 1); - dynstr_append_checked(&where,"))"); + dynstr_trunc(&dynamic_where, 1); + dynstr_append_checked(&dynamic_where,"))"); - DBUG_PRINT("info",("Dump TS for DBs where: %s",where.str)); - r= dump_tablespaces(where.str); - dynstr_free(&where); + DBUG_PRINT("info",("Dump TS for DBs where: %s",dynamic_where.str)); + r= dump_tablespaces(dynamic_where.str); + dynstr_free(&dynamic_where); return r; } @@ -4381,9 +4536,12 @@ static int dump_all_tables_in_db(char *database) } } if (numrows && mysql_real_query(mysql, query.str, query.length-1)) + { + dynstr_free(&query); DB_error(mysql, "when using LOCK TABLES"); - /* We shall continue here, if --force was given */ - dynstr_free(&query); + /* We shall continue here, if --force was given */ + } + dynstr_free(&query); /* Safe to call twice */ } if (flush_logs) { @@ -4393,6 +4551,14 @@ static int dump_all_tables_in_db(char *database) else verbose_msg("-- dump_all_tables_in_db : logs flushed successfully!\n"); } + if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) + { + verbose_msg("-- Setting savepoint...\n"); + if (mysql_query_with_error_report(mysql, 0, "SAVEPOINT sp")) + { + DBUG_RETURN(1); + } + } while ((table= getTableName(0))) { char *end= strmov(afterdot, table); @@ -4410,6 +4576,23 @@ static int dump_all_tables_in_db(char *database) maybe_exit(EX_MYSQLERR); } } + + /** + ROLLBACK TO SAVEPOINT in --single-transaction mode to release metadata + lock on table which was already dumped. This allows to avoid blocking + concurrent DDL on this table without sacrificing correctness, as we + won't access table second time and dumps created by --single-transaction + mode have validity point at the start of transaction anyway. + Note that this doesn't make --single-transaction mode with concurrent + DDL safe in general case. It just improves situation for people for whom + it might be working. + */ + if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) + { + verbose_msg("-- Rolling back to savepoint sp...\n"); + if (mysql_query_with_error_report(mysql, 0, "ROLLBACK TO SAVEPOINT sp")) + maybe_exit(EX_MYSQLERR); + } } else { @@ -4432,6 +4615,14 @@ static int dump_all_tables_in_db(char *database) } } } + + if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) + { + verbose_msg("-- Releasing savepoint...\n"); + if (mysql_query_with_error_report(mysql, 0, "RELEASE SAVEPOINT sp")) + DBUG_RETURN(1); + } + if (opt_events && mysql_get_server_version(mysql) >= 50106) { DBUG_PRINT("info", ("Dumping events for database %s", database)); @@ -4601,22 +4792,22 @@ static int dump_selected_tables(char *db, char **table_names, int tables) { char table_buff[NAME_LEN*2+3]; DYNAMIC_STRING lock_tables_query; - MEM_ROOT root; char **dump_tables, **pos, **end; DBUG_ENTER("dump_selected_tables"); if (init_dumping(db, init_dumping_tables)) DBUG_RETURN(1); - init_alloc_root(&root, 8192, 0); - if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *)))) + init_alloc_root(&glob_root, 8192, 0, MYF(0)); + if (!(dump_tables= pos= (char**) alloc_root(&glob_root, + tables * sizeof(char *)))) die(EX_EOM, "alloc_root failure."); init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024); for (; tables > 0 ; tables-- , table_names++) { /* the table name passed on commandline may be wrong case */ - if ((*pos= get_actual_table_name(*table_names, &root))) + if ((*pos= get_actual_table_name(*table_names, &glob_root))) { /* Add found table name to lock_tables_query */ if (lock_tables) @@ -4631,7 +4822,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) if (!ignore_errors) { dynstr_free(&lock_tables_query); - free_root(&root, MYF(0)); + free_root(&glob_root, MYF(0)); } maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names); /* We shall countinue here, if --force was given */ @@ -4652,7 +4843,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) if (!ignore_errors) { dynstr_free(&lock_tables_query); - free_root(&root, MYF(0)); + free_root(&glob_root, MYF(0)); } DB_error(mysql, "when doing LOCK TABLES"); /* We shall countinue here, if --force was given */ @@ -4664,7 +4855,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) if (mysql_refresh(mysql, REFRESH_LOG)) { if (!ignore_errors) - free_root(&root, MYF(0)); + free_root(&glob_root, MYF(0)); DB_error(mysql, "when doing refresh"); } /* We shall countinue here, if --force was given */ @@ -4674,6 +4865,16 @@ static int dump_selected_tables(char *db, char **table_names, int tables) if (opt_xml) print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS); + if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) + { + verbose_msg("-- Setting savepoint...\n"); + if (mysql_query_with_error_report(mysql, 0, "SAVEPOINT sp")) + { + free_root(&glob_root, MYF(0)); + DBUG_RETURN(1); + } + } + /* Dump each selected table */ for (pos= dump_tables; pos < end; pos++) { @@ -4686,9 +4887,42 @@ static int dump_selected_tables(char *db, char **table_names, int tables) { if (path) my_fclose(md_result_file, MYF(MY_WME)); + if (!ignore_errors) + free_root(&glob_root, MYF(0)); maybe_exit(EX_MYSQLERR); } } + + /** + ROLLBACK TO SAVEPOINT in --single-transaction mode to release metadata + lock on table which was already dumped. This allows to avoid blocking + concurrent DDL on this table without sacrificing correctness, as we + won't access table second time and dumps created by --single-transaction + mode have validity point at the start of transaction anyway. + Note that this doesn't make --single-transaction mode with concurrent + DDL safe in general case. It just improves situation for people for whom + it might be working. + */ + if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) + { + verbose_msg("-- Rolling back to savepoint sp...\n"); + if (mysql_query_with_error_report(mysql, 0, "ROLLBACK TO SAVEPOINT sp")) + { + if (!ignore_errors) + free_root(&glob_root, MYF(0)); + maybe_exit(EX_MYSQLERR); + } + } + } + + if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) + { + verbose_msg("-- Releasing savepoint...\n"); + if (mysql_query_with_error_report(mysql, 0, "RELEASE SAVEPOINT sp")) + { + free_root(&glob_root, MYF(0)); + DBUG_RETURN(1); + } } /* Dump each selected view */ @@ -4708,9 +4942,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) DBUG_PRINT("info", ("Dumping routines for database %s", db)); dump_routines_for_db(db); } - free_root(&root, MYF(0)); - my_free(order_by); - order_by= 0; + free_root(&glob_root, MYF(0)); if (opt_xml) { fputs("</database>\n", md_result_file); @@ -4722,12 +4954,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } /* dump_selected_tables */ -static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) +static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos, + int have_mariadb_gtid, int use_gtid) { MYSQL_ROW row; MYSQL_RES *UNINIT_VAR(master); char binlog_pos_file[FN_REFLEN]; char binlog_pos_offset[LONGLONG_LEN+1]; + char gtid_pos[MAX_GTID_LENGTH]; char *file, *offset; const char *comment_prefix= (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : ""; @@ -4738,10 +4972,14 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) return 1; file= binlog_pos_file; offset= binlog_pos_offset; + if (have_mariadb_gtid && + get_binlog_gtid_pos(binlog_pos_file, binlog_pos_offset, gtid_pos)) + return 1; } else { - if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS")) + if (mysql_query_with_error_report(mysql_con, &master, + "SHOW MASTER STATUS")) return 1; row= mysql_fetch_row(master); @@ -4766,6 +5004,9 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) return 0; } } + + if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 1)) + return 1; } /* SHOW MASTER STATUS reports file and position */ @@ -4774,7 +5015,19 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) "recovery from\n--\n\n"); fprintf(md_result_file, "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", - comment_prefix, file, offset); + (use_gtid ? "-- " : comment_prefix), file, offset); + if (have_mariadb_gtid) + { + print_comment(md_result_file, 0, + "\n--\n-- GTID to start replication from\n--\n\n"); + if (use_gtid) + fprintf(md_result_file, + "%sCHANGE MASTER TO MASTER_USE_GTID=slave_pos;\n", + comment_prefix); + fprintf(md_result_file, + "%sSET GLOBAL gtid_slave_pos='%s';\n", + (!use_gtid ? "-- " : comment_prefix), gtid_pos); + } check_io(md_result_file); if (!consistent_binlog_pos) @@ -4786,29 +5039,37 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) static int do_stop_slave_sql(MYSQL *mysql_con) { MYSQL_RES *slave; - /* We need to check if the slave sql is running in the first place */ - if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS")) + MYSQL_ROW row; + + if (mysql_query_with_error_report(mysql_con, &slave, + multi_source ? + "SHOW ALL SLAVES STATUS" : + "SHOW SLAVE STATUS")) return(1); - else + + /* Loop over all slaves */ + while ((row= mysql_fetch_row(slave))) { - MYSQL_ROW row= mysql_fetch_row(slave); - if (row && row[11]) + if (row[11 + multi_source]) { /* if SLAVE SQL is not running, we don't stop it */ - if (!strcmp(row[11],"No")) + if (strcmp(row[11 + multi_source], "No")) { - mysql_free_result(slave); - /* Silently assume that they don't have the slave running */ - return(0); + char query[160]; + if (multi_source) + sprintf(query, "STOP SLAVE '%.80s' SQL_THREAD", row[0]); + else + strmov(query, "STOP SLAVE SQL_THREAD"); + + if (mysql_query_with_error_report(mysql_con, 0, query)) + { + mysql_free_result(slave); + return 1; + } } } } mysql_free_result(slave); - - /* now, stop slave if running */ - if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD")) - return(1); - return(0); } @@ -4817,7 +5078,10 @@ static int add_stop_slave(void) if (opt_comments) fprintf(md_result_file, "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n"); - fprintf(md_result_file, "STOP SLAVE;\n"); + if (multi_source) + fprintf(md_result_file, "STOP ALL SLAVES;\n"); + else + fprintf(md_result_file, "STOP SLAVE;\n"); return(0); } @@ -4826,16 +5090,28 @@ static int add_slave_statements(void) if (opt_comments) fprintf(md_result_file, "\n--\n-- start slave statement to make a recovery dump)\n--\n\n"); - fprintf(md_result_file, "START SLAVE;\n"); + if (multi_source) + fprintf(md_result_file, "START ALL SLAVES;\n"); + else + fprintf(md_result_file, "START SLAVE;\n"); return(0); } -static int do_show_slave_status(MYSQL *mysql_con) +static int do_show_slave_status(MYSQL *mysql_con, int use_gtid, + int have_mariadb_gtid) { - MYSQL_RES *slave= 0; + MYSQL_RES *UNINIT_VAR(slave); + MYSQL_ROW row; const char *comment_prefix= (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : ""; - if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS")) + const char *gtid_comment_prefix= (use_gtid ? comment_prefix : "-- "); + const char *nogtid_comment_prefix= (!use_gtid ? comment_prefix : "-- "); + int set_gtid_done= 0; + + if (mysql_query_with_error_report(mysql_con, &slave, + multi_source ? + "SHOW ALL SLAVES STATUS" : + "SHOW SLAVE STATUS")) { if (!ignore_errors) { @@ -4845,65 +5121,103 @@ static int do_show_slave_status(MYSQL *mysql_con) mysql_free_result(slave); return 1; } - else + + while ((row= mysql_fetch_row(slave))) { - MYSQL_ROW row= mysql_fetch_row(slave); - if (row && row[9] && row[21]) + if (multi_source && !set_gtid_done) + { + char gtid_pos[MAX_GTID_LENGTH]; + if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 0)) + return 1; + if (opt_comments) + fprintf(md_result_file, "\n--\n-- Gtid position to start replication " + "from\n--\n\n"); + fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n", + gtid_comment_prefix, gtid_pos); + set_gtid_done= 1; + } + if (row[9 + multi_source] && row[21 + multi_source]) { + if (use_gtid) + { + if (multi_source) + fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO " + "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix, row[0]); + else + fprintf(md_result_file, "%sCHANGE MASTER TO " + "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix); + } + /* SHOW MASTER STATUS reports file and position */ if (opt_comments) fprintf(md_result_file, "\n--\n-- Position to start replication or point-in-time " "recovery from (the master of this slave)\n--\n\n"); - fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix); - + if (multi_source) + fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO ", + nogtid_comment_prefix, row[0]); + else + fprintf(md_result_file, "%sCHANGE MASTER TO ", nogtid_comment_prefix); + if (opt_include_master_host_port) { - if (row[1]) - fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]); + if (row[1 + multi_source]) + fprintf(md_result_file, "MASTER_HOST='%s', ", row[1 + multi_source]); if (row[3]) - fprintf(md_result_file, "MASTER_PORT=%s, ", row[3]); + fprintf(md_result_file, "MASTER_PORT=%s, ", row[3 + multi_source]); } fprintf(md_result_file, - "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]); + "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", + row[9 + multi_source], row[21 + multi_source]); check_io(md_result_file); } - mysql_free_result(slave); } + mysql_free_result(slave); return 0; } static int do_start_slave_sql(MYSQL *mysql_con) { MYSQL_RES *slave; + MYSQL_ROW row; + int error= 0; + DBUG_ENTER("do_start_slave_sql"); + /* We need to check if the slave sql is stopped in the first place */ - if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS")) - return(1); - else + if (mysql_query_with_error_report(mysql_con, &slave, + multi_source ? + "SHOW ALL SLAVES STATUS" : + "SHOW SLAVE STATUS")) + DBUG_RETURN(1); + + while ((row= mysql_fetch_row(slave))) { - MYSQL_ROW row= mysql_fetch_row(slave); - if (row && row[11]) + DBUG_PRINT("info", ("Connection: '%s' status: '%s'", + multi_source ? row[0] : "", row[11 + multi_source])); + if (row[11 + multi_source]) { /* if SLAVE SQL is not running, we don't start it */ - if (!strcmp(row[11],"Yes")) + if (strcmp(row[11 + multi_source], "Yes")) { - mysql_free_result(slave); - /* Silently assume that they don't have the slave running */ - return(0); + char query[160]; + if (multi_source) + sprintf(query, "START SLAVE '%.80s'", row[0]); + else + strmov(query, "START SLAVE"); + + if (mysql_query_with_error_report(mysql_con, 0, query)) + { + fprintf(stderr, "%s: Error: Unable to start slave '%s'\n", + my_progname_short, multi_source ? row[0] : ""); + error= 1; + } } } } mysql_free_result(slave); - - /* now, start slave if stopped */ - if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE")) - { - fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short); - return 1; - } - return(0); + DBUG_RETURN(error); } @@ -4917,12 +5231,13 @@ static int do_flush_tables_read_lock(MYSQL *mysql_con) FLUSH TABLES is to lower the probability of a stage where both mysqldump and most client connections are stalled. Of course, if a second long update starts between the two FLUSHes, we have that bad stall. + + We use the LOCAL option, as we do not want the FLUSH TABLES replicated to + other servers. */ return - ( mysql_query_with_error_report(mysql_con, 0, - ((opt_master_data != 0) ? - "FLUSH /*!40101 LOCAL */ TABLES" : - "FLUSH TABLES")) || + ( mysql_query_with_error_report(mysql_con, 0, + "FLUSH /*!40101 LOCAL */ TABLES") || mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES WITH READ LOCK") ); } @@ -5027,7 +5342,7 @@ static ulong find_set(TYPELIB *lib, const char *x, size_t length, for (; pos != end && *pos != ','; pos++) ; var_len= (uint) (pos - start); - strmake(buff, start, min(sizeof(buff) - 1, var_len)); + strmake(buff, start, MY_MIN(sizeof(buff) - 1, var_len)); find= find_type(buff, lib, FIND_TYPE_BASIC); if (!find) { @@ -5151,11 +5466,12 @@ char check_if_ignore_table(const char *table_name, char *table_type) /* If these two types, we do want to skip dumping the table */ - if (!opt_no_data && - (!my_strcasecmp(&my_charset_latin1, table_type, "MRG_MyISAM") || - !strcmp(table_type,"MRG_ISAM") || - !strcmp(table_type,"FEDERATED"))) - result= IGNORE_DATA; + if (!opt_no_data && opt_no_data_med) + { + const char *found= strstr(" " MED_ENGINES ",", table_type); + if (found && found[-1] == ' ' && found[strlen(table_type)] == ',') + result= IGNORE_DATA; + } } mysql_free_result(res); DBUG_RETURN(result); @@ -5542,6 +5858,7 @@ int main(int argc, char **argv) char bin_log_name[FN_REFLEN]; int exit_code; int consistent_binlog_pos= 0; + int have_mariadb_gtid= 0; MY_INIT(argv[0]); sf_leaking_memory=1; /* don't report memory leaks on early exits */ @@ -5580,6 +5897,13 @@ int main(int argc, char **argv) if (!path) write_header(md_result_file, *argv); + /* Check if the server support multi source */ + if (mysql_get_server_version(mysql) >= 100000) + { + multi_source= 2; + have_mariadb_gtid= 1; + } + if (opt_slave_data && do_stop_slave_sql(mysql)) goto err; @@ -5625,9 +5949,12 @@ int main(int argc, char **argv) /* Add 'STOP SLAVE to beginning of dump */ if (opt_slave_apply && add_stop_slave()) goto err; - if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos)) + + if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos, + have_mariadb_gtid, opt_use_gtid)) goto err; - if (opt_slave_data && do_show_slave_status(mysql)) + if (opt_slave_data && do_show_slave_status(mysql, opt_use_gtid, + have_mariadb_gtid)) goto err; if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */ goto err; diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 850a851b4aa..aee445d387d 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -442,8 +442,12 @@ static MYSQL *db_connect(char *host, char *database, (char*) &opt_local_file); #ifdef HAVE_OPENSSL if (opt_use_ssl) + { mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); #endif @@ -461,6 +465,9 @@ static MYSQL *db_connect(char *host, char *database, 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, 0))) @@ -489,7 +496,6 @@ static void db_disconnect(char *host, MYSQL *mysql) } - static void safe_exit(int error, MYSQL *mysql) { if (error && ignore_errors) @@ -508,7 +514,10 @@ static void safe_exit(int error, MYSQL *mysql) free_defaults(argv_to_free); mysql_library_end(); my_free(opt_password); - my_end(my_end_arg); + if (error) + sf_leaking_memory= 1; /* dirty exit, some threads are still running */ + else + my_end(my_end_arg); /* clean exit */ exit(error); } diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 4349c063ee8..eec4a8d3268 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -68,10 +68,12 @@ int main(int argc, char **argv) my_bool first_argument_uses_wildcards=0; char *wild; MYSQL mysql; + static char **defaults_argv; MY_INIT(argv[0]); sf_leaking_memory=1; /* don't report memory leaks on early exits */ if (load_defaults("my",load_default_groups,&argc,&argv)) exit(1); + defaults_argv=argv; get_options(&argc,&argv); @@ -118,8 +120,12 @@ int main(int argc, char **argv) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); #ifdef HAVE_OPENSSL if (opt_use_ssl) + { mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&opt_ssl_verify_server_cert); #endif @@ -137,13 +143,17 @@ int main(int argc, char **argv) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqlshow"); if (!(mysql_real_connect(&mysql,host,user,opt_password, (first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port, 0))) { fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); - exit(1); + error= 1; + goto error; } mysql.reconnect= 1; @@ -162,11 +172,14 @@ int main(int argc, char **argv) error=list_fields(&mysql,argv[0],argv[1],wild); break; } +error: mysql_close(&mysql); /* Close & free connection */ my_free(opt_password); + mysql_server_end(); #ifdef HAVE_SMEM my_free(shared_memory_base_name); #endif + free_defaults(defaults_argv); my_end(my_end_arg); exit(error ? 1 : 0); return 0; /* No compiler warnings */ diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 4f6fc7d45cb..b3229980e77 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -85,9 +85,7 @@ TODO: #include <mysqld_error.h> #include <my_dir.h> #include <signal.h> -#include <stdarg.h> #include <sslopt-vars.h> -#include <sys/types.h> #ifndef __WIN__ #include <sys/wait.h> #endif @@ -170,6 +168,7 @@ static ulonglong auto_generate_sql_number; const char *concurrency_str= NULL; static char *create_string; uint *concurrency; +static char mysql_charsets_dir[FN_REFLEN+1]; const char *default_dbug_option="d:t:o,/tmp/mysqlslap.trace"; const char *opt_csv_str; @@ -301,8 +300,12 @@ void set_mysql_connect_options(MYSQL *mysql) mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS); #ifdef HAVE_OPENSSL if (opt_use_ssl) + { mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } #endif if (opt_protocol) mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); @@ -359,6 +362,9 @@ int main(int argc, char **argv) if (opt_default_auth && *opt_default_auth) mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqlslap"); if (!opt_only_print) { if (!(mysql_real_connect(&mysql, host, user, opt_password, @@ -367,6 +373,7 @@ int main(int argc, char **argv) { fprintf(stderr,"%s: Error when connecting to server: %s\n", my_progname,mysql_error(&mysql)); + mysql_close(&mysql); free_defaults(defaults_argv); my_end(0); exit(1); @@ -412,8 +419,7 @@ int main(int argc, char **argv) pthread_mutex_destroy(&sleeper_mutex); pthread_cond_destroy(&sleep_threshhold); - if (!opt_only_print) - mysql_close(&mysql); /* Close & free connection */ + mysql_close(&mysql); /* Close & free connection */ /* now free all the strings we created */ my_free(opt_password); @@ -580,6 +586,9 @@ static struct my_option my_long_options[] = "Number of row inserts to perform for each thread (default is 100).", &auto_generate_sql_number, &auto_generate_sql_number, 0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.", &commit_rate, &commit_rate, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -777,6 +786,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), DBUG_PUSH(argument ? argument : default_dbug_option); debug_check_flag= 1; break; + case OPT_CHARSETS_DIR: + strmake_buf(mysql_charsets_dir, argument); + charsets_dir = mysql_charsets_dir; + break; case OPT_SLAP_CSV: if (!argument) argument= (char *)"-"; /* use stdout */ @@ -1808,8 +1821,8 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit) pthread_mutex_lock(&sleeper_mutex); master_wakeup= 0; - pthread_mutex_unlock(&sleeper_mutex); pthread_cond_broadcast(&sleep_threshhold); + pthread_mutex_unlock(&sleeper_mutex); gettimeofday(&start_time, NULL); @@ -1858,21 +1871,21 @@ pthread_handler_t run_task(void *p) } pthread_mutex_unlock(&sleeper_mutex); - if (!(mysql= mysql_init(NULL))) + if (mysql_thread_init()) { - fprintf(stderr,"%s: mysql_init() failed ERROR : %s\n", - my_progname, mysql_error(mysql)); + fprintf(stderr,"%s: mysql_thread_init() failed\n", my_progname); exit(0); } - set_mysql_connect_options(mysql); - if (mysql_thread_init()) + if (!(mysql= mysql_init(NULL))) { - fprintf(stderr,"%s: mysql_thread_init() failed ERROR : %s\n", - my_progname, mysql_error(mysql)); + fprintf(stderr,"%s: mysql_init() failed\n", my_progname); + mysql_thread_end(); exit(0); } + set_mysql_connect_options(mysql); + DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user)); if (!opt_only_print) @@ -1990,8 +2003,7 @@ end: if (commit_rate) run_query(mysql, "COMMIT", strlen("COMMIT")); - if (!opt_only_print) - mysql_close(mysql); + mysql_close(mysql); mysql_thread_end(); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 3652d1a40e2..84d5abc1a67 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -44,7 +44,8 @@ #include <hash.h> #include <stdarg.h> #include <violite.h> -#include "my_regex.h" /* Our own version of regex */ +#define PCRE_STATIC 1 /* Important on Windows */ +#include "pcreposix.h" /* pcreposix regex library */ #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif @@ -87,6 +88,8 @@ static my_bool non_blocking_api_enabled= 0; #define QUERY_SEND_FLAG 1 #define QUERY_REAP_FLAG 2 +#define QUERY_PRINT_ORIGINAL_FLAG 4 + #ifndef HAVE_SETENV static int setenv(const char *name, const char *value, int overwrite); #endif @@ -248,14 +251,16 @@ static const char *opt_suite_dir, *opt_overlay_dir; static size_t suite_dir_len, overlay_dir_len; /* Precompiled re's */ -static my_regex_t ps_re; /* the query can be run using PS protocol */ -static my_regex_t sp_re; /* the query can be run as a SP */ -static my_regex_t view_re; /* the query can be run as a view*/ +static regex_t ps_re; /* the query can be run using PS protocol */ +static regex_t sp_re; /* the query can be run as a SP */ +static regex_t view_re; /* the query can be run as a view*/ static void init_re(void); -static int match_re(my_regex_t *, char *); +static int match_re(regex_t *, char *); static void free_re(void); +static char *get_string(char **to_ptr, char **from_ptr, + struct st_command *command); static int replace(DYNAMIC_STRING *ds_str, const char *search_str, ulong search_len, const char *replace_str, ulong replace_len); @@ -345,7 +350,8 @@ enum enum_commands { Q_ERROR, Q_SEND, Q_REAP, Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN, - Q_PING, Q_EVAL, + Q_PING, Q_EVAL, + Q_EVALP, Q_EVAL_RESULT, Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG, Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG, @@ -411,6 +417,7 @@ const char *command_names[]= "replace_column", "ping", "eval", + "evalp", "eval_result", /* Enable/disable that the _query_ is logged to result file */ "enable_query_log", @@ -832,6 +839,7 @@ static void handle_no_active_connection(struct st_command* command, #define EMB_END_CONNECTION 3 #define EMB_PREPARE_STMT 4 #define EMB_EXECUTE_STMT 5 +#define EMB_CLOSE_STMT 6 /* workaround for MySQL BUG#57491 */ #undef MY_WME @@ -880,6 +888,9 @@ pthread_handler_t connection_thread(void *arg) case EMB_EXECUTE_STMT: cn->result= mysql_stmt_execute(cn->stmt); break; + case EMB_CLOSE_STMT: + cn->result= mysql_stmt_close(cn->stmt); + break; default: DBUG_ASSERT(0); } @@ -977,6 +988,17 @@ static int do_stmt_execute(struct st_connection *cn) } +static int do_stmt_close(struct st_connection *cn) +{ + /* The cn->stmt is already set. */ + if (!cn->has_thread) + return mysql_stmt_close(cn->stmt); + signal_connection_thd(cn, EMB_CLOSE_STMT); + wait_query_thread_done(cn); + return cn->result; +} + + static void emb_close_connection(struct st_connection *cn) { if (!cn->has_thread) @@ -1012,6 +1034,7 @@ static void init_connection_thd(struct st_connection *cn) #define do_read_query_result(cn) mysql_read_query_result(cn->mysql) #define do_stmt_prepare(cn, q, q_len) mysql_stmt_prepare(cn->stmt, q, q_len) #define do_stmt_execute(cn) mysql_stmt_execute(cn->stmt) +#define do_stmt_close(cn) mysql_stmt_close(cn->stmt) #endif /*EMBEDDED_LIBRARY*/ @@ -1081,7 +1104,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, Run query and dump the result to stderr in vertical format NOTE! This function should be safe to call when an error - has occured and thus any further errors will be ignored(although logged) + has occurred and thus any further errors will be ignored (although logged) SYNOPSIS show_query @@ -1147,7 +1170,7 @@ static void show_query(MYSQL* mysql, const char* query) is added to the warning stack, only print @@warning_count-1 warnings. NOTE! This function should be safe to call when an error - has occured and this any further errors will be ignored(although logged) + has occurred and this any further errors will be ignored(although logged) SYNOPSIS show_warnings_before_error @@ -1371,11 +1394,11 @@ void close_connections() DBUG_ENTER("close_connections"); for (--next_con; next_con >= connections; --next_con) { + if (next_con->stmt) + do_stmt_close(next_con); #ifdef EMBEDDED_LIBRARY emb_close_connection(next_con); #endif - if (next_con->stmt) - mysql_stmt_close(next_con->stmt); next_con->stmt= 0; mysql_close(next_con->mysql); next_con->mysql= 0; @@ -3675,7 +3698,6 @@ void do_remove_files_wildcard(struct st_command *command) fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME); DBUG_PRINT("info", ("listing directory: %s", dirname)); - /* Note that my_dir sorts the list if not given any flags */ if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME)))) { error= 1; @@ -3690,7 +3712,7 @@ void do_remove_files_wildcard(struct st_command *command) /* Set default wild chars for wild_compare, is changed in embedded mode */ set_wild_chars(1); - for (i= 0; i < (uint) dir_info->number_off_files; i++) + for (i= 0; i < (uint) dir_info->number_of_files; i++) { file= dir_info->dir_entry + i; /* Remove only regular files, i.e. no directories etc. */ @@ -3953,17 +3975,12 @@ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname, DBUG_ENTER("get_list_files"); DBUG_PRINT("info", ("listing directory: %s", ds_dirname->str)); - /* Note that my_dir sorts the list if not given any flags */ - if (!(dir_info= my_dir(ds_dirname->str, MYF(0)))) + if (!(dir_info= my_dir(ds_dirname->str, MYF(MY_WANT_SORT)))) DBUG_RETURN(1); set_wild_chars(1); - for (i= 0; i < (uint) dir_info->number_off_files; i++) + for (i= 0; i < (uint) dir_info->number_of_files; i++) { file= dir_info->dir_entry + i; - if (file->name[0] == '.' && - (file->name[1] == '\0' || - (file->name[1] == '.' && file->name[2] == '\0'))) - continue; /* . or .. */ if (ds_wild && ds_wild->length && wild_compare(file->name, ds_wild->str, 0)) continue; @@ -4635,7 +4652,8 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused))) } -void do_sync_with_master2(struct st_command *command, long offset) +void do_sync_with_master2(struct st_command *command, long offset, + const char *connection_name) { MYSQL_RES *res; MYSQL_ROW row; @@ -4646,8 +4664,9 @@ void do_sync_with_master2(struct st_command *command, long offset) if (!master_pos.file[0]) die("Calling 'sync_with_master' without calling 'save_master_pos'"); - sprintf(query_buf, "select master_pos_wait('%s', %ld, %d)", - master_pos.file, master_pos.pos + offset, timeout); + sprintf(query_buf, "select master_pos_wait('%s', %ld, %d, '%s')", + master_pos.file, master_pos.pos + offset, timeout, + connection_name); if (mysql_query(mysql, query_buf)) die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql), @@ -4682,7 +4701,7 @@ void do_sync_with_master2(struct st_command *command, long offset) master_pos_wait returned NULL. This indicates that slave SQL thread is not started, the slave's master information is not initialized, the arguments are - incorrect, or an error has occured + incorrect, or an error has occurred */ die("%.*s failed: '%s' returned NULL " \ "indicating slave SQL thread failure", @@ -4707,16 +4726,32 @@ void do_sync_with_master(struct st_command *command) long offset= 0; char *p= command->first_argument; const char *offset_start= p; + char *start, *buff= 0; + start= (char*) ""; + if (*offset_start) { for (; my_isdigit(charset_info, *p); p++) offset = offset * 10 + *p - '0'; - if(*p && !my_isspace(charset_info, *p)) + if (*p && !my_isspace(charset_info, *p) && *p != ',') die("Invalid integer argument \"%s\"", offset_start); + + while (*p && my_isspace(charset_info, *p)) + p++; + if (*p == ',') + { + p++; + while (*p && my_isspace(charset_info, *p)) + p++; + start= buff= (char*)my_malloc(strlen(p)+1,MYF(MY_WME | MY_FAE)); + get_string(&buff, &p, command); + } command->last_argument= p; } - do_sync_with_master2(command, offset); + do_sync_with_master2(command, offset, start); + if (buff) + my_free(start); return; } @@ -5204,7 +5239,7 @@ typedef struct static st_error global_error_names[] = { - { "<No error>", -1U, "" }, + { "<No error>", ~0U, "" }, #include <mysqld_ername.h> { 0, 0, 0 } }; @@ -5368,7 +5403,7 @@ void do_get_errcodes(struct st_command *command) { die("The sqlstate definition must start with an uppercase S"); } - else if (*p == 'E' || *p == 'H') + else if (*p == 'E' || *p == 'W' || *p == 'H') { /* Error name string */ @@ -5377,9 +5412,9 @@ void do_get_errcodes(struct st_command *command) to->type= ERR_ERRNO; DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum)); } - else if (*p == 'e' || *p == 'h') + else if (*p == 'e' || *p == 'w' || *p == 'h') { - die("The error name definition must start with an uppercase E or H"); + die("The error name definition must start with an uppercase E or W or H"); } else { @@ -5442,8 +5477,8 @@ void do_get_errcodes(struct st_command *command) If string is a '$variable', return the value of the variable. */ -char *get_string(char **to_ptr, char **from_ptr, - struct st_command *command) +static char *get_string(char **to_ptr, char **from_ptr, + struct st_command *command) { char c, sep; char *to= *to_ptr, *from= *from_ptr, *start=to; @@ -5617,7 +5652,11 @@ void do_close_connection(struct st_command *command) con->mysql->net.vio = 0; } } -#else +#endif /*!EMBEDDED_LIBRARY*/ + if (con->stmt) + do_stmt_close(con); + con->stmt= 0; +#ifdef EMBEDDED_LIBRARY /* As query could be still executed in a separate theread we need to check if the query's thread was finished and probably wait @@ -5625,9 +5664,6 @@ void do_close_connection(struct st_command *command) */ emb_close_connection(con); #endif /*EMBEDDED_LIBRARY*/ - if (con->stmt) - mysql_stmt_close(con->stmt); - con->stmt= 0; mysql_close(con->mysql); con->mysql= 0; @@ -5704,6 +5740,10 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, verbose_msg("Connecting to server %s:%d (socket %s) as '%s'" ", connection '%s', attempt %d ...", host, port, sock, user, name, failed_attempts); + + mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqltest"); while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) { @@ -5804,7 +5844,9 @@ int connect_n_handle_errors(struct st_command *command, replace_dynstr_append(ds, command->query); dynstr_append_mem(ds, ";\n", 2); } - + + mysql_options(con, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(con, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqltest"); while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS)) { @@ -5888,6 +5930,8 @@ void do_connect(struct st_command *command) my_bool con_ssl= 0, con_compress= 0; my_bool con_pipe= 0; my_bool con_shm __attribute__ ((unused))= 0; + int read_timeout= 0; + int write_timeout= 0; struct st_connection* con_slot; static DYNAMIC_STRING ds_connection_name; @@ -5984,6 +6028,16 @@ void do_connect(struct st_command *command) con_pipe= 1; else if (length == 3 && !strncmp(con_options, "SHM", 3)) con_shm= 1; + else if (strncasecmp(con_options, "read_timeout=", + sizeof("read_timeout=")-1) == 0) + { + read_timeout= atoi(con_options + sizeof("read_timeout=")-1); + } + else if (strncasecmp(con_options, "write_timeout=", + sizeof("write_timeout=")-1) == 0) + { + write_timeout= atoi(con_options + sizeof("write_timeout=")-1); + } else die("Illegal option to connect: %.*s", (int) (end - con_options), con_options); @@ -6035,6 +6089,8 @@ void do_connect(struct st_command *command) #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) mysql_ssl_set(con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, ssl_cipher ? ssl_cipher : opt_ssl_cipher); + mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); #if MYSQL_VERSION_ID >= 50000 /* Turn on ssl_verify_server_cert only if host is "localhost" */ opt_ssl_verify_server_cert= !strcmp(ds_host.str, "localhost"); @@ -6054,6 +6110,18 @@ void do_connect(struct st_command *command) if (opt_protocol) mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); + if (read_timeout) + { + mysql_options(con_slot->mysql, MYSQL_OPT_READ_TIMEOUT, + (char*)&read_timeout); + } + + if (write_timeout) + { + mysql_options(con_slot->mysql, MYSQL_OPT_WRITE_TIMEOUT, + (char*)&write_timeout); + } + #ifdef HAVE_SMEM if (con_shm) { @@ -6545,9 +6613,9 @@ int read_line(char *buf, int size) } else if ((c == '{' && (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5, - (uchar*) buf, min(5, p - buf), 0) || + (uchar*) buf, MY_MIN(5, p - buf), 0) || !my_strnncoll_simple(charset_info, (const uchar*) "if", 2, - (uchar*) buf, min(2, p - buf), 0)))) + (uchar*) buf, MY_MIN(2, p - buf), 0)))) { /* Only if and while commands can be terminated by { */ *p++= c; @@ -7309,13 +7377,13 @@ void str_to_file(const char *fname, char *str, int size) } -void check_regerr(my_regex_t* r, int err) +void check_regerr(regex_t* r, int err) { char err_buf[1024]; if (err) { - my_regerror(err,r,err_buf,sizeof(err_buf)); + regerror(err,r,err_buf,sizeof(err_buf)); die("Regex error: %s\n", err_buf); } } @@ -7350,7 +7418,7 @@ void init_win_path_patterns() DBUG_ENTER("init_win_path_patterns"); - my_init_dynamic_array(&patterns, sizeof(const char*), 16, 16); + my_init_dynamic_array(&patterns, sizeof(const char*), 16, 16, MYF(0)); /* Loop through all paths in the array */ for (i= 0; i < num_paths; i++) @@ -7699,6 +7767,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; MYSQL_RES *warn_res; + DYNAMIC_STRING res; DBUG_ENTER("append_warnings"); if (!(count= mysql_warning_count(mysql))) @@ -7718,11 +7787,18 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) die("Warning count is %u but didn't get any warnings", count); - append_result(ds, warn_res); + init_dynamic_string(&res, "", 1024, 1024); + + append_result(&res, warn_res); mysql_free_result(warn_res); - DBUG_PRINT("warnings", ("%s", ds->str)); + DBUG_PRINT("warnings", ("%s", res.str)); + if (display_result_sorted) + dynstr_append_sorted(ds, &res, 0); + else + dynstr_append_mem(ds, res.str, res.length); + dynstr_free(&res); DBUG_RETURN(count); } @@ -8386,7 +8462,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) /* Evaluate query if this is an eval command */ - if (command->type == Q_EVAL || command->type == Q_SEND_EVAL) + if (command->type == Q_EVAL || command->type == Q_SEND_EVAL || + command->type == Q_EVALP) { if (!command->eval_query.str) init_dynamic_string(&command->eval_query, "", command->query_len + 256, @@ -8422,10 +8499,20 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) */ if (!disable_query_log && (flags & QUERY_SEND_FLAG)) { - replace_dynstr_append_mem(ds, query, query_len); + char *print_query= query; + int print_len= query_len; + if (flags & QUERY_PRINT_ORIGINAL_FLAG) + { + print_query= command->query; + print_len= command->end - command->query; + } + replace_dynstr_append_mem(ds, print_query, print_len); dynstr_append_mem(ds, delimiter, delimiter_length); dynstr_append_mem(ds, "\n", 1); } + + /* We're done with this flag */ + flags &= ~QUERY_PRINT_ORIGINAL_FLAG; /* Write the command to the result file before we execute the query @@ -8599,19 +8686,18 @@ char *re_eprint(int err) { static char epbuf[100]; size_t len __attribute__((unused))= - my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); + regerror(err, (regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); } -void init_re_comp(my_regex_t *re, const char* str) +void init_re_comp(regex_t *re, const char* str) { - int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), - &my_charset_latin1); + int err= regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB | REG_DOTALL)); if (err) { char erbuf[100]; - int len= my_regerror(err, re, erbuf, sizeof(erbuf)); + int len= regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf); } @@ -8656,7 +8742,7 @@ void init_re(void) } -int match_re(my_regex_t *re, char *str) +int match_re(regex_t *re, char *str) { while (my_isspace(charset_info, *str)) str++; @@ -8668,7 +8754,7 @@ int match_re(my_regex_t *re, char *str) str= comm_end + 2; } - int err= my_regexec(re, str, (size_t)0, NULL, 0); + int err= regexec(re, str, (size_t)0, NULL, 0); if (err == 0) return 1; @@ -8677,7 +8763,7 @@ int match_re(my_regex_t *re, char *str) { char erbuf[100]; - int len= my_regerror(err, re, erbuf, sizeof(erbuf)); + int len= regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf); } @@ -8686,10 +8772,9 @@ int match_re(my_regex_t *re, char *str) void free_re(void) { - my_regfree(&ps_re); - my_regfree(&sp_re); - my_regfree(&view_re); - my_regex_end(); + regfree(&ps_re); + regfree(&sp_re); + regfree(&view_re); } /****************************************************************************/ @@ -8955,12 +9040,16 @@ int main(int argc, char **argv) cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->cmd= cmd_none; - my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024); + my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024, MYF(0)); if (my_hash_init2(&var_hash, 64, charset_info, - 128, 0, 0, get_var_key, var_free, MYF(0))) + 128, 0, 0, get_var_key, 0, var_free, MYF(0))) die("Variable hash initialization failed"); + { + char path_separator[]= { FN_LIBCHAR, 0 }; + var_set_string("SYSTEM_PATH_SEPARATOR", path_separator); + } var_set_string("MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION); var_set_string("MYSQL_SYSTEM_TYPE", SYSTEM_TYPE); var_set_string("MYSQL_MACHINE_TYPE", MACHINE_TYPE); @@ -8985,7 +9074,7 @@ int main(int argc, char **argv) #endif init_dynamic_string(&ds_res, "", 2048, 2048); - init_alloc_root(&require_file_root, 1024, 1024); + init_alloc_root(&require_file_root, 1024, 1024, MYF(0)); parse_args(argc, argv); @@ -9073,6 +9162,8 @@ int main(int argc, char **argv) { mysql_ssl_set(con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(con->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(con->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); #if MYSQL_VERSION_ID >= 50000 /* Turn on ssl_verify_server_cert only if host is "localhost" */ opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host, "localhost"); @@ -9284,6 +9375,7 @@ int main(int argc, char **argv) case Q_EVAL_RESULT: die("'eval_result' command is deprecated"); case Q_EVAL: + case Q_EVALP: case Q_QUERY_VERTICAL: case Q_QUERY_HORIZONTAL: if (command->query == command->query_buf) @@ -9311,6 +9403,9 @@ int main(int argc, char **argv) flags= QUERY_REAP_FLAG; } + if (command->type == Q_EVALP) + flags |= QUERY_PRINT_ORIGINAL_FLAG; + /* Check for special property for this query */ display_result_vertically|= (command->type == Q_QUERY_VERTICAL); @@ -9380,7 +9475,7 @@ int main(int argc, char **argv) select_connection(command); else select_connection_name("slave"); - do_sync_with_master2(command, 0); + do_sync_with_master2(command, 0, ""); break; } case Q_COMMENT: @@ -9875,36 +9970,34 @@ struct st_regex int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace, char *string, int icase); +bool parse_re_part(char *start_re, char *end_re, + char **p, char *end, char **buf) +{ + if (*start_re != *end_re) + { + switch ((*start_re= *(*p)++)) { + case '(': *end_re= ')'; break; + case '[': *end_re= ']'; break; + case '{': *end_re= '}'; break; + case '<': *end_re= '>'; break; + default: *end_re= *start_re; + } + } + while (*p < end && **p != *end_re) + { + if ((*p)[0] == '\\' && *p + 1 < end && (*p)[1] == *end_re) + (*p)++; -/* - Finds the next (non-escaped) '/' in the expression. - (If the character '/' is needed, it can be escaped using '\'.) -*/ + *(*buf)++= *(*p)++; + } + *(*buf)++= 0; + + (*p)++; + + return *p > end; +} -#define PARSE_REGEX_ARG \ - while (p < expr_end) \ - { \ - char c= *p; \ - if (c == '/') \ - { \ - if (last_c == '\\') \ - { \ - buf_p[-1]= '/'; \ - } \ - else \ - { \ - *buf_p++ = 0; \ - break; \ - } \ - } \ - else \ - *buf_p++ = c; \ - \ - last_c= c; \ - p++; \ - } \ - \ /* Initializes the regular substitution expression to be used in the result output of test. @@ -9916,16 +10009,15 @@ struct st_replace_regex* init_replace_regex(char* expr) { struct st_replace_regex* res; char* buf,*expr_end; - char* p; + char* p, start_re, end_re= 1; char* buf_p; uint expr_len= strlen(expr); - char last_c = 0; struct st_regex reg; /* my_malloc() will die on fail with MY_FAE */ res=(struct st_replace_regex*)my_malloc( sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME)); - my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128); + my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex), 128, 128, MYF(0)); buf= (char*)res + sizeof(*res); expr_end= expr + expr_len; @@ -9937,44 +10029,32 @@ struct st_replace_regex* init_replace_regex(char* expr) { bzero(®,sizeof(reg)); /* find the start of the statement */ - while (p < expr_end) - { - if (*p == '/') - break; + while (my_isspace(charset_info, *p) && p < expr_end) p++; - } - if (p == expr_end || ++p == expr_end) + if (p >= expr_end) { if (res->regex_arr.elements) break; else goto err; } - /* we found the start */ - reg.pattern= buf_p; - /* Find first argument -- pattern string to be removed */ - PARSE_REGEX_ARG - - if (p == expr_end || ++p == expr_end) - goto err; + start_re= 0; + reg.pattern= buf_p; + if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p)) + goto err; - /* buf_p now points to the replacement pattern terminated with \0 */ reg.replace= buf_p; - - /* Find second argument -- replace string to replace pattern */ - PARSE_REGEX_ARG - - if (p == expr_end) - goto err; - - /* skip the ending '/' in the statement */ - p++; + if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p)) + goto err; /* Check if we should do matching case insensitive */ if (p < expr_end && *p == 'i') + { + p++; reg.icase= 1; + } /* done parsing the statement, now place it in regex_arr */ if (insert_dynamic(&res->regex_arr,(uchar*) ®)) @@ -10122,13 +10202,13 @@ void free_replace_regex() int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace, char *string, int icase) { - my_regex_t r; - my_regmatch_t *subs; + regex_t r; + regmatch_t *subs; char *replace_end; char *buf= *buf_p; int len; int buf_len, need_buf_len; - int cflags= REG_EXTENDED; + int cflags= REG_EXTENDED | REG_DOTALL; int err_code; char *res_p,*str_p,*str_end; @@ -10147,13 +10227,13 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, if (icase) cflags|= REG_ICASE; - if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1))) + if ((err_code= regcomp(&r,pattern,cflags))) { check_regerr(&r,err_code); return 1; } - subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1), + subs= (regmatch_t*)my_malloc(sizeof(regmatch_t) * (r.re_nsub+1), MYF(MY_WME+MY_FAE)); *res_p= 0; @@ -10164,14 +10244,14 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, while (!err_code) { /* find the match */ - err_code= my_regexec(&r,str_p, r.re_nsub+1, subs, + err_code= regexec(&r,str_p, r.re_nsub+1, subs, (str_p == string) ? REG_NOTBOL : 0); /* if regular expression error (eg. bad syntax, or out of memory) */ if (err_code && err_code != REG_NOMATCH) { check_regerr(&r,err_code); - my_regfree(&r); + regfree(&r); return 1; } @@ -10284,7 +10364,7 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, } } my_free(subs); - my_regfree(&r); + regfree(&r); *res_p= 0; *buf_p= buf; *buf_len_p= buf_len; @@ -10980,7 +11060,7 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input, if (!*start) DBUG_VOID_RETURN; /* No input */ - my_init_dynamic_array(&lines, sizeof(const char*), 32, 32); + my_init_dynamic_array(&lines, sizeof(const char*), 32, 32, MYF(0)); if (keep_header) { |