Commit 53abe494 authored by Sergey Petrunia's avatar Sergey Petrunia
Browse files

Merge

parents 869c86b3 bae55255
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ check_cpu () {
  fi

  cc_ver=`$cc --version | sed 1q`
  cc_verno=`echo $cc_ver | sed -e 's/^.*gcc/gcc/g; s/[^0-9. ]//g;	 s/^ *//g; s/ .*//g'`
  cc_verno=`echo $cc_ver | sed -e 's/^.*(GCC)//g; s/[^0-9. ]//g;	 s/^ *//g; s/ .*//g'`
  set -- `echo $cc_verno | tr '.' ' '`
  cc_major=$1
  cc_minor=$2
+3 −2
Original line number Diff line number Diff line
@@ -88,11 +88,12 @@ mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \

mysqltest_SOURCES=		mysqltest.c
mysqltest_CFLAGS=		-DTHREAD -UUNDEF_THREADS_HACK
mysqltest_LDADD =		$(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
mysqltest_LDADD =		$(CXXLDFLAGS) \
				@CLIENT_EXTRA_LDFLAGS@ \
				$(LIBMYSQLCLIENT_LA) \
				$(top_builddir)/mysys/libmysys.a \
				$(top_builddir)/regex/libregex.a
				$(top_builddir)/regex/libregex.a \
				$(CLIENT_THREAD_LIBS)

mysql_upgrade_SOURCES=          mysql_upgrade.c \
                                $(top_srcdir)/mysys/my_getpagesize.c
+56 −83
Original line number Diff line number Diff line
@@ -269,6 +269,10 @@ get_one_option(int optid, const struct my_option *opt,
}


/**
  Run a command using the shell, storing its output in the supplied dynamic
  string.
*/
static int run_command(char* cmd,
                       DYNAMIC_STRING *ds_res)
{
@@ -341,37 +345,15 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...)
}


/*
  Try to get the full path to this exceutable

  Return 0 if path found

/**
  Look for the filename of given tool, with the presumption that it is in the
  same directory as mysql_upgrade and that the same executable-searching 
  mechanism will be used when we run our sub-shells with popen() later.
*/

static my_bool get_full_path_to_executable(char* path)
static void find_tool(char *tool_executable_name, const char *tool_name, 
                      const char *self_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);
}


/*
  Look for the tool in the same directory as mysql_upgrade.
*/

static void find_tool(char *tool_path, const char *tool_name)
{
  size_t path_len;
  char path[FN_REFLEN];
  char *last_fn_libchar;
  DYNAMIC_STRING ds_tmp;
  DBUG_ENTER("find_tool");
  DBUG_PRINT("enter", ("progname: %s", my_progname));
@@ -379,36 +361,24 @@ static void find_tool(char *tool_path, const char *tool_name)
  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))
  last_fn_libchar= strrchr(self_name, FN_LIBCHAR);

  if (last_fn_libchar == NULL)
  {
    /*
      Easy way to get full executable path failed, try
      other methods
      mysql_upgrade was found by the shell searching the path.  A sibling
      next to us should be found the same way.
    */
    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);
    strncpy(tool_executable_name, tool_name, FN_REFLEN);
  }
  else
  {
      /* 3. Just go for it and hope tool is in path */
      path[0]= 0;
    }
  }
    int len;

  DBUG_PRINT("info", ("path: '%s'", path));

  /* Chop off binary name (i.e mysql-upgrade) from path */
  dirname_part(path, path, &path_len);
    /*
      mysql_upgrade was run absolutely or relatively.  We can find a sibling
      by replacing our name after the LIBCHAR with the new tool name.
    */

    /*
      When running in a not yet installed build and using libtool,
@@ -418,38 +388,32 @@ static void find_tool(char *tool_path, const char *tool_name)
      mysqlcheck). Thus if path ends in .libs/, step up one directory
      and execute the tools from there
    */
  path[max(path_len-1, 0)]= 0;   /* Chop off last / */
  if (strncmp(path + dirname_length(path), ".libs", 5) == 0)
    if (((last_fn_libchar - 6) >= self_name) &&
        (strncmp(last_fn_libchar - 5, ".libs", 5) == 0) &&
        (*(last_fn_libchar - 6) == FN_LIBCHAR))
    {
    DBUG_PRINT("info", ("Chopping off .libs from '%s'", path));

    /* Chop off .libs */
    dirname_part(path, path, &path_len);
      DBUG_PRINT("info", ("Chopping off \".libs\" from end of path"));
      last_fn_libchar -= 6;
    }

    len= last_fn_libchar - self_name;

  DBUG_PRINT("info", ("path: '%s'", 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);
    my_snprintf(tool_executable_name, FN_REFLEN, "%.*s%c%s",
                len, self_name, FN_LIBCHAR, tool_name);
  }

  /* Make sure the tool exists */
  if (my_access(tool_path, F_OK) != 0)
    die("Can't find '%s'", tool_path);
  verbose("Looking for '%s' as: %s", tool_name, tool_executable_name);

  /*
    Make sure it can be executed
  */
  if (run_tool(tool_path,
  if (run_tool(tool_executable_name,
               &ds_tmp, /* Get output from command, discard*/
               "--help",
               "2>&1",
               IF_WIN("> NUL", "> /dev/null"),
               NULL))
    die("Can't execute '%s'", tool_path);
    die("Can't execute '%s'", tool_executable_name);

  dynstr_free(&ds_tmp);

@@ -759,11 +723,20 @@ static const char *load_default_groups[]=

int main(int argc, char **argv)
{
  char self_name[FN_REFLEN];

  MY_INIT(argv[0]);
#ifdef __NETWARE__
  setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
#endif

#if __WIN__
  if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0)
#endif
  {
    strncpy(self_name, argv[0], FN_REFLEN);
  }

  if (init_dynamic_string(&ds_args, "", 512, 256))
    die("Out of memory");

@@ -789,10 +762,10 @@ int main(int argc, char **argv)
  dynstr_append(&ds_args, " ");

  /* Find mysql */
  find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"));
  find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name);

  /* Find mysqlcheck */
  find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"));
  find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);

  /*
    Read the mysql_upgrade_info file to check if mysql_upgrade
+127 −54
Original line number Diff line number Diff line
@@ -171,6 +171,8 @@ static ulonglong timer_now(void);

static ulonglong progress_start= 0;

static ulong connection_retry_sleep= 100000; /* Microseconds */

/* Precompiled re's */
static my_regex_t ps_re;     /* the query can be run using PS protocol */
static my_regex_t sp_re;     /* the query can be run as a SP */
@@ -495,6 +497,9 @@ void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input);

static int match_expected_error(struct st_command *command,
                                unsigned int err_errno,
                                const char *err_sqlstate);
void handle_error(struct st_command*,
                  unsigned int err_errno, const char *err_error,
                  const char *err_sqlstate, DYNAMIC_STRING *ds);
@@ -848,30 +853,26 @@ void check_command_args(struct st_command *command,
  DBUG_VOID_RETURN;
}


void handle_command_error(struct st_command *command, uint error)
{
  DBUG_ENTER("handle_command_error");
  DBUG_PRINT("enter", ("error: %d", error));
  if (error != 0)
  {
    uint i;
    int i;

    if (command->abort_on_error)
      die("command \"%.*s\" failed with error %d",
          command->first_word_len, command->query, error);
    for (i= 0; i < command->expected_errors.count; i++)
    {
      DBUG_PRINT("info", ("expected error: %d",
                          command->expected_errors.err[i].code.errnum));
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
          (command->expected_errors.err[i].code.errnum == error))

    i= match_expected_error(command, error, NULL);

    if (i >= 0)
    {
      DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
                          command->first_word_len, command->query, error));
      DBUG_VOID_RETURN;
    }
    }
    die("command \"%.*s\" failed with wrong error: %d",
        command->first_word_len, command->query, error);
  }
@@ -2465,8 +2466,8 @@ void do_exec(struct st_command *command)
  error= pclose(res_file);
  if (error > 0)
  {
    uint status= WEXITSTATUS(error), i;
    my_bool ok= 0;
    uint status= WEXITSTATUS(error);
    int i;

    if (command->abort_on_error)
    {
@@ -2478,19 +2479,13 @@ void do_exec(struct st_command *command)

    DBUG_PRINT("info",
               ("error: %d, status: %d", error, status));
    for (i= 0; i < command->expected_errors.count; i++)
    {
      DBUG_PRINT("info", ("expected error: %d",
                          command->expected_errors.err[i].code.errnum));
      if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
          (command->expected_errors.err[i].code.errnum == status))
      {
        ok= 1;

    i= match_expected_error(command, status, NULL);

    if (i >= 0)
      DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d",
                          command->first_argument, status));
      }
    }
    if (!ok)
    else
    {
      dynstr_free(&ds_cmd);
      die("command \"%s\" failed with wrong error: %d",
@@ -4290,7 +4285,6 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host,
                  int port, const char *sock)
{
  int failed_attempts= 0;
  static ulong connection_retry_sleep= 100000; /* Microseconds */

  DBUG_ENTER("safe_connect");
  while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
@@ -4357,6 +4351,7 @@ int connect_n_handle_errors(struct st_command *command,
                            const char* db, int port, const char* sock)
{
  DYNAMIC_STRING *ds;
  int failed_attempts= 0;

  ds= &ds_res;

@@ -4385,9 +4380,41 @@ int connect_n_handle_errors(struct st_command *command,
    dynstr_append_mem(ds, delimiter, delimiter_length);
    dynstr_append_mem(ds, "\n", 1);
  }
  if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
  while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
                          CLIENT_MULTI_STATEMENTS))
  {
    /*
      If we have used up all our connections check whether this
      is expected (by --error). If so, handle the error right away.
      Otherwise, give it some extra time to rule out race-conditions.
      If extra-time doesn't help, we have an unexpected error and
      must abort -- just proceeding to handle_error() when second
      and third chances are used up will handle that for us.

      There are various user-limits of which only max_user_connections
      and max_connections_per_hour apply at connect time. For the
      the second to create a race in our logic, we'd need a limits
      test that runs without a FLUSH for longer than an hour, so we'll
      stay clear of trying to work out which exact user-limit was
      exceeded.
    */

    if (((mysql_errno(con) == ER_TOO_MANY_USER_CONNECTIONS) ||
         (mysql_errno(con) == ER_USER_LIMIT_REACHED)) &&
        (failed_attempts++ < opt_max_connect_retries))
    {
      int i;

      i= match_expected_error(command, mysql_errno(con), mysql_sqlstate(con));

      if (i >= 0)
        goto do_handle_error;                 /* expected error, handle */

      my_sleep(connection_retry_sleep);       /* unexpected error, wait */
      continue;                               /* and give it 1 more chance */
    }

do_handle_error:
    var_set_errno(mysql_errno(con));
    handle_error(command, mysql_errno(con), mysql_error(con),
		 mysql_sqlstate(con), ds);
@@ -6149,6 +6176,56 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
}


/*
  Check whether given error is in list of expected errors

  SYNOPSIS
    match_expected_error()

  PARAMETERS
    command        the current command (and its expect-list)
    err_errno      error number of the error that actually occurred
    err_sqlstate   SQL-state that was thrown, or NULL for impossible
                   (file-ops, diff, etc.)

  RETURNS
    -1 for not in list, index in list of expected errors otherwise

  NOTE
    If caller needs to know whether the list was empty, they should
    check command->expected_errors.count.
*/

static int match_expected_error(struct st_command *command,
                                unsigned int err_errno,
                                const char *err_sqlstate)
{
  uint i;

  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
  {
    if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
        (command->expected_errors.err[i].code.errnum == err_errno))
      return i;

    if (command->expected_errors.err[i].type == ERR_SQLSTATE)
    {
      /*
        NULL is quite likely, but not in conjunction with a SQL-state expect!
      */
      if (unlikely(err_sqlstate == NULL))
        die("expecting a SQL-state (%s) from query '%s' which cannot produce one...",
            command->expected_errors.err[i].code.sqlstate, command->query);

      if (strncmp(command->expected_errors.err[i].code.sqlstate,
                  err_sqlstate, SQLSTATE_LENGTH) == 0)
        return i;
    }
  }
  return -1;
}


/*
  Handle errors which occurred during execution

@@ -6169,7 +6246,7 @@ void handle_error(struct st_command *command,
                  unsigned int err_errno, const char *err_error,
                  const char *err_sqlstate, DYNAMIC_STRING *ds)
{
  uint i;
  int i;

  DBUG_ENTER("handle_error");

@@ -6195,13 +6272,10 @@ void handle_error(struct st_command *command,

  DBUG_PRINT("info", ("expected_errors.count: %d",
                      command->expected_errors.count));
  for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
  {
    if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
         (command->expected_errors.err[i].code.errnum == err_errno)) ||
        ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
         (strncmp(command->expected_errors.err[i].code.sqlstate,
                  err_sqlstate, SQLSTATE_LENGTH) == 0)))

  i= match_expected_error(command, err_errno, err_sqlstate);

  if (i >= 0)
  {
    if (!disable_result_log)
    {
@@ -6223,7 +6297,6 @@ void handle_error(struct st_command *command,
    /* OK */
    DBUG_VOID_RETURN;
  }
  }

  DBUG_PRINT("info",("i: %d  expected_errors: %d", i,
                     command->expected_errors.count));
@@ -6237,7 +6310,7 @@ void handle_error(struct st_command *command,
    dynstr_append_mem(ds, "\n", 1);
  }

  if (i)
  if (command->expected_errors.count > 0)
  {
    if (command->expected_errors.err[0].type == ERR_ERRNO)
      die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
+4 −4
Original line number Diff line number Diff line
@@ -343,8 +343,8 @@ case $default_charset in
      default_charset_default_collation="ucs2_general_ci"
      define(UCSC1, ucs2_general_ci ucs2_bin)
      define(UCSC2, ucs2_czech_ci ucs2_danish_ci)
      define(UCSC3, ucs2_esperanto_ci ucs2_estonian_ci ucs2_icelandic_ci)
      define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci)
      define(UCSC3, ucs2_esperanto_ci ucs2_estonian_ci ucs2_hungarian_ci)
      define(UCSC4, ucs2_icelandic_ci ucs2_latvian_ci ucs2_lithuanian_ci)
      define(UCSC5, ucs2_persian_ci ucs2_polish_ci ucs2_romanian_ci)
      define(UCSC6, ucs2_slovak_ci ucs2_slovenian_ci)
      define(UCSC7, ucs2_spanish2_ci ucs2_spanish_ci)
@@ -367,8 +367,8 @@ case $default_charset in
      else
        define(UTFC1, utf8_general_ci utf8_bin)
        define(UTFC2, utf8_czech_ci utf8_danish_ci)
        define(UTFC3, utf8_esperanto_ci utf8_estonian_ci utf8_icelandic_ci)
        define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci)
        define(UTFC3, utf8_esperanto_ci utf8_estonian_ci utf8_hungarian_ci)
        define(UTFC4, utf8_icelandic_ci utf8_latvian_ci utf8_lithuanian_ci)
        define(UTFC5, utf8_persian_ci utf8_polish_ci utf8_romanian_ci)
        define(UTFC6, utf8_slovak_ci utf8_slovenian_ci)
        define(UTFC7, utf8_spanish2_ci utf8_spanish_ci)
Loading