mirror of
https://github.com/MariaDB/server.git
synced 2025-02-02 12:01:42 +01:00
09a53f28a7
Faster thr_alarm() Added 'Opened_files' status variable to track calls to my_open() Don't give warnings when running mysql_install_db Added option --source-install to mysql_install_db I had to do the following renames() as used polymorphism didn't work with Forte compiler on 64 bit systems index_read() -> index_read_map() index_read_idx() -> index_read_idx_map() index_read_last() -> index_read_last_map() BUILD/compile-solaris-sparc-forte: Updated script to current Solaris installations Now we compile by default for 64 bits client/mysql.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) client/mysql_upgrade.c: Fixed compiler warning (on Forte) client/mysqladmin.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) client/mysqlcheck.c: Fixed compiler warning (on Forte) client/mysqldump.c: Fixed compiler warning (on Forte) client/mysqlslap.c: Fixed compiler warning (on Forte) client/mysqltest.c: Fixed compiler warning (on Forte) client/sql_string.cc: Avoid compiler warnings when using C function pointers in C++ configure.in: Added detection of mtmalloc and ieeefp.h extra/replace.c: Fixed compiler warning (on Forte) include/m_ctype.h: Added some typedef's to make it easy to use C function pointers in C++ include/my_sys.h: Added my_file_total_opened (counter for calls to my_open()) include/myisam.h: Fixed compiler warning (on Forte) libmysql/libmysql.c: Fixed compiler warning (on Forte) by adding casts and change types libmysql/manager.c: Fixed compiler warning (on Forte) by adding casts and change types mysql-test/r/ctype_cp932_binlog_stm.result: Updated positions (Needed because we didn't before correctly restore collation_database after running stored procedure mysys/my_fopen.c: Count number of opened files mysys/my_open.c: Count number of opened files mysys/my_static.c: Count number of opened files mysys/thr_alarm.c: Optimization to do less alarm() and pthread_sigmask() calls. Idea is to remember time for next pending alarm and not reschedule a new alarm if it's after the current one. Before we only did this if there was other pending alarms. We don't have to use pthread_sigmask() in case of 'USE_ONE_SIGNAL_HAND' as the alarm() signal will be blocked for the calling thread anyway and no other thread will have the alarm() signal enabled to call process_alarm() regex/regcomp.c: Fixed compiler warning (on Forte) by adding casts and change types scripts/mysql_install_db.sh: Added option --source-install to allow one to create a mysql database from the source tree without installing MySQL Don't give (unnecessary) warnings server-tools/instance-manager/angel.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) server-tools/instance-manager/thread_registry.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/event_db_repository.cc: index_read() -> index_read_map() sql/event_queue.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/field.cc: Fixed compiler warnings about hidden fields sql/ha_partition.cc: Fixed compiler warnings about hidden fields index_read() -> index_read_map() sql/ha_partition.h: index_read() -> index_read_map() sql/handler.cc: Added PAGE option to row types (to prepare for future) index_read() -> index_read_map() sql/handler.h: Added ROW_TYPE_PAGE (for future) Added flag to signal if table was to be created transactionally I had to do the following renames() as used polymorphism didn't work with Forte compiler on 64 bit systems index_read() -> index_read_map() index_read_idx() -> index_read_idx_map() index_read_last() -> index_read_last_map() sql/item.cc: Fixed indentation Renamed local variable to avoid hiding class variable sql/item_cmpfunc.cc: Renamed local variable to avoid hiding class variable sql/item_cmpfunc.h: Removed not used variable sql/item_func.cc: Renamed local variable to avoid hiding class variable sql/item_strfunc.cc: Moved functions from Item_strfunc.cc sql/item_strfunc.h: Move functions to item_strfunc.cc Use C function pointer type to avoid compiler warnings (with Forte) sql/item_subselect.cc: index_read() -> index_read_map() sql/item_xmlfunc.cc: Renamed local variable to avoid hiding class variable Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/key.cc: Fixed indentation sql/log.cc: Renamed local variable to avoid hiding class variable sql/log_event.cc: Removed call to my_time() when creating class instance of Log_event() as this may have static instances. (One can't call my_time() before my_init()) index_read() -> index_read_map() Renamed local variable to avoid hiding class variable sql/log_event_old.cc: Renamed local variable to avoid hiding class variable sql/mysql_priv.h: Made all create_backup_ctx() declarations identical. This lifted up a bug where wrong create_backup_ctx() was called in some cases. Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/mysqld.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) Fixed indentation Don't call end_thr_alarm() when calling unireg_abort() as unireg_abort() already calls end_thr_alarm() Added variable 'Opened_files' (number of calls to my_open() or my_fopen()) Don't print 'loose' warnings when using --bootstrap (to avoid warnings when running mysql_install_db) Fixed compiler warnings sql/opt_range.cc: index_read() -> index_read_map() sql/opt_sum.cc: index_read() -> index_read_map() sql/partition_info.cc: Renamed local variable to avoid hiding class variable sql/rpl_filter.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/set_var.cc: Renamed local variable to avoid hiding class variable Added 'process_key_cache_t' type to avoid compiler warning (on Forte) sql/set_var.h: Added 'process_key_cache_t' type to avoid compiler warning (on Forte) sql/sp.cc: More debugging index_read() -> index_read_map() sql/sp_cache.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/sp_head.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) Moved 'saved_creation_ctx' higher up to be able to free objects allocated by create_backup_ctx() sql/sql_acl.cc: index_read() -> index_read_map() sql/sql_class.cc: Renamed local variable to avoid hiding class variable Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/sql_class.h: Renamed local variable to avoid hiding class variable sql/sql_db.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) sql/sql_delete.cc: Renamed local variable to avoid hiding class variable sql/sql_handler.cc: index_read() -> index_read_map() sql/sql_help.cc: index_read() -> index_read_map() sql/sql_insert.cc: index_read() -> index_read_map() Renamed local variable to avoid hiding class variable sql/sql_lex.cc: Renamed local variable to avoid hiding class variable sql/sql_plugin.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) index_read() -> index_read_map() Don't give warnings about not used plugins if we are using --warnings=0 sql/sql_select.cc: index_read() -> index_read_map() sql-common/client.c: Fixed compiler warning (on Forte) sql-common/my_time.c: Removed never accessed code Fixed compiler warning (on Forte) sql/sql_servers.cc: index_read() -> index_read_map() sql/sql_show.cc: Added TRANSACTIONAL to SHOW CREATE Fixed ROW_TYPE_PAGE sql/sql_string.cc: Avoid compiler warnings when using C function pointers in C++ sql/sql_table.cc: Set create_info->transactional if we used TRANSACTIONAL=1 sql/sql_udf.cc: index_read() -> index_read_map() sql/sql_yacc.yy: Added TRANSACTIONAL=0|1 to CREATE (for future) Added row type PAGE (was only partionally handled before) sql/strfunc.cc: Avoid compiler warnings when using C function pointers in C++ sql/table.cc: More DBUG statements Declare all create_backup_ctx() functions identically Remember if table was created with TRANSACTIONAL flag or not (future safe) Renamed local variable to avoid hiding class variable sql/table.h: Remember if table was created with TRANSACTIONAL=1 sql/tztime.cc: index_read() -> index_read_map() sql-common/pack.c: Fixed compiler warning (on Forte) storage/archive/archive_reader.c: Fixed compiler warning (on Forte) storage/archive/azio.c: Fixed compiler warning (on Forte) storage/blackhole/ha_blackhole.cc: index_read() -> index_read_map() storage/blackhole/ha_blackhole.h: index_read() -> index_read_map() storage/csv/ha_tina.cc: Declare functions sent to C code with extern "C" to avoid compiler warnings (on Forte) storage/example/ha_example.cc: index_read() -> index_read_map() storage/example/ha_example.h: index_read() -> index_read_map() storage/heap/ha_heap.cc: index_read() -> index_read_map() storage/heap/ha_heap.h: index_read() -> index_read_map() storage/heap/hp_test1.c: Fixed compiler warning (on Forte) storage/heap/hp_test2.c: Fixed compiler warning (on Forte) storage/myisam/ft_boolean_search.c: Fixed compiler warning (on Forte) storage/myisam/ft_nlq_search.c: Fixed compiler warning (on Forte) storage/myisam/ft_parser.c: Fixed compiler warning (on Forte) storage/myisam/ft_stopwords.c: Fixed compiler warning (on Forte) storage/myisam/ha_myisam.cc: index_read() -> index_read_map() storage/myisam/ha_myisam.h: index_read() -> index_read_map() storage/myisam/mi_check.c: Fixed compiler warning (on Forte) storage/myisam/mi_delete.c: Fixed compiler warning (on Forte) storage/myisam/mi_dynrec.c: Fixed compiler warning (on Forte) storage/myisam/mi_extra.c: Fixed compiler warning (on Forte) storage/myisam/mi_key.c: Fixed compiler warning (on Forte) storage/myisam/mi_keycache.c: Fixed compiler warning (on Forte) storage/myisam/mi_locking.c: Fixed compiler warning (on Forte) storage/myisam/mi_log.c: Fixed compiler warning (on Forte) storage/myisam/mi_open.c: Fixed compiler warning (on Forte) storage/myisam/mi_packrec.c: Fixed compiler warning (on Forte) storage/myisam/mi_page.c: Fixed compiler warning (on Forte) storage/myisam/mi_rkey.c: Added comment storage/myisam/mi_search.c: Fixed compiler warning (on Forte) storage/myisam/mi_statrec.c: Fixed compiler warning (on Forte) storage/myisam/mi_test1.c: Fixed compiler warning (on Forte) storage/myisam/mi_test2.c: Fixed compiler warning (on Forte) storage/myisam/mi_test3.c: Fixed compiler warning (on Forte) storage/myisam/mi_update.c: Fixed compiler warning (on Forte) storage/myisam/mi_write.c: Fixed compiler warning (on Forte) storage/myisam/myisamdef.h: Fixed that file_read/file_write returns type size_t Changed some functions to use uchar * as argument/return value instead of char* This fixed some compiler warnings on Forte storage/myisam/myisamlog.c: Fixed compiler warning (on Forte) storage/myisam/myisampack.c: Fixed compiler warning (on Forte) storage/myisam/rt_test.c: Fixed compiler warning (on Forte) storage/myisam/sort.c: Fixed compiler warning (on Forte) by adding casts or changing variables to uchar* storage/myisam/sp_test.c: Fixed compiler warning (on Forte) by adding casts or changing variables to uchar* storage/myisammrg/ha_myisammrg.cc: index_read() -> index_read_map() storage/myisammrg/ha_myisammrg.h: index_read() -> index_read_map() storage/myisammrg/myrg_create.c: Fixed compiler warning (on Forte) by adding casts or changing variable types storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp: Tdummy -> align (as in other part of cluster code) storage/ndb/src/kernel/vm/DynArr256.cpp: Removed not used variable storage/ndb/src/ndbapi/Ndb.cpp: Removed not used variable strings/strtod.c: Include ieeefp.h to avoid compiler warning tests/bug25714.c: Fixed compiler warning tests/mysql_client_test.c: Remove not used variable Fixed indentation Removed never reached code Fixed compiler warning (on Forte) by adding casts or changing variable types vio/viosocket.c: Fixed compiler warning (on Forte) by adding casts or changing variable types
800 lines
20 KiB
C
800 lines
20 KiB
C
/* Copyright (C) 2000 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 */
|
|
|
|
#include "client_priv.h"
|
|
#include <sslopt-vars.h>
|
|
#include "../scripts/mysql_fix_privilege_tables_sql.c"
|
|
|
|
#define VER "1.1"
|
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
|
#include <sys/wait.h>
|
|
#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 my_bool opt_force, opt_verbose, debug_info_flag, debug_check_flag;
|
|
static uint my_end_arg= 0;
|
|
static char *opt_user= (char*)"root";
|
|
|
|
static DYNAMIC_STRING ds_args;
|
|
|
|
static char *opt_password= 0;
|
|
static my_bool tty_password= 0;
|
|
|
|
#ifndef DBUG_OFF
|
|
static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace";
|
|
#endif
|
|
|
|
static char **defaults_argv;
|
|
|
|
static my_bool not_used; /* Can't use GET_BOOL without a value pointer */
|
|
|
|
#include <help_start.h>
|
|
|
|
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', "Not used by mysql_upgrade. Only for backward compatibilty",
|
|
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
{"character-sets-dir", OPT_CHARSETS_DIR,
|
|
"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.",
|
|
(uchar**)¬_used, (uchar**)¬_used, 0, GET_BOOL, NO_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},
|
|
#else
|
|
{"debug", '#', "Output debug log", (uchar* *) & default_dbug_option,
|
|
(uchar* *) & 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 .",
|
|
(uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
|
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
|
{"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag,
|
|
(uchar**) &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
|
{"default-character-set", OPT_DEFAULT_CHARSET,
|
|
"Set the default character set.", 0,
|
|
0, 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.",
|
|
(uchar**)&opt_force, (uchar**)&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.", (uchar**) &opt_password,(uchar**) &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,
|
|
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
|
#endif
|
|
{"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.", 0,
|
|
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
#endif
|
|
{"socket", 'S', "Socket file to use for connection.",
|
|
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
{"user", 'u', "User for login if not current user.", (uchar**) &opt_user,
|
|
(uchar**) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
#include <sslopt-longopts.h>
|
|
{"verbose", 'v', "Display more output about the process",
|
|
(uchar**) &opt_verbose, (uchar**) &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}
|
|
};
|
|
|
|
#include <help_end.h>
|
|
|
|
|
|
static void free_used_memory(void)
|
|
{
|
|
/* Free memory allocated by 'load_defaults' */
|
|
free_defaults(defaults_argv);
|
|
|
|
dynstr_free(&ds_args);
|
|
}
|
|
|
|
|
|
static void die(const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
DBUG_ENTER("die");
|
|
|
|
/* 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);
|
|
|
|
free_used_memory();
|
|
my_end(my_end_arg);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
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, 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)
|
|
|
|
{
|
|
const char* eq= NullS;
|
|
const char* arg= NullS;
|
|
if (opt->arg_type != NO_ARG)
|
|
{
|
|
eq= "=";
|
|
switch (opt->var_type & GET_TYPE_MASK) {
|
|
case GET_STR:
|
|
arg= argument;
|
|
break;
|
|
default:
|
|
die("internal error at %s: %d",__FILE__, __LINE__);
|
|
}
|
|
}
|
|
dynstr_append_os_quoted(ds, "--", opt->name, eq, arg, NullS);
|
|
dynstr_append(&ds_args, " ");
|
|
}
|
|
|
|
|
|
static my_bool
|
|
get_one_option(int optid, const struct my_option *opt,
|
|
char *argument)
|
|
{
|
|
my_bool add_option= TRUE;
|
|
|
|
switch (optid) {
|
|
|
|
case '?':
|
|
printf("%s Ver %s Distrib %s, for %s (%s)\n",
|
|
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
|
|
puts("MySQL utility for upgrading databases to new MySQL versions\n");
|
|
my_print_help(my_long_options);
|
|
exit(0);
|
|
break;
|
|
|
|
case '#':
|
|
DBUG_PUSH(argument ? argument : default_dbug_option);
|
|
add_option= FALSE;
|
|
debug_check_flag= 1;
|
|
break;
|
|
|
|
case 'p':
|
|
tty_password= 1;
|
|
add_option= FALSE;
|
|
if (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;
|
|
}
|
|
break;
|
|
|
|
case 'b': /* --basedir */
|
|
case 'v': /* --verbose */
|
|
case 'd': /* --datadir */
|
|
case 'f': /* --force */
|
|
add_option= FALSE;
|
|
break;
|
|
}
|
|
|
|
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_args string
|
|
*/
|
|
add_one_option(&ds_args, opt, argument);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int run_command(char* cmd,
|
|
DYNAMIC_STRING *ds_res)
|
|
{
|
|
char buf[512]= {0};
|
|
FILE *res_file;
|
|
int error;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
error= pclose(res_file);
|
|
return WEXITSTATUS(error);
|
|
}
|
|
|
|
|
|
static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...)
|
|
{
|
|
int ret;
|
|
const char* arg;
|
|
va_list args;
|
|
DYNAMIC_STRING ds_cmdline;
|
|
|
|
DBUG_ENTER("run_tool");
|
|
DBUG_PRINT("enter", ("tool_path: %s", tool_path));
|
|
|
|
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 *)))
|
|
{
|
|
/* 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, " ");
|
|
}
|
|
|
|
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));
|
|
dynstr_free(&ds_cmdline);
|
|
DBUG_RETURN(ret);
|
|
}
|
|
|
|
|
|
/*
|
|
Try to get the full path to this exceutable
|
|
|
|
Return 0 if path found
|
|
|
|
*/
|
|
|
|
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);
|
|
#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);
|
|
}
|
|
|
|
|
|
/*
|
|
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)
|
|
{
|
|
char path[FN_REFLEN];
|
|
DYNAMIC_STRING ds_tmp;
|
|
DBUG_ENTER("find_tool");
|
|
DBUG_PRINT("enter", ("progname: %s", my_progname));
|
|
|
|
if (init_dynamic_string(&ds_tmp, "", 32, 32))
|
|
die("Out of memory");
|
|
|
|
/* Initialize path with the full path to this program */
|
|
if (get_full_path_to_executable(path))
|
|
{
|
|
/*
|
|
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));
|
|
my_snprintf(path, FN_REFLEN, "%s%s", buf, my_progname);
|
|
}
|
|
else
|
|
{
|
|
/* 3. Just go for it and hope tool is in path */
|
|
path[0]= 0;
|
|
}
|
|
}
|
|
do
|
|
{
|
|
size_t path_len;
|
|
DBUG_PRINT("enter", ("path: %s", path));
|
|
|
|
/* Chop off last char(since it might be a /) */
|
|
path[max((strlen(path)-1), 0)]= 0;
|
|
|
|
/* Chop off last dir part */
|
|
dirname_part(path, path, &path_len);
|
|
|
|
/* 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 | O_RDWR,
|
|
MYF(MY_WME))) < 0)
|
|
die("Failed to create temporary file for defaults");
|
|
|
|
if (my_write(fd, (uchar*) query, strlen(query),
|
|
MYF(MY_FNABP | MY_WME)))
|
|
die("Failed to write to '%s'", query_file_path);
|
|
|
|
ret= run_tool(mysql_path,
|
|
ds_res,
|
|
ds_args.str,
|
|
"--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<datadir>\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_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 */
|
|
fputs(MYSQL_SERVER_VERSION, out);
|
|
my_fclose(out, MYF(0));
|
|
|
|
/*
|
|
Check if the upgrad_info_file was properly created/updated
|
|
It's not a fatal error -> just print a message if it fails
|
|
*/
|
|
if (!upgrade_already_done())
|
|
fprintf(stderr,
|
|
"Could not write to the upgrade info file '%s' in "
|
|
"the MySQL Servers datadir, errno: %d\n",
|
|
upgrade_info_file, errno);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
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 */
|
|
ds_args.str,
|
|
"--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)
|
|
{
|
|
MY_INIT(argv[0]);
|
|
#ifdef __NETWARE__
|
|
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
|
|
#endif
|
|
|
|
if (init_dynamic_string(&ds_args, "", 512, 256))
|
|
die("Out of memory");
|
|
|
|
load_defaults("my", load_default_groups, &argc, &argv);
|
|
defaults_argv= argv; /* Must be freed by 'free_defaults' */
|
|
|
|
if (handle_options(&argc, &argv, my_long_options, get_one_option))
|
|
die(NULL);
|
|
if (debug_info_flag)
|
|
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
|
|
if (debug_check_flag)
|
|
my_end_arg= MY_CHECK_ERROR;
|
|
|
|
if (tty_password)
|
|
{
|
|
opt_password= get_tty_password(NullS);
|
|
/* add password to defaults file */
|
|
dynstr_append_os_quoted(&ds_args, "--password=", opt_password, NullS);
|
|
dynstr_append(&ds_args, " ");
|
|
}
|
|
/* add user to defaults file */
|
|
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"));
|
|
|
|
/* Find mysqlcheck */
|
|
find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"));
|
|
|
|
/*
|
|
Read the mysql_upgrade_info file to check if mysql_upgrade
|
|
already has been run for this installation of MySQL
|
|
*/
|
|
if (!opt_force && upgrade_already_done())
|
|
{
|
|
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);
|
|
}
|
|
|
|
/*
|
|
Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
|
|
*/
|
|
if (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
|
|
*/
|
|
die("Upgrade failed" );
|
|
}
|
|
verbose("OK");
|
|
|
|
/* Create a file indicating upgrade has been performed */
|
|
create_mysql_upgrade_info_file();
|
|
|
|
free_used_memory();
|
|
my_end(my_end_arg);
|
|
exit(0);
|
|
}
|
|
|