Bug #15 Bug in interactive
Submitted: 25 Dec 2002 22:51 Modified: 28 Jan 2003 16:49
Reporter: Jani Tolonen Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Command-line Clients Severity:S3 (Non-critical)
Version:4.0 OS:Any (All)
Assigned to: Jani Tolonen CPU Architecture:Any

[25 Dec 2002 22:51] Jani Tolonen
Description:
Interactive 'connect' command was not able to take
a database name as argument, if it contained special
characters, such as a space in it's name.

How to repeat:
mysql> use `stupid db` localhost

Suggested fix:
Here is a patch of mysql.cc from version 13.2 to 13.3

*** /my/tmp/mysql.cc    Wed Dec 25 21:21:56 2002
--- client/mysql.cc     Wed Dec 25 23:52:53 2002
***************
*** 40,46 ****
  #include <signal.h>
  #include <violite.h>

! const char *VER= "13.2";

  /* Don't try to make a nice table if the data is too big */
  #define MAX_COLUMN_LENGTH          1024
--- 40,46 ----
  #include <signal.h>
  #include <violite.h>

! const char *VER= "13.3";

  /* Don't try to make a nice table if the data is too big */
  #define MAX_COLUMN_LENGTH          1024
***************
*** 195,201 ****
  static int init_tee(char *);
  static void end_tee();
  static const char* construct_prompt();
! static char *get_arg(char *line);
  static void init_username();
  static void add_int_to_prompt(int toadd);

--- 195,201 ----
  static int init_tee(char *);
  static void end_tee();
  static const char* construct_prompt();
! static char *get_arg(char *line, my_bool get_next_arg);
  static void init_username();
  static void add_int_to_prompt(int toadd);

***************
*** 2231,2253 ****
  static int
  com_connect(String *buffer, char *line)
  {
!   char *tmp,buff[256];
    bool save_rehash= rehash;
    int error;

    if (buffer)
    {
!     while (my_isspace(system_charset_info,*line))
!       line++;
!     strnmov(buff,line,sizeof(buff)-1);                // Don't destroy history!     if (buff[0] == '\\')                      // Short command
!       buff[1]=' ';
!     tmp=(char *) strtok(buff," \t");          // Skip connect command
!     if (tmp && (tmp=(char *) strtok(NullS," \t;")))
!     {
!       my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
!       current_db=my_strdup(tmp,MYF(MY_WME));
!       if ((tmp=(char *) strtok(NullS," \t;")))
        {
        my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
        current_host=my_strdup(tmp,MYF(MY_WME));
--- 2231,2251 ----
  static int
  com_connect(String *buffer, char *line)
  {
!   char *tmp, buff[256];
    bool save_rehash= rehash;
    int error;

+   bzero(buff, sizeof(buff));
    if (buffer)
    {
!     strmov(buff, line);
!     tmp= get_arg(buff, 0);
!     if (tmp && *tmp)
!     {
!       my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
!       current_db= my_strdup(tmp, MYF(MY_WME));
!       tmp= get_arg(buff, 1);
!       if (tmp)
        {
        my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
        current_host=my_strdup(tmp,MYF(MY_WME));
***************
*** 2333,2340 ****
    char *tmp;
    char buff[256];

    strmov(buff, line);
!   tmp= get_arg(buff);
    if (!tmp || !*tmp)
    {
      put_info("USE must be followed by a database name", INFO_ERROR);
--- 2331,2339 ----
    char *tmp;
    char buff[256];

+   bzero(buff, sizeof(buff));
    strmov(buff, line);
!   tmp= get_arg(buff, 0);
    if (!tmp || !*tmp)
    {
      put_info("USE must be followed by a database name", INFO_ERROR);
***************
*** 2376,2384 ****
  }

  enum quote_type { NO_QUOTE, SQUOTE, DQUOTE, BTICK };

! char *get_arg(char *line)
  {
    char *ptr;
    my_bool quoted= 0, valid_arg= 0;
--- 2375,2394 ----
  }

+
+ /*
+   Gets argument from a command on the command line. If get_next_arg is
+   not defined, skips the command and returns the first argument. The
+   line is modified by adding zero to the end of the argument. If
+   get_next_arg is defined, then the function searches for end of string
+   first, after found, returns the next argument and adds zero to the
+   end. If you ever wish to use this feature, remember to initialize all
+   items in the array to zero first.
+ */
+
  enum quote_type { NO_QUOTE, SQUOTE, DQUOTE, BTICK };

! char *get_arg(char *line, my_bool get_next_arg)
  {
    char *ptr;
    my_bool quoted= 0, valid_arg= 0;
***************
*** 2386,2398 ****
    enum quote_type qtype= NO_QUOTE;

    ptr= line;
!   /* skip leading white spaces */
!   while (my_isspace(system_charset_info, *ptr))
!     ptr++;
!   if (*ptr == '\\') // short command was used
!     ptr+= 2;
!   while (!my_isspace(system_charset_info, *ptr)) // skip command
!     ptr++;
    while (my_isspace(system_charset_info, *ptr))
      ptr++;
    if ((*ptr == '\'' && (qtype= SQUOTE)) ||
--- 2396,2417 ----
    enum quote_type qtype= NO_QUOTE;

    ptr= line;
!   if (get_next_arg)
!   {
!     for (; ptr && *ptr; ptr++);
!     if ((ptr + 1) && *(ptr + 1))
!       ptr++;
!   }
!   else
!   {
!     /* skip leading white spaces */
!     while (my_isspace(system_charset_info, *ptr))
!       ptr++;
!     if (*ptr == '\\') // short command was used
!       ptr+= 2;
!     while (!my_isspace(system_charset_info, *ptr)) // skip command
!       ptr++;
!   }
    while (my_isspace(system_charset_info, *ptr))
      ptr++;
    if ((*ptr == '\'' && (qtype= SQUOTE)) ||
***************
*** 2415,2423 ****
        ptr= line;
        ptr+= count;
      }
!     else if (!quoted && *ptr == ' ')
!       *(ptr + 1) = 0;
!     else if ((*ptr == '\'' && qtype == SQUOTE) ||
             (*ptr == '\"' && qtype == DQUOTE) ||
             (*ptr == '`' && qtype == BTICK))
      {
--- 2434,2441 ----
        ptr= line;
        ptr+= count;
      }
!     else if ((!quoted && *ptr == ' ') ||
!            (*ptr == '\'' && qtype == SQUOTE) ||
             (*ptr == '\"' && qtype == DQUOTE) ||
             (*ptr == '`' && qtype == BTICK))
      {
[28 Jan 2003 16:49] MySQL Developer
Thank you for your bug report. This issue has already been fixed
in the latest released version of that product, which you can download at 
http://www.mysql.com/downloads/