mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Fix for:
bug #26215: mysql command line client should not strip comments from SQL statements and bug #11230: Keeping comments when storing stored procedures With the introduction of multiline comments support in the command line client (mysql) in MySQL 4.1, it became impossible to preserve client-side comments within single SQL statements or stored routines. This feature was useful for monitoring tools and maintenance. The patch adds a new option to the command line client ('--enable-comments', '-c') which allows to preserve SQL comments and send them to the server for single SQL statements, and to keep comments in the code for stored procedures / functions / triggers. The patch is a modification of the contributed patch from bug #11230 with the following changes: - code style changes to conform to the coding guidelines - changed is_prefix() to my_strnncoll() to detect the DELIMITER command, since the first one is case-sensitive and not charset-aware - renamed t/comments-51.* to t/mysql_comments.* - removed tests for comments in triggers since 5.0 does not have SHOW CREATE TRIGGER (those tests will be added back in 5.1). The test cases are only for bug #11230. No automated test case for bug #26215 is possible due to the test suite deficiencies (though the cases from the bug report were tested manually).
This commit is contained in:
168
client/mysql.cc
168
client/mysql.cc
@ -140,6 +140,7 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
|
||||
default_pager_set= 0, opt_sigint_ignore= 0,
|
||||
show_warnings= 0;
|
||||
static volatile int executing_query= 0, interrupted_query= 0;
|
||||
static my_bool preserve_comments= 0;
|
||||
static ulong opt_max_allowed_packet, opt_net_buffer_length;
|
||||
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
|
||||
static my_string opt_mysql_unix_port=0;
|
||||
@ -754,6 +755,10 @@ static struct my_option my_long_options[] =
|
||||
{"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
|
||||
(gptr*) &show_warnings, (gptr*) &show_warnings, 0, GET_BOOL, NO_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
{"comments", 'c', "Preserve comments. Send comments to the server."
|
||||
" Comments are discarded by default, enable with --enable-comments",
|
||||
(gptr*) &preserve_comments, (gptr*) &preserve_comments,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -1131,10 +1136,6 @@ static int read_and_execute(bool interactive)
|
||||
status.exit_status=0;
|
||||
break;
|
||||
}
|
||||
if (!in_string && (line[0] == '#' ||
|
||||
(line[0] == '-' && line[1] == '-') ||
|
||||
line[0] == 0))
|
||||
continue; // Skip comment lines
|
||||
|
||||
/*
|
||||
Check if line is a mysql command line
|
||||
@ -1260,15 +1261,21 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
|
||||
for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
|
||||
{
|
||||
if (my_isspace(charset_info,inchar) && out == line &&
|
||||
buffer.is_empty())
|
||||
continue;
|
||||
if (!preserve_comments)
|
||||
{
|
||||
// Skip spaces at the beggining of a statement
|
||||
if (my_isspace(charset_info,inchar) && (out == line) &&
|
||||
buffer.is_empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef USE_MB
|
||||
// Accept multi-byte characters as-is
|
||||
int length;
|
||||
if (use_mb(charset_info) &&
|
||||
(length= my_ismbchar(charset_info, pos, end_of_line)))
|
||||
{
|
||||
if (!*ml_comment)
|
||||
if (!*ml_comment || preserve_comments)
|
||||
{
|
||||
while (length--)
|
||||
*out++ = *pos++;
|
||||
@ -1294,8 +1301,13 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
}
|
||||
if ((com=find_command(NullS,(char) inchar)))
|
||||
{
|
||||
const String tmp(line,(uint) (out-line), charset_info);
|
||||
buffer.append(tmp);
|
||||
// Flush previously accepted characters
|
||||
if (out != line)
|
||||
{
|
||||
buffer.append(line, (uint) (out-line));
|
||||
out= line;
|
||||
}
|
||||
|
||||
if ((*com->func)(&buffer,pos-1) > 0)
|
||||
DBUG_RETURN(1); // Quit
|
||||
if (com->takes_params)
|
||||
@ -1323,7 +1335,6 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
pos+= delimiter_length - 1; // Point at last delim char
|
||||
}
|
||||
}
|
||||
out=line;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1336,46 +1347,106 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
}
|
||||
}
|
||||
else if (!*ml_comment && !*in_string &&
|
||||
(*pos == *delimiter && is_prefix(pos + 1, delimiter + 1) ||
|
||||
buffer.length() == 0 && (out - line) >= 9 &&
|
||||
!my_strcasecmp(charset_info, line, "delimiter")))
|
||||
{
|
||||
uint old_delimiter_length= delimiter_length;
|
||||
(out - line) >= 9 &&
|
||||
!my_strnncoll(charset_info, (uchar*) pos, 9,
|
||||
(const uchar*) "delimiter", 9) &&
|
||||
my_isspace(charset_info, pos[9]))
|
||||
{
|
||||
// Flush previously accepted characters
|
||||
if (out != line)
|
||||
buffer.append(line, (uint) (out - line)); // Add this line
|
||||
{
|
||||
buffer.append(line, (uint32) (out - line));
|
||||
out= line;
|
||||
}
|
||||
|
||||
// Flush possible comments in the buffer
|
||||
if (!buffer.is_empty())
|
||||
{
|
||||
if (com_go(&buffer, 0) > 0) // < 0 is not fatal
|
||||
DBUG_RETURN(1);
|
||||
buffer.length(0);
|
||||
}
|
||||
|
||||
/*
|
||||
Delimiter wants the get rest of the given line as argument to
|
||||
allow one to change ';' to ';;' and back
|
||||
*/
|
||||
buffer.append(pos);
|
||||
if (com_delimiter(&buffer, pos) > 0)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
buffer.length(0);
|
||||
break;
|
||||
}
|
||||
else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter))
|
||||
{
|
||||
// Found a statement. Continue parsing after the delimiter
|
||||
pos+= delimiter_length;
|
||||
|
||||
if (preserve_comments)
|
||||
{
|
||||
while (my_isspace(charset_info, *pos))
|
||||
*out++= *pos++;
|
||||
}
|
||||
// Flush previously accepted characters
|
||||
if (out != line)
|
||||
{
|
||||
buffer.append(line, (uint32) (out-line));
|
||||
out= line;
|
||||
}
|
||||
|
||||
if (preserve_comments && ((*pos == '#') ||
|
||||
((*pos == '-') &&
|
||||
(pos[1] == '-') &&
|
||||
my_isspace(charset_info, pos[2]))))
|
||||
{
|
||||
// Add trailing single line comments to this statement
|
||||
buffer.append(pos);
|
||||
pos+= strlen(pos);
|
||||
}
|
||||
|
||||
pos--;
|
||||
|
||||
if ((com= find_command(buffer.c_ptr(), 0)))
|
||||
{
|
||||
if (com->func == com_delimiter)
|
||||
{
|
||||
/*
|
||||
Delimiter wants the get rest of the given line as argument to
|
||||
allow one to change ';' to ';;' and back
|
||||
*/
|
||||
char *end= strend(pos);
|
||||
buffer.append(pos, (uint) (end - pos));
|
||||
/* Ensure pos will point at \0 after the pos+= below */
|
||||
pos= end - old_delimiter_length + 1;
|
||||
}
|
||||
if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
|
||||
DBUG_RETURN(1); // Quit
|
||||
|
||||
if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
|
||||
DBUG_RETURN(1); // Quit
|
||||
}
|
||||
else
|
||||
{
|
||||
if (com_go(&buffer, 0) > 0) // < 0 is not fatal
|
||||
DBUG_RETURN(1);
|
||||
if (com_go(&buffer, 0) > 0) // < 0 is not fatal
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
buffer.length(0);
|
||||
out= line;
|
||||
pos+= old_delimiter_length - 1;
|
||||
}
|
||||
else if (!*ml_comment && (!*in_string && (inchar == '#' ||
|
||||
inchar == '-' && pos[1] == '-' &&
|
||||
my_isspace(charset_info,pos[2]))))
|
||||
break; // comment to end of line
|
||||
{
|
||||
// Flush previously accepted characters
|
||||
if (out != line)
|
||||
{
|
||||
buffer.append(line, (uint32) (out - line));
|
||||
out= line;
|
||||
}
|
||||
|
||||
// comment to end of line
|
||||
if (preserve_comments)
|
||||
buffer.append(pos);
|
||||
|
||||
break;
|
||||
}
|
||||
else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
|
||||
*(pos+2) != '!')
|
||||
{
|
||||
pos++;
|
||||
if (preserve_comments)
|
||||
{
|
||||
*out++= *pos++; // copy '/'
|
||||
*out++= *pos; // copy '*'
|
||||
}
|
||||
else
|
||||
pos++;
|
||||
*ml_comment= 1;
|
||||
if (out != line)
|
||||
{
|
||||
@ -1385,8 +1456,21 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
}
|
||||
else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/')
|
||||
{
|
||||
pos++;
|
||||
if (preserve_comments)
|
||||
{
|
||||
*out++= *pos++; // copy '*'
|
||||
*out++= *pos; // copy '/'
|
||||
}
|
||||
else
|
||||
pos++;
|
||||
*ml_comment= 0;
|
||||
if (out != line)
|
||||
{
|
||||
buffer.append(line, (uint32) (out - line));
|
||||
out= line;
|
||||
}
|
||||
// Consumed a 2 chars or more, and will add 1 at most,
|
||||
// so using the 'line' buffer to edit data in place is ok.
|
||||
need_space= 1;
|
||||
}
|
||||
else
|
||||
@ -1401,14 +1485,12 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
else if (!*ml_comment && !*in_string &&
|
||||
(inchar == '\'' || inchar == '"' || inchar == '`'))
|
||||
*in_string= (char) inchar;
|
||||
if (!*ml_comment)
|
||||
if (!*ml_comment || preserve_comments)
|
||||
{
|
||||
if (need_space && !my_isspace(charset_info, (char)inchar))
|
||||
{
|
||||
*out++= ' ';
|
||||
need_space= 0;
|
||||
}
|
||||
*out++= (char) inchar;
|
||||
need_space= 0;
|
||||
*out++= (char) inchar;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1418,7 +1500,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
|
||||
uint length=(uint) (out-line);
|
||||
if (buffer.length() + length >= buffer.alloced_length())
|
||||
buffer.realloc(buffer.length()+length+IO_SIZE);
|
||||
if (!(*ml_comment) && buffer.append(line,length))
|
||||
if ((!*ml_comment || preserve_comments) && buffer.append(line, length))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
Reference in New Issue
Block a user