Bug #78114 mysql client fails on delimiter sequence or quote symbols inside hint comments
Submitted: 17 Aug 2015 19:51 Modified: 2 Oct 2015 16:42
Reporter: Gleb Shchepa Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Command-line Clients Severity:S3 (Non-critical)
Version:5.7 OS:Any
Assigned to: CPU Architecture:Any

[17 Aug 2015 19:51] Gleb Shchepa
Description:
1. Hint commentaries are designed to behave like regular /* ... */ commentaries:

  SELECT /*+ " */ 1; -- a valid SQL query

However, the mysql client program waits for the closing doublequote character:

mysql> SELECT /*+ ' */ 1;
    '> 
    '> 
    '> ';
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set, 1 warning (0,00 sec)

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

Backquote "`" and singlequote "'" characters are affected the same way.

2. There is a similar issue with statement delimiters:

mysql> SELECT /*+ ; */ 1; -- also a valid SQL query
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/*+' at line 1
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*/ 1' at line 1

How to repeat:
In the mysql client program, with or without the --comments parameter:

SELECT /*+ ' */ 1;
SELECT /*+ ` */ 1;
SELECT /*+ " */ 1;
SELECT /*+ ; */ 1;

Suggested fix:
The patch:

================================================================================

diff --git a/client/mysql.cc b/client/mysql.cc
index 266725b..e41af00 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -2498,7 +2498,7 @@ static bool add_line(String &buffer, char *line, size_t line_length,
   char buff[80], *pos, *out;
   COMMANDS *com;
   bool need_space= 0;
-  bool ss_comment= 0;
+  enum { SSC_NONE= 0, SSC_CONDITIONAL, SSC_HINT } ss_comment= SSC_NONE;
   DBUG_ENTER("add_line");
 
   if (!line[0] && buffer.is_empty())
@@ -2595,7 +2595,8 @@ static bool add_line(String &buffer, char *line, size_t line_length,
        continue;
       }
     }
-    else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter))
+    else if (!*ml_comment && !*in_string && ss_comment != SSC_HINT &&
+             is_prefix(pos, delimiter))
     {
       // Found a statement. Continue parsing after the delimiter
       pos+= delimiter_length;
@@ -2717,12 +2718,12 @@ static bool add_line(String &buffer, char *line, size_t line_length,
     {                                          // Add found char to buffer
       if (!*in_string && inchar == '/' && pos[1] == '*' &&
           (pos[2] == '!' || pos[2] == '+'))
-        ss_comment= 1;
+        ss_comment= (pos[2] == '!') ? SSC_CONDITIONAL : SSC_HINT;
       else if (!*in_string && ss_comment && inchar == '*' && *(pos + 1) == '/')
-        ss_comment= 0;
+        ss_comment= SSC_NONE;
       if (inchar == *in_string)
        *in_string= 0;
-      else if (!*ml_comment && !*in_string &&
+      else if (!*ml_comment && !*in_string && ss_comment != SSC_HINT &&
               (inchar == '\'' || inchar == '"' || inchar == '`'))
        *in_string= (char) inchar;
       if (!*ml_comment || preserve_comments)

================================================================================

After the fix:

mysql> SELECT /* ' */ 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

mysql> SELECT /*+ ' */ 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set, 1 warning (0,00 sec)

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------------+
| Level   | Code | Message                                             |
+---------+------+-----------------------------------------------------+
| Warning | 1064 | Optimizer hint syntax error near '' */ 1' at line 1 |
+---------+------+-----------------------------------------------------+
1 row in set (0,00 sec)

mysql> SELECT /*+ " */ 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set, 1 warning (0,00 sec)

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------------+
| Level   | Code | Message                                             |
+---------+------+-----------------------------------------------------+
| Warning | 1064 | Optimizer hint syntax error near '" */ 1' at line 1 |
+---------+------+-----------------------------------------------------+
1 row in set (0,00 sec)

mysql> SELECT /*+ ` */ 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set, 1 warning (0,00 sec)

mysql> SHOW WARNINGS;
+---------+------+----------------------------------------------------+
| Level   | Code | Message                                            |
+---------+------+----------------------------------------------------+
| Warning | 1064 | Optimizer hint syntax error near ' */ 1' at line 1 |
+---------+------+----------------------------------------------------+
1 row in set (0,00 sec)

mysql> SELECT /*+ ; */ 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set, 1 warning (0,00 sec)

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------------+
| Level   | Code | Message                                             |
+---------+------+-----------------------------------------------------+
| Warning | 1064 | Optimizer hint syntax error near '; */ 1' at line 1 |
+---------+------+-----------------------------------------------------+
1 row in set (0,00 sec)
[2 Oct 2015 16:42] Paul DuBois
Noted in 5.7.9, 5.8.0 changelogs.

The mysql client parser incorrectly interpreted optimizer hint
comments that contained ;, ", ', or ` characters.