From 1d24597ff94a45e714151f3024a013e44a569169 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 13:21:39 +0200 Subject: [PATCH 01/17] Bug#25452 mysql_upgrade access denied - Improve mysql_upgrade and add comments describing it's logic - Don't look for mysql and mysqlcheck randomly, use dir where mysql_upgrade was started from - Don't look for mysql_fix_privilege_tables.sql randomly, compile in the mysql_fix_privilege_tables.sql file and use that to upgrade the system tables of MySQL - Check for any unexpected error returned from runnning the mysql_fix_privilege_tables SQL - Fix bug#26639, bug#24248 and bug#25405 BitKeeper/etc/ignore: Added scripts/comp_sql scripts/mysql_fix_privilege_tables_sql.c to the ignore list CMakeLists.txt: Build files also in scripts/ Makefile.am: Build scripts/ a little earlier to make the scripts/mysql_fix_privilege_tables_sql.c file available when client/ is built client/mysql_upgrade.c: Updated version of mysql_upgrade with comments and logical functions include/my_global.h: Move IF_WIN macro to my_global.h fr from sql/mysql_priv.h mysql-test/r/mysql_upgrade.result: Update result mysql-test/t/mysql_upgrade.test: Add more tests for different bugs related to mysql_upgrade scripts/Makefile.am: Build comp_sql and mysql_fix_privilege_tables_sql.c sql/mysql_priv.h: Move IF_WIN macro to my_global.h fr from sql/mysql_priv.h scripts/CMakeLists.txt: New BitKeeper file ``scripts/CMakeLists.txt'' scripts/comp_sql.c: New BitKeeper file ``scripts/comp_sql.c'' --- .bzrignore | 2 + CMakeLists.txt | 1 + Makefile.am | 4 +- client/mysql_upgrade.c | 1206 +++++++++++++++------------ include/my_global.h | 8 + mysql-test/r/bdb_notembedded.result | 35 + mysql-test/r/mysql_upgrade.result | 87 +- mysql-test/t/bdb_notembedded.test | 38 + mysql-test/t/mysql_upgrade.test | 48 +- scripts/CMakeLists.txt | 28 + scripts/Makefile.am | 14 + scripts/comp_sql.c | 119 +++ sql/mysql_priv.h | 2 - 13 files changed, 972 insertions(+), 620 deletions(-) create mode 100644 mysql-test/r/bdb_notembedded.result create mode 100644 mysql-test/t/bdb_notembedded.test create mode 100755 scripts/CMakeLists.txt create mode 100644 scripts/comp_sql.c diff --git a/.bzrignore b/.bzrignore index 8e65ec6d6b8..8f8fa4031a9 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1337,3 +1337,5 @@ win/vs71cache.txt win/vs8cache.txt zlib/*.ds? zlib/*.vcproj +scripts/comp_sql +scripts/mysql_fix_privilege_tables_sql.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b458864c410..6615599cd4a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,7 @@ ADD_SUBDIRECTORY(dbug) ADD_SUBDIRECTORY(strings) ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(mysys) +ADD_SUBDIRECTORY(scripts) ADD_SUBDIRECTORY(extra/yassl) ADD_SUBDIRECTORY(extra/yassl/taocrypt) ADD_SUBDIRECTORY(extra) diff --git a/Makefile.am b/Makefile.am index 04d50ccfbaf..92b8428e40e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,9 +21,9 @@ AUTOMAKE_OPTIONS = foreign EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ README COPYING EXCEPTIONS-CLIENT CMakeLists.txt SUBDIRS = . include @docs_dirs@ @zlib_dir@ @yassl_dir@ \ - @readline_topdir@ sql-common \ + @readline_topdir@ sql-common scripts \ @thread_dirs@ pstack \ - @sql_union_dirs@ scripts @man_dirs@ tests \ + @sql_union_dirs@ @man_dirs@ tests \ netware @libmysqld_dirs@ \ @bench_dirs@ support-files @tools_dirs@ diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 0c921c8e0d8..371857816b6 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -14,57 +14,42 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "client_priv.h" -#include -#include #include +#include "../scripts/mysql_fix_privilege_tables_sql.c" -#define UPGRADE_DEFAULTS_NAME "mysql_upgrade_defaults" -#define MYSQL_UPGRADE_INFO_NAME "mysql_upgrade_info" -#define MYSQL_FIX_PRIV_TABLES_NAME "mysql_fix_privilege_tables.sql" +static char mysql_path[FN_REFLEN]; +static char mysqlcheck_path[FN_REFLEN]; +static char defaults_file_option[32+FN_REFLEN]; -#define MY_PARENT (1 << 0) -#define MY_ISDIR (1 << 1) -#define MY_SEARCH_SELF (1 << 2) +static my_bool opt_force, opt_verbose; +static char *opt_user= (char*)"root"; -#ifdef __WIN__ -const char *mysqlcheck_name= "mysqlcheck.exe"; -const char *mysql_name= "mysql.exe"; -const char *mysqld_name= "mysqld.exe"; -#define EXTRA_CLIENT_PATHS "client/release", "client/debug" -#else -const char *mysqlcheck_name= "mysqlcheck"; -const char *mysql_name= "mysql"; -const char *mysqld_name= "mysqld"; -#define EXTRA_CLIENT_PATHS "client" -#endif /*__WIN__*/ +static DYNAMIC_STRING ds_options; -extern TYPELIB sql_protocol_typelib; +static char *opt_password= 0; +static my_bool tty_password= 0; -static my_bool opt_force= 0, opt_verbose= 0, opt_compress= 0; -static char *user= (char*) "root", *basedir= 0, *datadir= 0, *opt_password= 0; -static char *current_host= 0; -static char *opt_default_charset= 0, *opt_charsets_dir= 0; -#ifdef HAVE_SMEM -static char *shared_memory_base_name= 0; -#endif -static char *opt_protocol= 0; -static my_string opt_mysql_port= 0, opt_mysql_unix_port= 0; #ifndef DBUG_OFF static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace"; #endif -static my_bool info_flag= 0, tty_password= 0; static char **defaults_argv; +static File defaults_fd= -1; + +static my_bool not_used; /* Can't use GET_BOOL without a value pointer */ + +#include + static struct my_option my_long_options[]= { {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"basedir", 'b', "Specifies the directory where MySQL is installed", - (gptr*) &basedir, - (gptr*) &basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"datadir", 'd', "Specifies the data directory", (gptr*) &datadir, - (gptr*) &datadir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"basedir", 'b', "Not used by mysql_upgrade. Only for backward compatibilty", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"datadir", 'd', + "Not used by mysql_upgrade. Only for backward compatibilty", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit", 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -72,638 +57,759 @@ static struct my_option my_long_options[]= {"debug", '#', "Output debug log", (gptr *) & default_dbug_option, (gptr *) & default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"debug-info", 'T', "Print some debug info at exit.", (gptr *) & info_flag, - (gptr *) & info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (gptr*) &opt_default_charset, - (gptr*) &opt_default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " - "has already been executed for the current version of MySQL.", - (gptr*) &opt_force, (gptr*) &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, - 0, 0, 0, 0}, + "Set the default character set.", 0, + 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are.", (gptr*) &opt_charsets_dir, - (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory where character sets are.", 0, + 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", OPT_COMPRESS, "Use compression in server/client protocol.", - (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, - 0, 0, 0}, - {"host",'h', "Connect to host.", (gptr*) ¤t_host, - (gptr*) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (gptr*)¬_used, (gptr*)¬_used, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " + "has already been executed for the current version of MySQL.", + (gptr*)&opt_force, (gptr*)&opt_force, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"host",'h', "Connect to host.", 0, + 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"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}, + " it's solicited on the tty.", (gptr*) &opt_password,(gptr*) &opt_password, + 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ - {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, + {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"port", 'P', "Port number to use for connection.", 0, + 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (gptr*) &shared_memory_base_name, - (gptr*) &shared_memory_base_name, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Base name of shared memory.", 0, + 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", 'S', "Socket file to use for connection.", - (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"user", 'u', "User for login if not current user.", (gptr*) &user, - (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", (gptr*) &opt_user, + (gptr*) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include - {"verbose", 'v', "Display more output about the process", - (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, - GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Display more output about the process", + (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, + GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; -static const char *load_default_groups[]= -{ - "mysql_upgrade", 0 -}; - #include -static LIST *extra_defaults= NULL; -typedef struct _extra_default +static void free_used_memory(void) { - int id; - const char *name; - int n_len; - const char *value; - int v_len; -} extra_default_t; + /* Close the defaults file */ + if (defaults_fd != -1) + my_close(defaults_fd, MYF(0)); -static inline -void set_extra_default(int id, const struct my_option *opt) + /* Free memory allocated by 'load_defaults' */ + free_defaults(defaults_argv); + + dynstr_free(&ds_options); +} + + +static void die(const char *fmt, ...) { - switch (id) { - case 'b': case 'd': /* these are ours */ - case 'f': /* --force is ours */ - case 'u': /* --user passed on cmdline */ - case 'T': /* --debug-info is not accepted by mysqlcheck */ - case 'p': /* --password may change yet */ - /* so, do nothing */ - break; - default: - { - LIST *l; - extra_default_t *d; + va_list args; + DBUG_ENTER("die"); - /* - Remove any earlier duplicates: they can - refer to invalid memory addresses (stale pointers) - */ - l= extra_defaults; - while (l) - { - LIST *n= l->next; + /* Print the error message */ + va_start(args, fmt); + if (fmt) + { + fprintf(stderr, "FATAL ERROR: "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + fflush(stderr); + } + va_end(args); - d= l->data; - if (d->id == id) - { - extra_defaults= list_delete(extra_defaults, l); - my_free((gptr)l, MYF(0)); - my_free((gptr)d, MYF(0)); - } - l= n; - } + free_used_memory(); + my_end(MY_CHECK_ERROR); + exit(1); +} - d= (extra_default_t *)my_malloc(sizeof(extra_default_t), - MYF(MY_FAE | MY_ZEROFILL)); - d->id= id; - d->name= opt->name; - d->n_len= strlen(opt->name); - if (opt->arg_type != NO_ARG && opt->value) - switch (opt->var_type & GET_TYPE_MASK) { - case GET_BOOL: - if (*((int *)opt->value)) - { - d->value= "true"; - d->v_len= 4; - } - break; - case GET_STR: - case GET_STR_ALLOC: - d->value= *opt->value; - d->v_len= strlen(d->value); - break; - default: - my_printf_error(0, "Error: internal error at %s:%d", MYF(0), - __FILE__, __LINE__); - exit(1); - } - list_push(extra_defaults, d); + +static void verbose(const char *fmt, ...) +{ + va_list args; + + if (!opt_verbose) + return; + + /* Print the verbose message */ + va_start(args, fmt); + if (fmt) + { + vfprintf(stdout, fmt, args); + fprintf(stdout, "\n"); + fflush(stdout); + } + va_end(args); +} + + +/* + Add one option - passed to mysql_upgrade on command line + or by defaults file(my.cnf) - to a dynamic string that later + can be written to a temporary file. In this way we pass the + same arguments on to mysql and mysql_check +*/ + +static void add_one_option(DYNAMIC_STRING* ds, + const struct my_option *opt, + const char* argument) +{ + dynstr_append(ds, opt->name); + + if (opt->arg_type != NO_ARG) + { + dynstr_append(ds, "="); + switch (opt->var_type & GET_TYPE_MASK) { + case GET_STR: + case GET_STR_ALLOC: + dynstr_append(ds, argument); + break; + default: + die("internal error at %s: %d",__FILE__, __LINE__); } } + dynstr_append(ds, "\n"); } static my_bool -get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), +get_one_option(int optid, const struct my_option *opt, char *argument) { + my_bool add_option= TRUE; + switch (optid) { + case '?': - puts - ("MySQL utility to upgrade database to the current server version"); - puts(""); + printf("MySQL utility for upgrading database to MySQL version %s\n", + MYSQL_SERVER_VERSION); my_print_help(my_long_options); exit(0); + break; + case '#': DBUG_PUSH(argument ? argument : default_dbug_option); + add_option= FALSE; break; + case 'p': tty_password= 1; + add_option= FALSE; if (argument) { - char *start= argument; - my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); - opt_password= my_strdup(argument, MYF(MY_FAE)); + /* Add password to ds_options before overwriting the arg with x's */ + add_one_option(&ds_options, opt, argument); while (*argument) *argument++= 'x'; /* Destroy argument */ - if (*start) - start[1]= 0; /* Cut length of argument */ tty_password= 0; } break; -#ifdef __WIN__ - case 'W': - my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR)); - opt_protocol= my_strdup("pipe", MYF(MY_FAE)); + + case 'b': /* --basedir */ + case 'v': /* --verbose */ + case 'd': /* --datadir */ + case 'f': /* --force */ + add_option= FALSE; break; -#endif - case OPT_MYSQL_PROTOCOL: - if (find_type(argument, &sql_protocol_typelib, 0) > 0) - { - my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR)); - opt_protocol= my_strdup(argument, MYF(MY_FAE)); - } - else - { - fprintf(stderr, "Unknown option to protocol: %s\n", argument); - exit(1); - } - break; -#include - default:; } - set_extra_default(opt->id, opt); + + if (add_option) + { + /* + This is an option that is accpted by mysql_upgrade just so + it can be passed on to "mysql" and "mysqlcheck" + Save it in the ds_options string + */ + add_one_option(&ds_options, opt, argument); + } return 0; } -static int create_check_file(const char *path) +/* + Write the options that should be passed on to + mysql and mysqlcheck to a temporary file +*/ + +static void create_defaults_file(void) { - int ret; - File fd; - - fd= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME)); - if (fd < 0) { - ret= 1; - goto error; - } - ret= my_write(fd, MYSQL_SERVER_VERSION, - sizeof(MYSQL_SERVER_VERSION) - 1, - MYF(MY_WME | MY_FNABP)); - ret|= my_close(fd, MYF(MY_FAE | MY_WME)); -error: - return ret; + static char defaults_file_path[FN_REFLEN]; + DBUG_ENTER("create_defaults_file"); + + if ((defaults_fd= create_temp_file(defaults_file_path, NULL, + "cnf", O_CREAT | O_SHARE, + MYF(MY_WME))) < 0) + die("Failed to create temporary file for defaults"); + + DBUG_PRINT("info", ("Writing options: %s", ds_options.str)); + if (my_write(defaults_fd, ds_options.str, ds_options.length, + MYF(MY_FNABP | MY_WME))) + die("Failed to write to '%s'", defaults_file_path); + + /* + Dont close the temporary file yet, it will be used + by mysql and mysqlcheck + */ + + /* + Create the option that should be added to + tools in order to use this file + */ + snprintf(defaults_file_option, sizeof(defaults_file_option), + "--defaults-file=%s", defaults_file_path); + DBUG_PRINT("info", ("defaults_file_option: %s", defaults_file_option)); + + DBUG_VOID_RETURN; } -static int create_defaults_file(const char *path, const char *forced_path) +static int run_command(char* cmd, + DYNAMIC_STRING *ds_res) +{ + char buf[512]= {0}; + FILE *res_file; + + if (!(res_file= popen(cmd, "r"))) + die("popen(\"%s\", \"r\") failed", cmd); + + while (fgets(buf, sizeof(buf), res_file)) + { + DBUG_PRINT("info", ("buf: %s", buf)); + if(ds_res) + { + /* Save the output of this command in the supplied string */ + dynstr_append(ds_res, buf); + } + else + { + /* Print it directly on screen */ + fprintf(stdout, "%s", buf); + } + } + + return WEXITSTATUS(pclose(res_file)); +} + + +static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) { int ret; - uint cnt; - File forced_file, defaults_file; - - DYNAMIC_STRING buf; - extra_default_t *d; + const char* arg; + va_list args; + DYNAMIC_STRING ds_cmdline; - DBUG_ENTER("create_defaults_file"); - DBUG_PRINT("enter", ("path: %s, forced_path: %s", path, forced_path)); + DBUG_ENTER("run_tool"); + DBUG_PRINT("enter", ("tool_path: %s", tool_path)); - /* Delete any previous defaults file generated by mysql_upgrade */ - my_delete(path, MYF(0)); - - defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY | O_EXCL, - MYF(MY_FAE | MY_WME)); - if (defaults_file < 0) + if (init_dynamic_string(&ds_cmdline, IF_WIN("\"", ""), FN_REFLEN, FN_REFLEN)) + die("Out of memory"); + + dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS); + dynstr_append(&ds_cmdline, " "); + + va_start(args, ds_res); + + while ((arg= va_arg(args, char *))) { - ret= 1; - goto out; + /* Options should be os quoted */ + if (strncmp(arg, "--", 2) == 0) + dynstr_append_os_quoted(&ds_cmdline, arg, NullS); + else + dynstr_append(&ds_cmdline, arg); + dynstr_append(&ds_cmdline, " "); } - if (init_dynamic_string(&buf, NULL, my_getpagesize(), FN_REFLEN)) - { - ret= 1; - goto error; - } + va_end(args); - /* Copy forced_path file into the defaults_file being generated */ - if (forced_path) - { - forced_file= my_open(forced_path, O_RDONLY, MYF(MY_FAE | MY_WME)); - if (forced_file < 0) - { - ret= 1; - goto error; - } - DBUG_PRINT("info", ("Copying from %s to %s", forced_path, path)); - do - { - cnt= my_read(forced_file, buf.str, buf.max_length, MYF(MY_WME)); - if ((cnt == MY_FILE_ERROR) - || my_write(defaults_file, buf.str, cnt, MYF(MY_FNABP | MY_WME))) - { - ret= 1; - my_close(forced_file, MYF(0)); - goto error; - } - DBUG_PRINT("info", ("%s", buf.str)); - } while (cnt == buf.max_length); - my_close(forced_file, MYF(0)); - } - - /* Write all extra_default options into the [client] section */ - dynstr_set(&buf, "\n[client]"); - if (opt_password) - { - if (dynstr_append(&buf, "\npassword=") - || dynstr_append(&buf, opt_password)) - { - ret = 1; - goto error; - } - } - DBUG_PRINT("info", ("Writing extra_defaults to file")); - while (extra_defaults) - { - int len; - - d= extra_defaults->data; - len= d->n_len + d->v_len + 1; - if (buf.length + len >= buf.max_length) /* to avoid realloc() */ - { - - if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME))) - { - ret= 1; - goto error; - } - dynstr_set(&buf, NULL); - } - if (dynstr_append_mem(&buf, "\n", 1) || - dynstr_append_mem(&buf, d->name, d->n_len) || - (d->v_len && (dynstr_append_mem(&buf, "=", 1) || - dynstr_append_mem(&buf, d->value, d->v_len)))) - { - ret= 1; - goto error; - } - DBUG_PRINT("info", ("%s", buf.str)); - my_free((gptr)d, MYF(0)); - list_pop(extra_defaults); /* pop off the head */ - } - if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME))) - { - ret= 1; - goto error; - } - /* everything's all right */ - ret= 0; -error: - dynstr_free(&buf); - - if (defaults_file >= 0) - ret|= my_close(defaults_file, MYF(MY_WME)); - - if (ret) - my_delete(path, MYF(0)); - -out: + DBUG_PRINT("info", ("Running: %s", ds_cmdline.str)); + ret= run_command(ds_cmdline.str, ds_res); + DBUG_PRINT("exit", ("ret: %d", ret)); + dynstr_free(&ds_cmdline); DBUG_RETURN(ret); } -/* Compare filenames */ -static int comp_names(struct fileinfo *a, struct fileinfo *b) +/* + Try to get the full path to this exceutable + + Return 0 if path found + +*/ + +static my_bool get_full_path_to_executable(char* path) { - return (strcmp(a->name,b->name)); + my_bool ret; + DBUG_ENTER("get_full_path_to_executable"); +#ifdef WIN + ret= GetModuleFileName(NULL, path, FN_REFLEN) != 0; +#else + /* my_readlink returns 0 if a symlink was read */ + ret= my_readlink(path, "/proc/self/exe", MYF(0)) != 0; + /* Might also want to try with /proc/$$/exe if the above fails */ +#endif + DBUG_PRINT("exit", ("path: %s", path)); + DBUG_RETURN(ret); } -static int find_file(const char *name, const char *root, - uint flags, char *result, size_t len, ...) +/* + Look for the tool in the same directory as mysql_upgrade. + + When running in a not yet installed build the the program + will exist but it need to be invoked via it's libtool wrapper. + Check if the found tool can executed and if not look in the + directory one step higher up where the libtool wrapper normally + is found +*/ + +static void find_tool(char *tool_path, const char *tool_name) { - int ret= 1; - va_list va; - const char *subdir; - char *cp; - FILEINFO key; + char path[FN_REFLEN]; + DYNAMIC_STRING ds_tmp; + DBUG_ENTER("find_tool"); + DBUG_PRINT("enter", ("progname: %s", my_progname)); - /* Init key with name of the file to look for */ - key.name= (char*)name; + if (init_dynamic_string(&ds_tmp, "", 32, 32)) + die("Out of memory"); - DBUG_ASSERT(root != NULL); - - cp= strmake(result, root, len); - if (cp[-1] != FN_LIBCHAR) - *cp++= FN_LIBCHAR; - - va_start(va, len); - subdir= (!(flags & MY_SEARCH_SELF)) ? va_arg(va, char *) : ""; - while (subdir) + /* Initialize path with the full path to this program */ + if (get_full_path_to_executable(path)) { - MY_DIR *dir; - FILEINFO *match; - char *cp1; - - cp1= strnmov(cp, subdir, len - (cp - result) - 1); - - dir= my_dir(result, (flags & MY_ISDIR) ? MY_WANT_STAT : MYF(0)); - if (dir) - { - match= bsearch(&key, dir->dir_entry, dir->number_off_files, - sizeof(FILEINFO), (qsort_cmp)comp_names); - if (match) - { - ret= (flags & MY_ISDIR) ? !MY_S_ISDIR(match->mystat->st_mode) : 0; - if (!ret) - { - if (cp1[-1] != FN_LIBCHAR) - *cp1++= FN_LIBCHAR; - - if (!(flags & MY_PARENT)) - strnmov(cp1, name, len - (cp1 - result)); - else - *cp1= '\0'; - - my_dirend(dir); - break; - } - } - my_dirend(dir); + /* + Easy way to get full executable path failed, try + other methods + */ + if (my_progname[0] == FN_LIBCHAR) + { + /* 1. my_progname contains full path */ + strmake(path, my_progname, FN_REFLEN); + } + else if (my_progname[0] == '.') + { + /* 2. my_progname contains relative path, prepend wd */ + char buf[FN_REFLEN]; + my_getwd(buf, FN_REFLEN, MYF(0)); + snprintf(path, FN_REFLEN, "%s%s", buf, my_progname); + } + else + { + /* 3. Just go for it and hope tool is in path */ + path[0]= 0; } - subdir= va_arg(va, char *); } - va_end(va); - return ret; + do + { + DBUG_PRINT("enter", ("path: %s", path)); + + /* Chop off last char(since it might be a /) */ + size_t pos= max((strlen(path)-1), 0); + path[pos]= 0; + + /* Chop off last dir part */ + dirname_part(path, path); + + /* Format name of the tool to search for */ + fn_format(tool_path, tool_name, + path, "", MYF(MY_REPLACE_DIR)); + + verbose("Looking for '%s' in: %s", tool_name, tool_path); + + /* Make sure the tool exists */ + if (my_access(tool_path, F_OK) != 0) + die("Can't find '%s'", tool_path); + + /* + Make sure it can be executed, otherwise try again + in higher level directory + */ + } + while(run_tool(tool_path, + &ds_tmp, /* Get output from command, discard*/ + "--help", + "2>&1", + IF_WIN("> NUL", "> /dev/null"), + NULL)); + + dynstr_free(&ds_tmp); + + DBUG_VOID_RETURN; } +/* + Run query using "mysql" +*/ + +static int run_query(const char *query, DYNAMIC_STRING *ds_res, + my_bool force) +{ + int ret; + File fd; + char query_file_path[FN_REFLEN]; + DBUG_ENTER("run_query"); + DBUG_PRINT("enter", ("query: %s", query)); + if ((fd= create_temp_file(query_file_path, NULL, + "sql", O_CREAT | O_SHARE, + MYF(MY_WME))) < 0) + die("Failed to create temporary file for defaults"); + + if (my_write(fd, query, strlen(query), + MYF(MY_FNABP | MY_WME))) + die("Failed to write to '%s'", query_file_path); + + ret= run_tool(mysql_path, + ds_res, + defaults_file_option, + "--database=mysql", + "--batch", /* Turns off pager etc. */ + force ? "--force": "--skip-force", + ds_res ? "--silent": "", + "<", + query_file_path, + "2>&1", + NULL); + + my_close(fd, MYF(0)); + + DBUG_RETURN(ret); +} + + +/* + Extract the value returned from result of "show variable like ..." +*/ + +static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value) +{ + char *value_start, *value_end; + /* + The query returns "datadir\t\n", skip past + the tab + */ + if ((value_start= strchr(ds->str, '\t')) == NULL) + return 1; /* Unexpected result */ + value_start++; + + /* Don't copy the ending newline */ + if (value_start && (value_end= strchr(value_start, '\n')) == NULL) + return 1; /* Unexpected result */ + + strncpy(value, value_start, min(FN_REFLEN, value_end-value_start)); + return 0; +} + + +static int get_upgrade_info_file_name(char* name) +{ + DYNAMIC_STRING ds_datadir; + DBUG_ENTER("get_upgrade_info_file_name"); + + if (init_dynamic_string(&ds_datadir, NULL, 32, 32)) + die("Out of memory"); + + if (run_query("show variables like 'datadir'", + &ds_datadir, FALSE) || + extract_variable_from_show(&ds_datadir, name)) + { + dynstr_free(&ds_datadir); + DBUG_RETURN(1); /* Query failed */ + } + + dynstr_free(&ds_datadir); + + fn_format(name, "mysql_upgrade_info", name, "", MYF(0)); + DBUG_PRINT("exit", ("name: %s", name)); + DBUG_RETURN(0); +} + + +/* + Read the content of mysql_upgrade_info file and + compare the version number form file against + version number wich mysql_upgrade was compiled for + + NOTE + This is an optimization to avoid running mysql_upgrade + when it's already been performed for the particular + version of MySQL. + + In case the MySQL server can't return the upgrade info + file it's always better to report that the upgrade hasn't + been performed. + +*/ + +static int upgrade_already_done(void) +{ + FILE *in; + char upgrade_info_file[FN_REFLEN]= {0}; + char buf[sizeof(MYSQL_SERVER_VERSION)+1]; + + if (get_upgrade_info_file_name(upgrade_info_file)) + return 0; /* Could not get filename => not sure */ + + if (!(in= my_fopen(upgrade_info_file, O_RDONLY, MYF(0)))) + return 0; /* Could not open file => not sure */ + + /* + Read from file, don't care if it fails since it + will be detected by the strncmp + */ + bzero(buf, sizeof(buf)); + fgets(buf, sizeof(buf), in); + + my_fclose(in, MYF(0)); + + return (strncmp(buf, MYSQL_SERVER_VERSION, + sizeof(MYSQL_SERVER_VERSION)-1)==0); +} + + +/* + Write mysql_upgrade_info file in servers data dir indicating that + upgrade has been done for this version + + NOTE + This might very well fail but since it's just an optimization + to run mysql_upgrade only when necessary the error can be + ignored. + +*/ + +static void create_mysql_upgrade_info_file(void) +{ + FILE *out; + char upgrade_info_file[FN_REFLEN]= {0}; + + if (get_upgrade_info_file_name(upgrade_info_file)) + return; /* Could not get filename => skip */ + + if (!(out= my_fopen(upgrade_info_file, O_TRUNC | O_WRONLY, MYF(0)))) + { + fprintf(stderr, + "Could not create the upgrade info file '%s' in " + "the MySQL Servers datadir, errno: %d\n", + upgrade_info_file, errno); + return; + } + + /* Write new version to file, just print a message if it fails */ + if (!fputs(MYSQL_SERVER_VERSION, out)) + fprintf(stderr, + "Could not write to the upgrade info file '%s' in " + "the MySQL Servers datadir, errno: %d\n", + upgrade_info_file, errno); + + my_fclose(out, MYF(0)); +} + + +/* + Check and upgrade(if neccessary) all tables + in the server using "mysqlcheck --check-upgrade .." +*/ + +static int run_mysqlcheck_upgrade(void) +{ + verbose("Running 'mysqlcheck'..."); + return run_tool(mysqlcheck_path, + NULL, /* Send output from mysqlcheck directly to screen */ + defaults_file_option, + "--check-upgrade", + "--all-databases", + "--auto-repair", + NULL); +} + + +static const char *expected_errors[]= +{ + "ERROR 1060", /* Duplicate column name */ + "ERROR 1061", /* Duplicate key name */ + "ERROR 1054", /* Unknown column */ + 0 +}; + + +static my_bool is_expected_error(const char* line) +{ + const char** error= expected_errors; + while (*error) + { + /* + Check if lines starting with ERROR + are in the list of expected errors + */ + if (strncmp(line, "ERROR", 5) != 0 || + strncmp(line, *error, strlen(*error)) == 0) + return 1; /* Found expected error */ + error++; + } + return 0; +} + + +static char* get_line(char* line) +{ + while (*line && *line != '\n') + line++; + if (*line) + line++; + return line; +} + + +/* Print the current line to stderr */ +static void print_line(char* line) +{ + while (*line && *line != '\n') + { + fputc(*line, stderr); + line++; + } + fputc('\n', stderr); +} + + +/* + Update all system tables in MySQL Server to current + version using "mysql" to execute all the SQL commands + compiled into the mysql_fix_privilege_tables array +*/ + +static int run_sql_fix_privilege_tables(void) +{ + int found_real_errors= 0; + DYNAMIC_STRING ds_result; + DBUG_ENTER("run_sql_fix_privilege_tables"); + + if (init_dynamic_string(&ds_result, "", 512, 512)) + die("Out of memory"); + + verbose("Running 'mysql_fix_privilege_tables'..."); + run_query(mysql_fix_privilege_tables, + &ds_result, /* Collect result */ + TRUE); + + { + /* + Scan each line of the result for real errors + and ignore the expected one(s) like "Duplicate column name", + "Unknown column" and "Duplicate key name" since they just + indicate the system tables are already up to date + */ + char *line= ds_result.str; + do + { + if (!is_expected_error(line)) + { + /* Something unexpected failed, dump error line to screen */ + found_real_errors++; + print_line(line); + } + } while ((line= get_line(line)) && *line); + } + + dynstr_free(&ds_result); + return found_real_errors; +} + + +static const char *load_default_groups[]= +{ + "client", /* Read settings how to connect to server */ + "mysql_upgrade", /* Read special settings for mysql_upgrade*/ + 0 +}; + + int main(int argc, char **argv) { - int ret; - - char *forced_defaults_file; - char *forced_extra_defaults; - char *local_defaults_group_suffix; - int no_defaults; - char path[FN_REFLEN], upgrade_defaults_path[FN_REFLEN]; - - DYNAMIC_STRING cmdline; - MY_INIT(argv[0]); #ifdef __NETWARE__ setscreenmode(SCR_AUTOCLOSE_ON_EXIT); #endif - /* Check if we are forced to use specific defaults */ - no_defaults= 0; - if (argc >= 2 && !strcmp(argv[1],"--no-defaults")) - no_defaults= 1; + if (init_dynamic_string(&ds_options, "[client]\n", 512, 256)) + die("Out of memory"); - get_defaults_options(argc, argv, - &forced_defaults_file, &forced_extra_defaults, - &local_defaults_group_suffix); - load_defaults("my", load_default_groups, &argc, &argv); - defaults_argv= argv; + defaults_argv= argv; /* Must be freed by 'free_defaults' */ + + if (handle_options(&argc, &argv, my_long_options, get_one_option)) + die(NULL); - /* - Must init_dynamic_string before handle_options because string is freed - at error label. - */ - if (init_dynamic_string(&cmdline, NULL, 2 * FN_REFLEN + 128, FN_REFLEN) || - handle_options(&argc, &argv, my_long_options, get_one_option)) - { - ret= 1; - goto error; - } if (tty_password) + { opt_password= get_tty_password(NullS); + /* add password to defaults file */ + dynstr_append(&ds_options, "password="); + dynstr_append(&ds_options, opt_password); + dynstr_append(&ds_options, "\n"); + } + /* add user to defaults file */ + dynstr_append(&ds_options, "user="); + dynstr_append(&ds_options, opt_user); + dynstr_append(&ds_options, "\n"); - if (!basedir) - { - my_getwd(path, sizeof(path), MYF(0)); - basedir= my_strdup(path, MYF(0)); - if (find_file("errmsg.sys", basedir, MYF(0), path, sizeof(path), - "share/mysql/english", NullS) - || find_file(mysqld_name, basedir, MYF(0), path, sizeof(path), - "bin", "libexec", NullS)) - { - my_free((gptr)basedir, MYF(0)); - basedir= (char *)DEFAULT_MYSQL_HOME; - } - } + /* Find mysql */ + find_tool(mysql_path, IF_WIN("mysql.exe", "mysql")); - if (!datadir) - { - if (!find_file("mysql", basedir, MYF(MY_ISDIR|MY_PARENT), - path, sizeof(path), - "data", "var", NullS)) - datadir= my_strdup(path, MYF(0)); - else - datadir= (char *)DATADIR; - } - if (find_file("user.frm", datadir, MYF(0), path, sizeof(path), - "mysql", NullS)) - { - ret= 1; - fprintf(stderr, - "Can't find data directory. Please restart with" - " --datadir=path-to-writable-data-dir"); - goto error; - } + /* Find mysqlcheck */ + find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck")); /* - Create the modified defaults file to be used by mysqlcheck + Create the defaults file(a small my.cnf) which will pass + all arguments accepted by mysql_upgrade on to mysqlcheck and mysql command line client */ - fn_format(upgrade_defaults_path, UPGRADE_DEFAULTS_NAME, datadir, "", MYF(0)); - create_defaults_file(upgrade_defaults_path, forced_extra_defaults); - + create_defaults_file(); /* Read the mysql_upgrade_info file to check if mysql_upgrade - already has been done - Maybe this could be done a little earlier? + already has been run for this installation of MySQL */ - if (!find_file(MYSQL_UPGRADE_INFO_NAME, datadir, MY_SEARCH_SELF, - path, sizeof(path), NULL, NullS) - && !opt_force) + if (!opt_force && upgrade_already_done()) { - char buf[sizeof(MYSQL_SERVER_VERSION)]; - int fd, cnt; - - fd= my_open(path, O_RDONLY, MYF(0)); - cnt= my_read(fd, buf, sizeof(buf) - 1, MYF(0)); - my_close(fd, MYF(0)); - buf[cnt]= 0; - if (!strcmp(buf, MYSQL_SERVER_VERSION)) - { - if (opt_verbose) - puts("mysql_upgrade has already been done for this version"); - goto fix_priv_tables; - } - } - - - /* Find mysqlcheck */ - if (find_file(mysqlcheck_name, basedir, MYF(0), path, sizeof(path), - "bin", EXTRA_CLIENT_PATHS, NullS)) - { - ret= 1; - fprintf(stderr, - "Can't find program '%s'\n" - "Please restart with --basedir=mysql-install-directory", - mysqlcheck_name); - goto error; - } - else - { -#ifdef __WIN__ - /* Windows requires an extra pair of quotes around the entire string. */ - dynstr_set(&cmdline, "\""); -#else - dynstr_set(&cmdline, ""); -#endif /* __WIN__ */ - dynstr_append_os_quoted(&cmdline, path, NullS); + printf("This installation of MySQL is already upgraded to %s, " + "use --force if you still need to run mysql_upgrade\n", + MYSQL_SERVER_VERSION); + die(NULL); } /* - All settings have been written to the "upgrade_defaults_path" - instruct mysqlcheck to only read options from that file + Run "mysqlcheck" and "mysql_fix_privilege_tables.sql" */ - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, - (no_defaults ? "--defaults-file=" : - "--defaults-extra-file="), - upgrade_defaults_path, NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--check-upgrade", NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--all-databases", NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--auto-repair", NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--user=", user, NullS); -#ifdef __WIN__ - dynstr_append(&cmdline, "\""); -#endif /* __WIN__ */ - - /* Execute mysqlcheck */ - if (opt_verbose) - printf("Running %s\n", cmdline.str); - DBUG_PRINT("info", ("Running: %s", cmdline.str)); - ret= system(cmdline.str); - if (ret) + if (run_mysqlcheck_upgrade() || + run_sql_fix_privilege_tables()) { - fprintf(stderr, "Error executing '%s'\n", cmdline.str); - goto error; + /* + The upgrade failed to complete in some way or another, + significant error message should have been printed to the screen + */ + die("Upgrade failed" ); } + verbose("OK"); - fn_format(path, MYSQL_UPGRADE_INFO_NAME, datadir, "", MYF(0)); - ret= create_check_file(path); - if (ret) - goto error; + /* Create a file indicating upgrade has been performed */ + create_mysql_upgrade_info_file(); -fix_priv_tables: - /* Find mysql */ - if (find_file(mysql_name, basedir, MYF(0), path, sizeof(path), - "bin", EXTRA_CLIENT_PATHS, NullS)) - { - ret= 1; - fprintf(stderr, - "Could not find MySQL command-line client (mysql).\n" - "Please use --basedir to specify the directory" - " where MySQL is installed."); - goto error; - } - else - { -#ifdef __WIN__ - /* Windows requires an extra pair of quotes around the entire string. */ - dynstr_set(&cmdline, "\""); -#else - dynstr_set(&cmdline, ""); -#endif /* __WIN__ */ - dynstr_append_os_quoted(&cmdline, path, NullS); - } - - /* Find mysql_fix_privililege_tables.sql */ - if (find_file(MYSQL_FIX_PRIV_TABLES_NAME, basedir, MYF(0), - path, sizeof(path), - "support_files", "share", "share/mysql", "scripts", - NullS) - && find_file(MYSQL_FIX_PRIV_TABLES_NAME, "/usr/local/mysql", MYF(0), - path, sizeof(path), - "share/mysql", NullS)) - { - ret= 1; - fprintf(stderr, - "Could not find file " MYSQL_FIX_PRIV_TABLES_NAME "\n" - "Please use --basedir to specify the directory" - " where MySQL is installed"); - goto error; - } - - /* - All settings have been written to the "upgrade_defaults_path", - instruct mysql to only read options from that file - */ - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, - (no_defaults ? "--defaults-file=" : - "--defaults-extra-file="), - upgrade_defaults_path, NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--force", NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--no-auto-rehash", NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--batch", NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--user=", user, NullS); - dynstr_append(&cmdline, " "); - dynstr_append_os_quoted(&cmdline, "--database=mysql", NullS); - dynstr_append(&cmdline, " < "); - dynstr_append_os_quoted(&cmdline, path, NullS); -#ifdef __WIN__ - dynstr_append(&cmdline, "\""); -#endif /* __WIN__ */ - - /* Execute "mysql --force < mysql_fix_privilege_tables.sql" */ - if (opt_verbose) - printf("Running %s\n", cmdline.str); - DBUG_PRINT("info", ("Running: %s", cmdline.str)); - ret= system(cmdline.str); - if (ret) - fprintf(stderr, "Error executing '%s'\n", cmdline.str); - -error: - dynstr_free(&cmdline); - - /* Delete the generated defaults file */ - my_delete(upgrade_defaults_path, MYF(0)); - - free_defaults(defaults_argv); - my_end(info_flag ? MY_CHECK_ERROR : 0); - return ret; + free_used_memory(); + my_end(MY_CHECK_ERROR); + exit(0); } diff --git a/include/my_global.h b/include/my_global.h index 21fe1ebc3cb..3382916840e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -86,6 +86,14 @@ #endif #endif /* _WIN32... */ +/* Make it easier to add conditionl code for windows */ +#ifdef __WIN__ +#define IF_WIN(A,B) (A) +#else +#define IF_WIN(A,B) (B) +#endif + + /* Some defines to avoid ifdefs in the code */ #ifndef NETWARE_YIELD #define NETWARE_YIELD diff --git a/mysql-test/r/bdb_notembedded.result b/mysql-test/r/bdb_notembedded.result new file mode 100644 index 00000000000..14cb5fad915 --- /dev/null +++ b/mysql-test/r/bdb_notembedded.result @@ -0,0 +1,35 @@ +set autocommit=1; +reset master; +create table bug16206 (a int); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 +f n Query 1 n use `test`; create table bug16206 (a int) +f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; insert into bug16206 values(2) +drop table bug16206; +reset master; +create table bug16206 (a int) engine= bdb; +insert into bug16206 values(0); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +insert into bug16206 values(3); +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 +f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb +f n Query 1 n use `test`; insert into bug16206 values(0) +f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; BEGIN +f n Query 1 n use `test`; insert into bug16206 values(2) +f n Query 1 n use `test`; COMMIT +f n Query 1 n use `test`; insert into bug16206 values(3) +drop table bug16206; +set autocommit=0; +End of 5.0 tests diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index f92540a0d55..ce4706c6d92 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -16,48 +16,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK -@hadGrantPriv:=1 -1 -1 -1 -@hadShowDbPriv:=1 -1 -1 -1 -@hadCreateViewPriv:=1 -1 -1 -1 -@hadCreateRoutinePriv:=1 -1 -1 -1 -@hadCreateUserPriv:=1 -1 -1 -1 Run it again - should say already completed -@hadGrantPriv:=1 -1 -1 -1 -@hadShowDbPriv:=1 -1 -1 -1 -@hadCreateViewPriv:=1 -1 -1 -1 -@hadCreateRoutinePriv:=1 -1 -1 -1 -@hadCreateUserPriv:=1 -1 -1 -1 -Force should run it regardless of wheter it's been run before +This installation of MySQL is already upgraded to VERSION, use --force if you still need to run mysql_upgrade +Force should run it regardless of wether it's been run before mysql.columns_priv OK mysql.db OK mysql.func OK @@ -75,23 +36,27 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK -@hadGrantPriv:=1 -1 -1 -1 -@hadShowDbPriv:=1 -1 -1 -1 -@hadCreateViewPriv:=1 -1 -1 -1 -@hadCreateRoutinePriv:=1 -1 -1 -1 -@hadCreateUserPriv:=1 -1 -1 -1 +CREATE USER mysqltest1@'%' IDENTIFIED by 'sakila'; +GRANT ALL ON *.* TO mysqltest1@'%'; +Run mysql_upgrade with password protected account +mysql.columns_priv OK +mysql.db OK +mysql.func OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.host OK +mysql.proc OK +mysql.procs_priv OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.user OK +DROP USER mysqltest1@'%'; +Run mysql_upgrade with a non existing server socket +mysqlcheck: Got error: 2002: Can't connect to local MySQL server through socket 'var/tmp/no_sock_here' (2) when trying to connect +FATAL ERROR: Upgrade failed diff --git a/mysql-test/t/bdb_notembedded.test b/mysql-test/t/bdb_notembedded.test new file mode 100644 index 00000000000..24e64ebbfb2 --- /dev/null +++ b/mysql-test/t/bdb_notembedded.test @@ -0,0 +1,38 @@ +-- source include/not_embedded.inc +-- source include/have_bdb.inc + +# +# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode +# +set autocommit=1; + +let $VERSION=`select version()`; + +reset master; +create table bug16206 (a int); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +--replace_result $VERSION VERSION +--replace_column 1 f 2 n 5 n +show binlog events; +drop table bug16206; + +reset master; +create table bug16206 (a int) engine= bdb; +insert into bug16206 values(0); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +insert into bug16206 values(3); +--replace_result $VERSION VERSION +--replace_column 1 f 2 n 5 n +show binlog events; +drop table bug16206; + +set autocommit=0; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index c6133f8e85f..973e9157987 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -7,17 +7,55 @@ select LENGTH("$MYSQL_UPGRADE")>0 as have_mysql_upgrade; --enable_query_log +# Get version of the server so it can be masked out in the +# error messages from mysql_upgrade +let $VERSION=`select LEFT(version(), 6)`; + # -# Basic test thta we can run mysql_upgrde and that it finds the +# Basic test that we can run mysql_upgrde and that it finds the # expected binaries it uses. # --echo Run mysql_upgrade once ---exec $MYSQL_UPGRADE 2> $MYSQLTEST_VARDIR/log/mysql_upgrade.err +--exec $MYSQL_UPGRADE --skip-verbose 2>&1 + +# It should have created a file in the MySQL Servers datadir +file_exists $MYSQLTEST_VARDIR/master-data/mysql_upgrade_info; --echo Run it again - should say already completed ---exec $MYSQL_UPGRADE 2> $MYSQLTEST_VARDIR/log/mysql_upgrade.err +--replace_result $VERSION VERSION +--error 1 +--exec $MYSQL_UPGRADE --skip-verbose 2>&1 ---echo Force should run it regardless of wheter it's been run before ---exec $MYSQL_UPGRADE --force 2> $MYSQLTEST_VARDIR/log/mysql_upgrade.err +# It should have created a file in the MySQL Servers datadir +file_exists $MYSQLTEST_VARDIR/master-data/mysql_upgrade_info; + +--echo Force should run it regardless of wether it's been run before +--exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 + +# It should have created a file in the MySQL Servers datadir +file_exists $MYSQLTEST_VARDIR/master-data/mysql_upgrade_info; +# +# Bug #25452 mysql_upgrade access denied. +# + +# Password protect a root account and run mysql_upgrade + +CREATE USER mysqltest1@'%' IDENTIFIED by 'sakila'; +GRANT ALL ON *.* TO mysqltest1@'%'; +--echo Run mysql_upgrade with password protected account +--exec $MYSQL_UPGRADE --skip-verbose --force --user=mysqltest1 --password=sakila 2>&1 + +DROP USER mysqltest1@'%'; + + +# +# Bug #26639 mysql_upgrade exits successfully even if external command failed +# + +--echo Run mysql_upgrade with a non existing server socket +--replace_result $MYSQLTEST_VARDIR var +--replace_regex /.*mysqlcheck.*: Got/mysqlcheck: Got/ +--error 1 +--exec $MYSQL_UPGRADE --skip-verbose --force --socket=$MYSQLTEST_VARDIR/tmp/no_sock_here 2>&1 diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt new file mode 100755 index 00000000000..8580844097e --- /dev/null +++ b/scripts/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (C) 2006 MySQL AB +# +# 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 +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +ADD_EXECUTABLE(comp_sql comp_sql.c) +TARGET_LINK_LIBRARIES(comp_sql dbug mysys strings) + +# Build comp_sql - used for embedding SQL in C or C++ programs +GET_TARGET_PROPERTY(COMP_SQL_EXE comp_sql LOCATION) + +ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/client/mysql_fix_privilege_tables_sql.c + COMMAND ${COMP_SQL_EXE} + ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables.sql + ${PROJECT_SOURCE_DIR}/client/mysql_fix_privilege_tables_sql.c + DEPENDS comp_sql ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables.sql) + diff --git a/scripts/Makefile.am b/scripts/Makefile.am index d7053a86b3a..e4a75ab4591 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -165,5 +165,19 @@ SUFFIXES = .sh @CHMOD@ +x $@-t @MV@ $@-t $@ + +BUILT_SOURCES = mysql_fix_privilege_tables_sql.c +noinst_PROGRAMS = comp_sql + +# +# Build mysql_fix_privilege_tables_sql.c from +# mysql_fix_privileges_tables.sql using comp_sql +# +mysql_fix_privilege_tables_sql.c: comp_sql.c mysql_fix_privilege_tables.sql + $(MAKE) $(AM_MAKEFLAGS) comp_sql$(EXEEXT) + $(top_builddir)/scripts/comp_sql$(EXEEXT) \ + mysql_fix_privilege_tables.sql $@ + + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/scripts/comp_sql.c b/scripts/comp_sql.c new file mode 100644 index 00000000000..60236774701 --- /dev/null +++ b/scripts/comp_sql.c @@ -0,0 +1,119 @@ +/* Copyright (C) 2004 MySQL AB + + 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Written by Magnus Svensson +*/ + +/* + Converts a SQL file into a C file that can be compiled and linked + into other programs +*/ + +#include +#include +#include + +FILE *in, *out; + +static void die(const char *fmt, ...) +{ + va_list args; + + /* Print the error message */ + fprintf(stderr, "FATAL ERROR: "); + if (fmt) + { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + } + else + fprintf(stderr, "unknown error"); + fprintf(stderr, "\n"); + fflush(stderr); + + /* Close any open files */ + if (in) + fclose(in); + if (out) + fclose(out); + + exit(1); +} + + +int main(int argc, char *argv[]) +{ + char buff[512]; + char* infile_name= argv[1]; + char* outfile_name= argv[2]; + char* end= infile_name; + + if (argc != 3) + die("Usage: comp_sql "); + + /* Open input and output file */ + if (!(in= fopen(infile_name, "r"))) + die("Failed to open SQL file '%s'", infile_name); + if (!(out= fopen(outfile_name, "w"))) + die("Failed to open output file '%s'", outfile_name); + + while(*end && *end != '.') + end++; + *end= 0; + fprintf(out, "const char* %s={\"\\\n", infile_name); + + while (fgets(buff, sizeof(buff), in)) + { + char *curr= buff; + while (*curr) + { + if (*curr == '\n') + { + /* + Reached end of line, add escaped newline, escaped + backslash and a newline to outfile + */ + fprintf(out, "\\n\\\n"); + curr++; + } + else if (*curr == '\r') + { + curr++; /* Skip */ + } + else + { + if (*curr == '"') + { + /* Needs escape */ + fputc('\\', out); + } + + fputc(*curr, out); + curr++; + } + } + } + + fprintf(out, "\\\n\"};\n"); + + fclose(in); + fclose(out); + + exit(0); + +} + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6667795f5f0..7961aa234c8 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -268,7 +268,6 @@ MY_LOCALE *my_locale_by_number(uint number); #endif #if defined(__WIN__) || defined(OS2) -#define IF_WIN(A,B) (A) #undef FLUSH_TIME #define FLUSH_TIME 1800 /* Flush every half hour */ @@ -277,7 +276,6 @@ MY_LOCALE *my_locale_by_number(uint number); #define WAIT_PRIOR 0 #define QUERY_PRIOR 2 #else -#define IF_WIN(A,B) (B) #define INTERRUPT_PRIOR 10 #define CONNECT_PRIOR 9 #define WAIT_PRIOR 8 From 5c911775429faaf321a44b483be02402d452c740 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 13:50:54 +0200 Subject: [PATCH 02/17] Make it possible to define how many slaves to start by writing --slave-num=n in -master.opt file --- mysql-test/lib/mtr_cases.pl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 8c2dbdec804..2eda77db08e 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -340,6 +340,13 @@ sub collect_one_test_case($$$$$$$) { next; } + $value= mtr_match_prefix($opt, "--slave-num="); + if ( defined $value ) + { + $tinfo->{'slave_num'}= $value; + next; + } + $value= mtr_match_prefix($opt, "--result-file="); if ( defined $value ) { From 4dc441d3c73e45bc9d24a375b75a9bb8e3b4f2dc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 16:56:17 +0200 Subject: [PATCH 03/17] Add mysql builtin $MYSQL_SERVER_VERSION and some function to make it easier to set a variable from string or int --- client/mysqltest.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index d2a01a7689c..4756eedd71b 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1311,23 +1311,31 @@ void var_set(const char *var_name, const char *var_name_end, DBUG_VOID_RETURN; } + +void var_set_string(const char* name, const char* value) +{ + var_set(name, name + strlen(name), value, value + strlen(value)); +} + + +void var_set_int(const char* name, int value) +{ + char buf[21]; + snprintf(buf, sizeof(buf), "%d", value); + var_set_string(name, buf); +} + + /* Store an integer (typically the returncode of the last SQL) - statement in the mysqltest builtin variable $mysql_errno, by - simulating of a user statement "let $mysql_errno= " + statement in the mysqltest builtin variable $mysql_errno */ void var_set_errno(int sql_errno) { - /* TODO MASV make easier */ - const char *var_name= "$mysql_errno"; - char var_val[21]; - uint length= my_sprintf(var_val, (var_val, "%d", sql_errno)); - var_set(var_name, var_name + 12, var_val, var_val + length); - return; + var_set_int("$mysql_errno", sql_errno); } - /* Set variable from the result of a query @@ -5990,6 +5998,8 @@ int main(int argc, char **argv) 1024, 0, 0, get_var_key, var_free, MYF(0))) die("Variable hash initialization failed"); + var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION); + memset(&master_pos, 0, sizeof(master_pos)); parser.current_line= parser.read_lines= 0; From aa043d73bf1a909469f29470934b05a6c4e47973 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 18:38:03 +0200 Subject: [PATCH 04/17] Use my_snprintf instead of snprintf --- client/mysqltest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 4756eedd71b..79dc9564cd0 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1321,7 +1321,7 @@ void var_set_string(const char* name, const char* value) void var_set_int(const char* name, int value) { char buf[21]; - snprintf(buf, sizeof(buf), "%d", value); + my_snprintf(buf, sizeof(buf), "%d", value); var_set_string(name, buf); } From 87a05adf408ae053c116b4009cc3812a91c33274 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 18:40:22 +0200 Subject: [PATCH 05/17] Use my_snprintf instead of snprintf --- client/mysql_upgrade.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 371857816b6..813f5b25bc7 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -269,8 +269,8 @@ static void create_defaults_file(void) Create the option that should be added to tools in order to use this file */ - snprintf(defaults_file_option, sizeof(defaults_file_option), - "--defaults-file=%s", defaults_file_path); + my_snprintf(defaults_file_option, sizeof(defaults_file_option), + "--defaults-file=%s", defaults_file_path); DBUG_PRINT("info", ("defaults_file_option: %s", defaults_file_option)); DBUG_VOID_RETURN; @@ -403,7 +403,7 @@ static void find_tool(char *tool_path, const char *tool_name) /* 2. my_progname contains relative path, prepend wd */ char buf[FN_REFLEN]; my_getwd(buf, FN_REFLEN, MYF(0)); - snprintf(path, FN_REFLEN, "%s%s", buf, my_progname); + my_snprintf(path, FN_REFLEN, "%s%s", buf, my_progname); } else { From 1f949e082dca08c290cc244bbad9475b5ab5358c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 19:00:42 +0200 Subject: [PATCH 06/17] Remove the check for value_start(if any it should be *value_start) --- client/mysql_upgrade.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 813f5b25bc7..92dcb62e8b7 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -505,7 +505,7 @@ static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value) value_start++; /* Don't copy the ending newline */ - if (value_start && (value_end= strchr(value_start, '\n')) == NULL) + if ((value_end= strchr(value_start, '\n')) == NULL) return 1; /* Unexpected result */ strncpy(value, value_start, min(FN_REFLEN, value_end-value_start)); From b4573eb4caff7e2a112c79f7923d565fb836e8a0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2007 19:34:33 +0200 Subject: [PATCH 07/17] Add CMakeLists.txt to EXTRA_DIST --- scripts/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index e4a75ab4591..e9398fc1a72 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -65,7 +65,8 @@ EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ mysqlbug \ make_win_bin_dist \ - mysql_system_tables_fix.sql + mysql_system_tables_fix.sql \ + CMakeLists.txt dist_pkgdata_DATA = fill_help_tables.sql \ mysql_fix_privilege_tables.sql \ From 4fff310ecfc2958483b3b01375c6b54afd443f7a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2007 17:00:29 +0200 Subject: [PATCH 08/17] mysql_upgrade win fixes client/mysql_upgrade.c: Windows fix scripts/CMakeLists.txt: Fix problems with CMakeList causing build to fail scripts/comp_sql.c: Improve comp_sql.c to generate output file with shorter strings --- client/mysql_upgrade.c | 13 ++++++++----- scripts/CMakeLists.txt | 9 ++++++--- scripts/comp_sql.c | 4 ++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 92dcb62e8b7..df70ed2c148 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -335,6 +335,10 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) va_end(args); +#ifdef __WIN__ + dynstr_append(&ds_cmdline, "\""); +#endif + DBUG_PRINT("info", ("Running: %s", ds_cmdline.str)); ret= run_command(ds_cmdline.str, ds_res); DBUG_PRINT("exit", ("ret: %d", ret)); @@ -354,11 +358,11 @@ static my_bool get_full_path_to_executable(char* path) { my_bool ret; DBUG_ENTER("get_full_path_to_executable"); -#ifdef WIN - ret= GetModuleFileName(NULL, path, FN_REFLEN) != 0; +#ifdef __WIN__ + ret= (GetModuleFileName(NULL, path, FN_REFLEN) == 0); #else /* my_readlink returns 0 if a symlink was read */ - ret= my_readlink(path, "/proc/self/exe", MYF(0)) != 0; + ret= (my_readlink(path, "/proc/self/exe", MYF(0)) != 0); /* Might also want to try with /proc/$$/exe if the above fails */ #endif DBUG_PRINT("exit", ("path: %s", path)); @@ -416,8 +420,7 @@ static void find_tool(char *tool_path, const char *tool_name) DBUG_PRINT("enter", ("path: %s", path)); /* Chop off last char(since it might be a /) */ - size_t pos= max((strlen(path)-1), 0); - path[pos]= 0; + path[max((strlen(path)-1), 0)]= 0; /* Chop off last dir part */ dirname_part(path, path); diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 8580844097e..cb5efd0ff9b 100755 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -20,9 +20,12 @@ TARGET_LINK_LIBRARIES(comp_sql dbug mysys strings) # Build comp_sql - used for embedding SQL in C or C++ programs GET_TARGET_PROPERTY(COMP_SQL_EXE comp_sql LOCATION) -ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/client/mysql_fix_privilege_tables_sql.c +ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables_sql.c COMMAND ${COMP_SQL_EXE} - ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables.sql - ${PROJECT_SOURCE_DIR}/client/mysql_fix_privilege_tables_sql.c + mysql_fix_privilege_tables.sql + mysql_fix_privilege_tables_sql.c DEPENDS comp_sql ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables.sql) +ADD_CUSTOM_TARGET(GenFixPrivs + ALL + DEPENDS ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables_sql.c) diff --git a/scripts/comp_sql.c b/scripts/comp_sql.c index 60236774701..328dab0cf13 100644 --- a/scripts/comp_sql.c +++ b/scripts/comp_sql.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) while(*end && *end != '.') end++; *end= 0; - fprintf(out, "const char* %s={\"\\\n", infile_name); + fprintf(out, "const char* %s={\n\"", infile_name); while (fgets(buff, sizeof(buff), in)) { @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) Reached end of line, add escaped newline, escaped backslash and a newline to outfile */ - fprintf(out, "\\n\\\n"); + fprintf(out, "\\n \"\n\""); curr++; } else if (*curr == '\r') From dea53d619b4e3e5f3eaaf26d83d5f35b922d3e82 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2007 17:01:19 +0200 Subject: [PATCH 09/17] Build zlib before extra since extra/comp_err uses zlib --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60ed1275521..b7f7a7228bc 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,10 +134,10 @@ ADD_SUBDIRECTORY(strings) ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(mysys) ADD_SUBDIRECTORY(scripts) +ADD_SUBDIRECTORY(zlib) ADD_SUBDIRECTORY(extra/yassl) ADD_SUBDIRECTORY(extra/yassl/taocrypt) ADD_SUBDIRECTORY(extra) -ADD_SUBDIRECTORY(zlib) ADD_SUBDIRECTORY(heap) ADD_SUBDIRECTORY(myisam) ADD_SUBDIRECTORY(myisammrg) From ffd062f7c7073e3f082e8cd35a25acd10c38d1ae Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2007 18:32:55 +0200 Subject: [PATCH 10/17] mysql_upgrade depends on GenFixPrivs --- client/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 785bba738bf..b598c77ddfc 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -83,6 +83,7 @@ TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wso ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c ../mysys/my_getpagesize.c) TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient mysys dbug yassl taocrypt zlib wsock32) +ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs) ADD_EXECUTABLE(mysqlshow mysqlshow.c) TARGET_LINK_LIBRARIES(mysqlshow mysqlclient mysys dbug yassl taocrypt zlib wsock32) From 36cd228af11ab85df1dbab55138316933107f8bd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2007 21:30:46 +0200 Subject: [PATCH 11/17] mysql_upgrade portability fixes client/mysql_upgrade.c: Add defines for WEXITSTATUS Pass arguments on command line instead of --defaults-file= mysql-test/r/mysql_upgrade.result: When testing that mysql_upgrade detect if mysqlcheck fails, use an option that is used on all platforms. mysql-test/t/mysql_upgrade.test: When testing that mysql_upgrade detect if mysqlcheck fails, use an option that is used on all platforms. scripts/comp_sql.c: Some compilers have a max string length, insert a newline at every 512th char in long strings --- client/mysql_upgrade.c | 111 ++++++++++-------------------- mysql-test/r/mysql_upgrade.result | 2 +- mysql-test/t/mysql_upgrade.test | 2 +- scripts/comp_sql.c | 9 +++ 4 files changed, 46 insertions(+), 78 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index df70ed2c148..d67933fa240 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -17,14 +17,25 @@ #include #include "../scripts/mysql_fix_privilege_tables_sql.c" +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifndef WEXITSTATUS +# ifdef __WIN__ +# define WEXITSTATUS(stat_val) (stat_val) +# else +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +# endif +#endif + static char mysql_path[FN_REFLEN]; static char mysqlcheck_path[FN_REFLEN]; -static char defaults_file_option[32+FN_REFLEN]; static my_bool opt_force, opt_verbose; static char *opt_user= (char*)"root"; -static DYNAMIC_STRING ds_options; +static DYNAMIC_STRING ds_args; static char *opt_password= 0; static my_bool tty_password= 0; @@ -35,8 +46,6 @@ static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace"; static char **defaults_argv; -static File defaults_fd= -1; - static my_bool not_used; /* Can't use GET_BOOL without a value pointer */ #include @@ -105,14 +114,10 @@ static struct my_option my_long_options[]= static void free_used_memory(void) { - /* Close the defaults file */ - if (defaults_fd != -1) - my_close(defaults_fd, MYF(0)); - /* Free memory allocated by 'load_defaults' */ free_defaults(defaults_argv); - dynstr_free(&ds_options); + dynstr_free(&ds_args); } @@ -159,30 +164,30 @@ static void verbose(const char *fmt, ...) /* Add one option - passed to mysql_upgrade on command line - or by defaults file(my.cnf) - to a dynamic string that later - can be written to a temporary file. In this way we pass the - same arguments on to mysql and mysql_check + or by defaults file(my.cnf) - to a dynamic string, in + this way we pass the same arguments on to mysql and mysql_check */ static void add_one_option(DYNAMIC_STRING* ds, const struct my_option *opt, const char* argument) -{ - dynstr_append(ds, opt->name); +{ + const char* eq= NullS; + const char* arg= NullS; if (opt->arg_type != NO_ARG) { - dynstr_append(ds, "="); + eq= "="; switch (opt->var_type & GET_TYPE_MASK) { case GET_STR: - case GET_STR_ALLOC: - dynstr_append(ds, argument); + arg= argument; break; default: die("internal error at %s: %d",__FILE__, __LINE__); } } - dynstr_append(ds, "\n"); + dynstr_append_os_quoted(ds, "--", opt->name, eq, arg, NullS); + dynstr_append(&ds_args, " "); } @@ -211,8 +216,8 @@ get_one_option(int optid, const struct my_option *opt, add_option= FALSE; if (argument) { - /* Add password to ds_options before overwriting the arg with x's */ - add_one_option(&ds_options, opt, argument); + /* Add password to ds_args before overwriting the arg with x's */ + add_one_option(&ds_args, opt, argument); while (*argument) *argument++= 'x'; /* Destroy argument */ tty_password= 0; @@ -232,51 +237,14 @@ get_one_option(int optid, const struct my_option *opt, /* This is an option that is accpted by mysql_upgrade just so it can be passed on to "mysql" and "mysqlcheck" - Save it in the ds_options string + Save it in the ds_args string */ - add_one_option(&ds_options, opt, argument); + add_one_option(&ds_args, opt, argument); } return 0; } -/* - Write the options that should be passed on to - mysql and mysqlcheck to a temporary file -*/ - -static void create_defaults_file(void) -{ - static char defaults_file_path[FN_REFLEN]; - DBUG_ENTER("create_defaults_file"); - - if ((defaults_fd= create_temp_file(defaults_file_path, NULL, - "cnf", O_CREAT | O_SHARE, - MYF(MY_WME))) < 0) - die("Failed to create temporary file for defaults"); - - DBUG_PRINT("info", ("Writing options: %s", ds_options.str)); - if (my_write(defaults_fd, ds_options.str, ds_options.length, - MYF(MY_FNABP | MY_WME))) - die("Failed to write to '%s'", defaults_file_path); - - /* - Dont close the temporary file yet, it will be used - by mysql and mysqlcheck - */ - - /* - Create the option that should be added to - tools in order to use this file - */ - my_snprintf(defaults_file_option, sizeof(defaults_file_option), - "--defaults-file=%s", defaults_file_path); - DBUG_PRINT("info", ("defaults_file_option: %s", defaults_file_option)); - - DBUG_VOID_RETURN; -} - - static int run_command(char* cmd, DYNAMIC_STRING *ds_res) { @@ -466,7 +434,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, DBUG_ENTER("run_query"); DBUG_PRINT("enter", ("query: %s", query)); if ((fd= create_temp_file(query_file_path, NULL, - "sql", O_CREAT | O_SHARE, + "sql", O_CREAT | O_SHARE | O_RDWR, MYF(MY_WME))) < 0) die("Failed to create temporary file for defaults"); @@ -476,7 +444,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, ret= run_tool(mysql_path, ds_res, - defaults_file_option, + ds_args.str, // MASV... quoted? "--database=mysql", "--batch", /* Turns off pager etc. */ force ? "--force": "--skip-force", @@ -631,7 +599,7 @@ static int run_mysqlcheck_upgrade(void) verbose("Running 'mysqlcheck'..."); return run_tool(mysqlcheck_path, NULL, /* Send output from mysqlcheck directly to screen */ - defaults_file_option, + ds_args.str, "--check-upgrade", "--all-databases", "--auto-repair", @@ -747,7 +715,7 @@ int main(int argc, char **argv) setscreenmode(SCR_AUTOCLOSE_ON_EXIT); #endif - if (init_dynamic_string(&ds_options, "[client]\n", 512, 256)) + if (init_dynamic_string(&ds_args, "", 512, 256)) die("Out of memory"); load_defaults("my", load_default_groups, &argc, &argv); @@ -760,14 +728,12 @@ int main(int argc, char **argv) { opt_password= get_tty_password(NullS); /* add password to defaults file */ - dynstr_append(&ds_options, "password="); - dynstr_append(&ds_options, opt_password); - dynstr_append(&ds_options, "\n"); + dynstr_append_os_quoted(&ds_args, "--password=", opt_password, NullS); + dynstr_append(&ds_args, " "); } /* add user to defaults file */ - dynstr_append(&ds_options, "user="); - dynstr_append(&ds_options, opt_user); - dynstr_append(&ds_options, "\n"); + dynstr_append_os_quoted(&ds_args, "--user=", opt_user, NullS); + dynstr_append(&ds_args, " "); /* Find mysql */ find_tool(mysql_path, IF_WIN("mysql.exe", "mysql")); @@ -775,13 +741,6 @@ int main(int argc, char **argv) /* Find mysqlcheck */ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck")); - /* - Create the defaults file(a small my.cnf) which will pass - all arguments accepted by mysql_upgrade on to mysqlcheck - and mysql command line client - */ - create_defaults_file(); - /* Read the mysql_upgrade_info file to check if mysql_upgrade already has been run for this installation of MySQL diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index ce4706c6d92..f8b55a7ce49 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -58,5 +58,5 @@ mysql.time_zone_transition_type OK mysql.user OK DROP USER mysqltest1@'%'; Run mysql_upgrade with a non existing server socket -mysqlcheck: Got error: 2002: Can't connect to local MySQL server through socket 'var/tmp/no_sock_here' (2) when trying to connect +mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (1) when trying to connect FATAL ERROR: Upgrade failed diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index 973e9157987..7ac7aecb838 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -58,4 +58,4 @@ DROP USER mysqltest1@'%'; --replace_result $MYSQLTEST_VARDIR var --replace_regex /.*mysqlcheck.*: Got/mysqlcheck: Got/ --error 1 ---exec $MYSQL_UPGRADE --skip-verbose --force --socket=$MYSQLTEST_VARDIR/tmp/no_sock_here 2>&1 +--exec $MYSQL_UPGRADE --skip-verbose --force --host=not_existing_host 2>&1 diff --git a/scripts/comp_sql.c b/scripts/comp_sql.c index 328dab0cf13..53359d384c1 100644 --- a/scripts/comp_sql.c +++ b/scripts/comp_sql.c @@ -106,6 +106,15 @@ int main(int argc, char *argv[]) curr++; } } + if (*(curr-1) != '\n') + { + /* + Some compilers have a max string length, + insert a newline at every 512th char in long + strings + */ + fprintf(out, "\"\n\""); + } } fprintf(out, "\\\n\"};\n"); From 45face8fb459740d268e778250d16bb9346f53e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2007 21:35:10 +0200 Subject: [PATCH 12/17] Add replace for varying errno --- mysql-test/r/mysql_upgrade.result | 2 +- mysql-test/t/mysql_upgrade.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index f8b55a7ce49..0c32f413bd8 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -58,5 +58,5 @@ mysql.time_zone_transition_type OK mysql.user OK DROP USER mysqltest1@'%'; Run mysql_upgrade with a non existing server socket -mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (1) when trying to connect +mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (errno) when trying to connect FATAL ERROR: Upgrade failed diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index 7ac7aecb838..51db2e99efd 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -56,6 +56,6 @@ DROP USER mysqltest1@'%'; --echo Run mysql_upgrade with a non existing server socket --replace_result $MYSQLTEST_VARDIR var ---replace_regex /.*mysqlcheck.*: Got/mysqlcheck: Got/ +--replace_regex /.*mysqlcheck.*: Got/mysqlcheck: Got/ /\([0-9]*\)/(errno)/ --error 1 --exec $MYSQL_UPGRADE --skip-verbose --force --host=not_existing_host 2>&1 From 1f6c9a58fbf1c4851008b9dd706d4fad8ee986db Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Apr 2007 07:20:26 +0200 Subject: [PATCH 13/17] Remove comment --- client/mysql_upgrade.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index d67933fa240..aeda47c48eb 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -444,7 +444,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, ret= run_tool(mysql_path, ds_res, - ds_args.str, // MASV... quoted? + ds_args.str, "--database=mysql", "--batch", /* Turns off pager etc. */ force ? "--force": "--skip-force", From d19d4b3f4f24c01f79cd4d281ae351e5a7faa2fa Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Apr 2007 11:01:22 +0200 Subject: [PATCH 14/17] Protect against killing pid's that would "killall" or "kill self" --- mysql-test/lib/mtr_process.pl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index e9e0dcce1b8..ad0fea465d6 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -1086,6 +1086,13 @@ sub mtr_kill_processes ($) { foreach my $pid (@$pids) { + + if ($pid <= 0) + { + mtr_warning("Trying to kill illegal pid: $pid"); + next; + } + foreach my $sig (15, 9) { last if mtr_im_kill_process([ $pid ], $sig, 10, 1); From 18ea5386484af6c7cc6dc00fd0cad09c362db0ff Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Apr 2007 11:41:55 +0200 Subject: [PATCH 15/17] Remove left over file fix_priv_tabs.result BitKeeper/deleted/.del-fix_priv_tabs.result: Delete: mysql-test/r/fix_priv_tabs.result --- mysql-test/r/fix_priv_tabs.result | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 mysql-test/r/fix_priv_tabs.result diff --git a/mysql-test/r/fix_priv_tabs.result b/mysql-test/r/fix_priv_tabs.result deleted file mode 100644 index e69de29bb2d..00000000000 From 166af98f4464378b338c95cf9ae0ee9d702e8cbc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Apr 2007 11:46:47 +0200 Subject: [PATCH 16/17] Remove left over file abi_check BitKeeper/deleted/.del-abi_check: Delete: include/abi_check --- include/abi_check | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 include/abi_check diff --git a/include/abi_check b/include/abi_check deleted file mode 100644 index e69de29bb2d..00000000000 From 6a05f2af3c14bf6fe7498d3fc11b37d08fc2ccf6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Apr 2007 12:02:58 +0200 Subject: [PATCH 17/17] Fix warnings reported by icc --- tests/mysql_client_test.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index d64ec08a71d..ae332edcdd8 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -85,7 +85,7 @@ struct my_tests_st if (opt_silent < 2) \ { \ fprintf(stdout, "\n\n#####################################\n"); \ - fprintf(stdout, "%d of (%d/%d): %s", test_count++, iter_count, \ + fprintf(stdout, "%u of (%u/%u): %s", test_count++, iter_count, \ opt_count, str); \ fprintf(stdout, " \n#####################################\n"); \ } @@ -99,7 +99,7 @@ if (!opt_silent) \ static void print_error(const char *msg); static void print_st_error(MYSQL_STMT *stmt, const char *msg); -static void client_disconnect(); +static void client_disconnect(void); /* @@ -118,7 +118,7 @@ static void client_disconnect(); #define DIE(expr) \ die(__FILE__, __LINE__, #expr) -void die(const char *file, int line, const char *expr) +static void die(const char *file, int line, const char *expr) { fflush(stdout); fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr); @@ -252,7 +252,7 @@ static my_bool check_have_innodb(MYSQL *conn) mysql_simple_prepare(): a variant without the 'length' parameter. */ -MYSQL_STMT *STDCALL +static MYSQL_STMT *STDCALL mysql_simple_prepare(MYSQL *mysql_arg, const char *query) { MYSQL_STMT *stmt= mysql_stmt_init(mysql_arg); @@ -467,7 +467,7 @@ static void my_print_result_metadata(MYSQL_RES *result) /* Process the result set */ -int my_process_result_set(MYSQL_RES *result) +static int my_process_result_set(MYSQL_RES *result) { MYSQL_ROW row; MYSQL_FIELD *field; @@ -523,7 +523,7 @@ int my_process_result_set(MYSQL_RES *result) } -int my_process_result(MYSQL *mysql_arg) +static int my_process_result(MYSQL *mysql_arg) { MYSQL_RES *result; int row_count; @@ -543,7 +543,7 @@ int my_process_result(MYSQL *mysql_arg) #define MAX_RES_FIELDS 50 #define MAX_FIELD_DATA_SIZE 255 -int my_process_stmt_result(MYSQL_STMT *stmt) +static int my_process_stmt_result(MYSQL_STMT *stmt) { int field_count; int row_count= 0;