Bug #19799 delimiter command not working correctly when sourcing a sql file
Submitted: 14 May 2006 10:04 Modified: 11 Dec 2006 9:48
Reporter: Eric MaLossi
Status: Closed
Category:Client Severity:S2 (Serious)
Version:5.0.21-community-nt OS:Microsoft Windows (win32 - XP SP2)
Assigned to: Iggy Galarza Target Version:

[14 May 2006 10:04] Eric MaLossi
Description:
The mysql client is handling the command 'delimiter' differently depending on whether it
is entered directly, or sourced from a sql file.  When sourced, the chosen delimiter
functions as expected while the script is running, but when the script ends the delimiter
is no longer the same.  It is unknown what it becomes after the script ends.

How to repeat:
Enter the following into a mysql client session. This works as expected:

mysql> delimiter //
mysql> show databases //
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+
3 rows in set (0.00 sec)

mysql>

Now create a sql file containing this single statement:
#FILE
delimiter //
#EOF

Source the file and attempt to use the new delimiter.  It is unclear what if anything it
has been set to:

mysql> \. c:/foo.sql
mysql> show databases //
    -> \c
mysql> show databases;
    -> \c
mysql> show databases //;
    -> \c

Interestingly if you put these two statements together in the file it works, so while the
script is being run, the delimiter is set as expected.  Only after the script ends does
the errant behavior begin:
#FILE
delimiter //
show databases //
#EOF

Source the file:
mysql> \. c:/foo.sql
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+
3 rows in set (0.00 sec)

mysql> show databases //
    -> \c
mysql>
[1 Jun 2006 10:04] Mark Johnson
I have experienced this problem as well.
When I save my "source" file in DOS format (i.e. carriage-return plus linefeed for end of
line), the DELIMITER fails after executing the script.
When I save my "source" file in unix format (just linefeed for end of line), the DELIMITER
works correctly after executing the script.

I am using version:
mysql-standard-5.0.21-linux-i686-glibc23
[4 Jul 2006 7:51] Mark Johnson
There is a workaround.  Simply manually reset the delimiter after running the script file.
 Then, the delimiter no longer includes the extra carriage-return, and mysql will work as
expected.
[17 Oct 2006 15:33] Dave Shawley
I patched a local version of 5.0.22 to fix this problem. It looks like intern_read_line in
client/readline.cpp was only honoring line feeds as the end of line character. The
following diff fixes this my normalizing CRLF to a space followed by a linefeed. I'm not
sure if this is production safe so use it at your own risk. The DELIMITER issue was just
driving me insane...

--- readline-orig.cpp	2006-05-25 10:56:44.000000000 -0400
+++ readline.cpp	2006-10-17 08:47:31.664113600 -0400
@@ -195,18 +195,49 @@
   buffer->start_of_line=buffer->end_of_line;
   for (;;)
   {
+    int expectNL = 0, foundEnd = 0;
     pos=buffer->end_of_line;
-    while (*pos != '\n' && *pos)
-      pos++;
+    while (!foundEnd)
+    {
+      switch (*pos)
+      {
+      case '\r':
+        expectNL = 1;
+        pos++;
+        break;
+      case '\n':
+        if (expectNL)
+        {
+          /* Got a CR as last character, set it to <space> */
+          *(pos-1) = ' ';
+        }
+        /*FALLTHRU*/
+      case '\0':
+        foundEnd = 1;
+        break;
+      default:
+        if (expectNL)
+        {
+          /* CR without NL, back up and we are done */
+          --pos;
+          foundEnd = 1;
+        }
+        else
+        {
+          pos++;
+        }
+        break;
+      }
+    }
     if (pos == buffer->end)
     {
       if ((uint) (pos - buffer->start_of_line) < buffer->max_size)
       {
-	if (!(length=fill_buffer(buffer)) || length == (uint) -1)
-	  DBUG_RETURN(0);
-	continue;
+        if (!(length=fill_buffer(buffer)) || length == (uint) -1)
+          DBUG_RETURN(0);
+        continue;
       }
-      pos--;					/* break line here */
+      pos--; /* break line here */
     }
     buffer->end_of_line=pos+1;
     *out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line);
[22 Nov 2006 3:05] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/15670

ChangeSet@1.2328, 2006-11-21 21:10:02-05:00, iggy@rolltop.ignatz42.dyndns.org +4 -0
  Bug#19799 delimiter command not working correctly when sourcing a sql file
  - Client side readline functions unconditionally search for Unix '\n' line
  endings. In this case, the delimiter statement was set to '//\r' instead 
  of the intended '//'. When removing the '\n' check for and remove 
  preceeding '\r' character as well.
[22 Nov 2006 7:23] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/15678

ChangeSet@1.2330, 2006-11-22 01:27:06-05:00, iggy@rolltop.ignatz42.dyndns.org +2 -0
  Bug#19799 delimiter command not working correctly when sourcing a sql file
  - Use more appropriate test case.
[11 Dec 2006 9:48] Jon Stephens
Thank you for your bug report. This issue has been committed to our source repository of
that product and will be incorporated into the next release.

If necessary, you can access the source repository and build the latest available version,
including the bug fix. More information about accessing the source trees is available at

    http://dev.mysql.com/doc/en/installing-source.html

Documented bugfix for 5.0.32 and 5.1.15.