Commit e4403f2e authored by kaa@polly.(none)'s avatar kaa@polly.(none)

Merge polly.(none):/home/kaa/src/opt/bug26215/my51-bug26215

into  polly.(none):/home/kaa/src/opt/mysql-5.1-opt
parents 606e269d 794274ab
...@@ -144,6 +144,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, ...@@ -144,6 +144,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
show_warnings= 0, executing_query= 0, interrupted_query= 0; show_warnings= 0, executing_query= 0, interrupted_query= 0;
static my_bool debug_info_flag, debug_check_flag; static my_bool debug_info_flag, debug_check_flag;
static my_bool column_types_flag; static my_bool column_types_flag;
static my_bool preserve_comments= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length; 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 uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static uint my_end_arg; static uint my_end_arg;
...@@ -778,6 +779,10 @@ static struct my_option my_long_options[] = ...@@ -778,6 +779,10 @@ static struct my_option my_long_options[] =
{"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
(uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG, (uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"comments", 'c', "Preserve comments. Send comments to the server."
" Comments are discarded by default, enable with --enable-comments",
(uchar**) &preserve_comments, (uchar**) &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} { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
}; };
...@@ -1154,10 +1159,6 @@ static int read_and_execute(bool interactive) ...@@ -1154,10 +1159,6 @@ static int read_and_execute(bool interactive)
status.exit_status=0; status.exit_status=0;
break; 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 Check if line is a mysql command line
...@@ -1283,15 +1284,21 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1283,15 +1284,21 @@ static bool add_line(String &buffer,char *line,char *in_string,
for (pos=out=line ; (inchar= (uchar) *pos) ; pos++) for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
{ {
if (my_isspace(charset_info,inchar) && out == line && if (!preserve_comments)
buffer.is_empty()) {
continue; // Skip spaces at the beggining of a statement
if (my_isspace(charset_info,inchar) && (out == line) &&
buffer.is_empty())
continue;
}
#ifdef USE_MB #ifdef USE_MB
// Accept multi-byte characters as-is
int length; int length;
if (use_mb(charset_info) && if (use_mb(charset_info) &&
(length= my_ismbchar(charset_info, pos, end_of_line))) (length= my_ismbchar(charset_info, pos, end_of_line)))
{ {
if (!*ml_comment) if (!*ml_comment || preserve_comments)
{ {
while (length--) while (length--)
*out++ = *pos++; *out++ = *pos++;
...@@ -1317,8 +1324,13 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1317,8 +1324,13 @@ static bool add_line(String &buffer,char *line,char *in_string,
} }
if ((com=find_command(NullS,(char) inchar))) if ((com=find_command(NullS,(char) inchar)))
{ {
const String tmp(line,(uint) (out-line), charset_info); // Flush previously accepted characters
buffer.append(tmp); if (out != line)
{
buffer.append(line, (uint) (out-line));
out= line;
}
if ((*com->func)(&buffer,pos-1) > 0) if ((*com->func)(&buffer,pos-1) > 0)
DBUG_RETURN(1); // Quit DBUG_RETURN(1); // Quit
if (com->takes_params) if (com->takes_params)
...@@ -1346,7 +1358,6 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1346,7 +1358,6 @@ static bool add_line(String &buffer,char *line,char *in_string,
pos+= delimiter_length - 1; // Point at last delim char pos+= delimiter_length - 1; // Point at last delim char
} }
} }
out=line;
} }
else else
{ {
...@@ -1359,46 +1370,106 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1359,46 +1370,106 @@ static bool add_line(String &buffer,char *line,char *in_string,
} }
} }
else if (!*ml_comment && !*in_string && else if (!*ml_comment && !*in_string &&
(*pos == *delimiter && is_prefix(pos + 1, delimiter + 1) || (out - line) >= 9 &&
buffer.length() == 0 && (out - line) >= 9 && !my_strnncoll(charset_info, (uchar*) pos, 9,
!my_strcasecmp(charset_info, line, "delimiter"))) (const uchar*) "delimiter", 9) &&
{ my_isspace(charset_info, pos[9]))
uint old_delimiter_length= delimiter_length; {
// Flush previously accepted characters
if (out != line) 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= find_command(buffer.c_ptr(), 0)))
{ {
if (com->func == com_delimiter)
{ if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
/* DBUG_RETURN(1); // Quit
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
} }
else else
{ {
if (com_go(&buffer, 0) > 0) // < 0 is not fatal if (com_go(&buffer, 0) > 0) // < 0 is not fatal
DBUG_RETURN(1); DBUG_RETURN(1);
} }
buffer.length(0); buffer.length(0);
out= line;
pos+= old_delimiter_length - 1;
} }
else if (!*ml_comment && (!*in_string && (inchar == '#' || else if (!*ml_comment && (!*in_string && (inchar == '#' ||
inchar == '-' && pos[1] == '-' && inchar == '-' && pos[1] == '-' &&
my_isspace(charset_info,pos[2])))) 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) == '*' && else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
*(pos+2) != '!') *(pos+2) != '!')
{ {
pos++; if (preserve_comments)
{
*out++= *pos++; // copy '/'
*out++= *pos; // copy '*'
}
else
pos++;
*ml_comment= 1; *ml_comment= 1;
if (out != line) if (out != line)
{ {
...@@ -1408,8 +1479,21 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1408,8 +1479,21 @@ static bool add_line(String &buffer,char *line,char *in_string,
} }
else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/') else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/')
{ {
pos++; if (preserve_comments)
{
*out++= *pos++; // copy '*'
*out++= *pos; // copy '/'
}
else
pos++;
*ml_comment= 0; *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; need_space= 1;
} }
else else
...@@ -1424,14 +1508,12 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1424,14 +1508,12 @@ static bool add_line(String &buffer,char *line,char *in_string,
else if (!*ml_comment && !*in_string && else if (!*ml_comment && !*in_string &&
(inchar == '\'' || inchar == '"' || inchar == '`')) (inchar == '\'' || inchar == '"' || inchar == '`'))
*in_string= (char) inchar; *in_string= (char) inchar;
if (!*ml_comment) if (!*ml_comment || preserve_comments)
{ {
if (need_space && !my_isspace(charset_info, (char)inchar)) if (need_space && !my_isspace(charset_info, (char)inchar))
{
*out++= ' '; *out++= ' ';
need_space= 0; need_space= 0;
} *out++= (char) inchar;
*out++= (char) inchar;
} }
} }
} }
...@@ -1441,7 +1523,7 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1441,7 +1523,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
uint length=(uint) (out-line); uint length=(uint) (out-line);
if (buffer.length() + length >= buffer.alloced_length()) if (buffer.length() + length >= buffer.alloced_length())
buffer.realloc(buffer.length()+length+IO_SIZE); 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(1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
......
drop table if exists t1;
drop function if exists foofct;
drop procedure if exists empty;
drop procedure if exists foosp;
drop procedure if exists nicesp;
drop trigger if exists t1_empty;
drop trigger if exists t1_bi;
"Pass 1 : --disable-comments"
1
1
2
2
foofct("call 1")
call 1
Function sql_mode Create Function character_set_client collation_connection Database Collation
foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nreturn\n\n\n\nx latin1 latin1_swedish_ci latin1_swedish_ci
foofct("call 2")
call 2
Function sql_mode Create Function character_set_client collation_connection Database Collation
foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nbegin\n \n \n \n\n \n\n \n return x;\nend latin1 latin1_swedish_ci latin1_swedish_ci
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
empty CREATE DEFINER=`root`@`localhost` PROCEDURE `empty`()\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci
id data
foo 42
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
foosp CREATE DEFINER=`root`@`localhost` PROCEDURE `foosp`()\ninsert into test.t1\n\n\n\n\n \n\n \n values ("foo", 42) latin1 latin1_swedish_ci latin1_swedish_ci
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
nicesp CREATE DEFINER=`root`@`localhost` PROCEDURE `nicesp`(a int)\nbegin\n \n declare b int;\n declare c float;\n\n \n \n\n \nend latin1 latin1_swedish_ci latin1_swedish_ci
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
t1_empty CREATE DEFINER=`root`@`localhost` trigger t1_empty after delete on t1\nfor each row\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
t1_bi CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1\nfor each row\nbegin\n\n\n\n \n declare b int;\n declare c float;\n\n \n \n\n \n set NEW.data := 12;\nend latin1 latin1_swedish_ci latin1_swedish_ci
id data
trig 12
"Pass 2 : --enable-comments"
1
1
2
2
foofct("call 1")
call 1
Function sql_mode Create Function character_set_client collation_connection Database Collation
foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nreturn\n-- comment 1a\n# comment 1b\n/* comment 1c */\nx # after body, on same line latin1 latin1_swedish_ci latin1_swedish_ci
foofct("call 2")
call 2
Function sql_mode Create Function character_set_client collation_connection Database Collation
foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nbegin\n -- comment 1a\n # comment 1b\n /*\n comment 1c\n */\n\n -- empty line below\n\n -- empty line above\n return x;\nend latin1 latin1_swedish_ci latin1_swedish_ci
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
empty CREATE DEFINER=`root`@`localhost` PROCEDURE `empty`()\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci
id data
foo 42
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
foosp CREATE DEFINER=`root`@`localhost` PROCEDURE `foosp`()\ninsert into test.t1\n## These comments are part of the procedure body, and should be kept.\n# Comment 2a\n-- Comment 2b\n/* Comment 2c */\n -- empty line below\n\n -- empty line above\n values ("foo", 42) # comment 3, still part of the body latin1 latin1_swedish_ci latin1_swedish_ci
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
nicesp CREATE DEFINER=`root`@`localhost` PROCEDURE `nicesp`(a int)\nbegin\n -- declare some variables here\n declare b int;\n declare c float;\n\n -- do more stuff here\n -- commented nicely and so on\n\n -- famous last words ...\nend latin1 latin1_swedish_ci latin1_swedish_ci
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
t1_empty CREATE DEFINER=`root`@`localhost` trigger t1_empty after delete on t1\nfor each row\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation
t1_bi CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1\nfor each row\nbegin\n# comment 1a\n-- comment 1b\n/*\n comment 1c\n*/\n -- declare some variables here\n declare b int;\n declare c float;\n\n -- do more stuff here\n -- commented nicely and so on\n\n -- famous last words ...\n set NEW.data := 12;\nend latin1 latin1_swedish_ci latin1_swedish_ci
id data
trig 12
End of 5.0 tests
##============================================================================
## Notes
##============================================================================
# Test case for Bug#11230
# The point of this test is to make sure that '#', '-- ' and '/* ... */'
# comments, as well as empty lines, are sent from the client to the server.
# This is to ensure better error reporting, and to keep comments in the code
# for stored procedures / functions / triggers (Bug#11230).
# As a result, be careful when editing comments in this script, they do
# matter.
#
# Also, note that this is a script for **mysql**, not mysqltest.
# This is critical, as the mysqltest client interprets comments differently.
##============================================================================
## Setup
##============================================================================
## See mysql_comments.test for initial cleanup
# Test tables
#
# t1 is reused throughout the file, and dropped at the end.
#
drop table if exists t1;
create table t1 (
id char(16) not null default '',
data int not null
);
##============================================================================
## Comments outside statements
##============================================================================
# Ignored 1a
-- Ignored 1b
/*
Ignored 1c
*/
select 1;
##============================================================================
## Comments inside statements
##============================================================================
select # comment 1a
# comment 2a
-- comment 2b
/*
comment 2c
*/
2
; # not strictly inside, but on same line
# ignored
##============================================================================
## Comments inside functions
##============================================================================
drop function if exists foofct ;
create function foofct (x char(20))
returns char(20)
/* not inside the body yet */
return
-- comment 1a
# comment 1b
/* comment 1c */
x; # after body, on same line
select foofct("call 1");
show create function foofct;
drop function foofct;
delimiter |
create function foofct(x char(20))
returns char(20)
begin
-- comment 1a
# comment 1b
/*
comment 1c
*/
-- empty line below
-- empty line above
return x;
end|
delimiter ;
select foofct("call 2");
show create function foofct;
drop function foofct;
##============================================================================
## Comments inside stored procedures
##============================================================================
# Empty statement
drop procedure if exists empty;
create procedure empty()
begin
end;
call empty();
show create procedure empty;
drop procedure empty;
drop procedure if exists foosp;
## These comments are before the create, and will be lost
# Comment 1a
-- Comment 1b
/*
Comment 1c
*/
create procedure foosp()
/* Comment not quiet in the body yet */
insert into test.t1
## These comments are part of the procedure body, and should be kept.
# Comment 2a
-- Comment 2b
/* Comment 2c */
-- empty line below
-- empty line above
values ("foo", 42); # comment 3, still part of the body
## After the ';', therefore not part of the body
# comment 4a
-- Comment 4b
/*
Comment 4c
*/
call foosp();
select * from t1;
delete from t1;
show create procedure foosp;
drop procedure foosp;
drop procedure if exists nicesp;
delimiter |
create procedure nicesp(a int)
begin
-- declare some variables here
declare b int;
declare c float;
-- do more stuff here
-- commented nicely and so on
-- famous last words ...
end|
delimiter ;
show create procedure nicesp;
drop procedure nicesp;
##============================================================================
## Comments inside triggers
##============================================================================
drop trigger if exists t1_empty;
create trigger t1_empty after delete on t1
for each row
begin
end;
show create trigger t1_empty;
drop trigger if exists t1_bi;
delimiter |
create trigger t1_bi before insert on t1
for each row
begin
# comment 1a
-- comment 1b
/*
comment 1c
*/
-- declare some variables here
declare b int;
declare c float;
-- do more stuff here
-- commented nicely and so on
-- famous last words ...
set NEW.data := 12;
end|
delimiter ;
show create trigger t1_bi;
# also make sure the trigger still works
insert into t1(id) value ("trig");
select * from t1;
##============================================================================
## Cleanup
##============================================================================
drop table t1;
# This test should work in embedded server after we fix mysqltest
-- source include/not_embedded.inc
###################### mysql_comments.test #############################
# #
# Testing of comments handling by the command line client (mysql) #
# #
# Creation: #
# 2007-10-29 akopytov Implemented this test as a part of fixes for #
# bug #26215 and bug #11230 #
# #
########################################################################
#
# Bug #11230: Keeping comments when storing stored procedures
#
# See the content of mysql_comments.sql
# Set the test database to a known state before running the tests.
--disable_warnings
drop table if exists t1;
drop function if exists foofct;
drop procedure if exists empty;
drop procedure if exists foosp;
drop procedure if exists nicesp;
drop trigger if exists t1_empty;
drop trigger if exists t1_bi;
--enable_warnings
# Test without comments
--echo "Pass 1 : --disable-comments"
--exec $MYSQL --disable-comments test 2>&1 < "./t/mysql_comments.sql"
# Test with comments
--echo "Pass 2 : --enable-comments"
--exec $MYSQL --enable-comments test 2>&1 < "./t/mysql_comments.sql"
--echo End of 5.0 tests
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment