Bug #49839 Small CR issue in mysql client
Submitted: 21 Dec 2009 7:53 Modified: 21 Dec 2009 8:06
Reporter: Roel Van de Paar Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Command-line Clients Severity:S3 (Non-critical)
Version:5.0.88, 5.1.41 OS:Any
Assigned to: CPU Architecture:Any
Tags: Contribution

[21 Dec 2009 7:53] Roel Van de Paar
Description:
mysql> create database bw
    -> ;use bw
Query OK, 1 row affected (0.00 sec)

    -> ;
ERROR 1102 (42000): Incorrect database name 'bw
'
mysql>
mysql> use bw;
Database changed

How to repeat:
create database name   /* Enter */
;use name              /* Enter */
;                      /* Enter */
[23 Dec 2009 0:33] Gavin Towey
In client/mysql.cc in read_and_execute() function there is this:

    /*
      Check if line is a mysql command line
      (We want to allow help, print and clear anywhere at line start
    */
    if ((named_cmds || glob_buffer.is_empty())
	&& !ml_comment && !in_string && (com=find_command(line,0)))
    {
      if ((*com->func)(&glob_buffer,line) > 0)
	break;
      if (glob_buffer.is_empty())		// If buffer was emptied
	in_string=0;
#ifdef HAVE_READLINE
      if (interactive && status.add_to_history && not_in_history(line))
	add_history(line);
#endif
      continue;
    }
    if (add_line(glob_buffer,line,&in_string,&ml_comment, truncated))
      break;

I noticed that when you enter a command by itself on a line, the first find_command() will grab it and cause the first branch to be taken.

Otherwise, if the line contains other leading characters, it misses that test, and in the add_line() function a newline is appended.  It drops back to user input, then add_line() won't find the command until a delimiter character is used.
[23 Dec 2009 20:09] Gavin Towey
more detail:

This block at the end of add_line is what adds the newline, it is entered to handle the "remainder" of a line -- the part of it left over after all delimited commands/statements have been found:

  if (out != line || !buffer.is_empty())
  {
    uint length=(uint) (out-line);

    if (!truncated &&
        (length < 9 || 
         my_strnncoll (charset_info, 
                       (uchar *)line, 9, (const uchar *) "delimiter", 9)))
    {
      /* 
        Don't add a new line in case there's a DELIMITER command to be 
        added to the glob buffer (e.g. on processing a line like 
        "<command>;DELIMITER <non-eof>") : similar to how a new line is 
        not added in the case when the DELIMITER is the first command 
        entered with an empty glob buffer. 
      */
      *out++='\n';
      length++;
    }

There has already been an exception added for the DELIMITER command. So I can see two possible solutions:

1. add a similar no-newline exception for all commands (or even just use?)
2. call find_command on this "remainder"

Anyone have any thoughts on which is better?
[24 Dec 2009 1:19] Gavin Towey
proposed fix

Attachment: mysql_client_bug_49839.patch (application/octet-stream, text), 177 bytes.

[24 Dec 2009 1:21] Gavin Towey
I created a patch around the second option.  Tested ok on my end, created against 5.1.34.

This is the first patch I've submitted, please let me know if this is not the correct process.