Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
bf1005a1
Commit
bf1005a1
authored
Jan 11, 2007
by
kostja@bodhi.local
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into bodhi.local:/opt/local/work/mysql-5.0-runtime
parents
49913f2a
6a99943e
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1338 additions
and
186 deletions
+1338
-186
heap/hp_block.c
heap/hp_block.c
+1
-1
heap/hp_write.c
heap/hp_write.c
+9
-3
mysql-test/r/sp-code.result
mysql-test/r/sp-code.result
+415
-0
mysql-test/r/sp_stress_case.result
mysql-test/r/sp_stress_case.result
+120
-0
mysql-test/r/view.result
mysql-test/r/view.result
+9
-0
mysql-test/t/log.sh
mysql-test/t/log.sh
+1
-1
mysql-test/t/sp-code.test
mysql-test/t/sp-code.test
+235
-0
mysql-test/t/sp_stress_case.test
mysql-test/t/sp_stress_case.test
+89
-0
mysql-test/t/view.test
mysql-test/t/view.test
+15
-0
server-tools/instance-manager/listener.cc
server-tools/instance-manager/listener.cc
+5
-5
sql/item_func.cc
sql/item_func.cc
+3
-2
sql/sp_head.cc
sql/sp_head.cc
+55
-41
sql/sp_head.h
sql/sp_head.h
+28
-11
sql/sql_class.cc
sql/sql_class.cc
+14
-0
sql/sql_class.h
sql/sql_class.h
+10
-2
sql/sql_lex.cc
sql/sql_lex.cc
+0
-1
sql/sql_lex.h
sql/sql_lex.h
+0
-1
sql/sql_prepare.cc
sql/sql_prepare.cc
+1
-2
sql/sql_string.cc
sql/sql_string.cc
+2
-2
sql/sql_yacc.yy
sql/sql_yacc.yy
+298
-114
tests/mysql_client_test.c
tests/mysql_client_test.c
+28
-0
No files found.
heap/hp_block.c
View file @
bf1005a1
...
...
@@ -75,7 +75,7 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
and my_default_record_cache_size we get about 1/128 unused memory.
*/
*
alloc_length
=
sizeof
(
HP_PTRS
)
*
i
+
block
->
records_in_block
*
block
->
recbuffer
;
if
(
!
(
root
=
(
HP_PTRS
*
)
my_malloc
(
*
alloc_length
,
MYF
(
0
))))
if
(
!
(
root
=
(
HP_PTRS
*
)
my_malloc
(
*
alloc_length
,
MYF
(
MY_WME
))))
return
1
;
if
(
i
==
0
)
...
...
heap/hp_write.c
View file @
bf1005a1
...
...
@@ -67,11 +67,17 @@ int heap_write(HP_INFO *info, const byte *record)
DBUG_RETURN
(
0
);
err:
DBUG_PRINT
(
"info"
,(
"Duplicate key: %d"
,
(
int
)
(
keydef
-
share
->
keydef
)));
if
(
my_errno
==
HA_ERR_FOUND_DUPP_KEY
)
DBUG_PRINT
(
"info"
,(
"Duplicate key: %d"
,
keydef
-
share
->
keydef
));
info
->
errkey
=
keydef
-
share
->
keydef
;
if
(
keydef
->
algorithm
==
HA_KEY_ALG_BTREE
)
/*
We don't need to delete non-inserted key from rb-tree. Also, if
we got ENOMEM, the key wasn't inserted, so don't try to delete it
either. Otherwise for HASH index on HA_ERR_FOUND_DUPP_KEY the key
was inserted and we have to delete it.
*/
if
(
keydef
->
algorithm
==
HA_KEY_ALG_BTREE
||
my_errno
==
ENOMEM
)
{
/* we don't need to delete non-inserted key from rb-tree */
keydef
--
;
}
while
(
keydef
>=
share
->
keydef
)
...
...
mysql-test/r/sp-code.result
View file @
bf1005a1
...
...
@@ -199,6 +199,421 @@ Pos Instruction
44 jump 14
45 stmt 9 "drop temporary table sudoku_work, sud..."
drop procedure sudoku_solve;
DROP PROCEDURE IF EXISTS proc_19194_simple;
DROP PROCEDURE IF EXISTS proc_19194_searched;
DROP PROCEDURE IF EXISTS proc_19194_nested_1;
DROP PROCEDURE IF EXISTS proc_19194_nested_2;
DROP PROCEDURE IF EXISTS proc_19194_nested_3;
DROP PROCEDURE IF EXISTS proc_19194_nested_4;
CREATE PROCEDURE proc_19194_simple(i int)
BEGIN
DECLARE str CHAR(10);
CASE i
WHEN 1 THEN SET str="1";
WHEN 2 THEN SET str="2";
WHEN 3 THEN SET str="3";
ELSE SET str="unknown";
END CASE;
SELECT str;
END|
CREATE PROCEDURE proc_19194_searched(i int)
BEGIN
DECLARE str CHAR(10);
CASE
WHEN i=1 THEN SET str="1";
WHEN i=2 THEN SET str="2";
WHEN i=3 THEN SET str="3";
ELSE SET str="unknown";
END CASE;
SELECT str;
END|
CREATE PROCEDURE proc_19194_nested_1(i int, j int)
BEGIN
DECLARE str_i CHAR(10);
DECLARE str_j CHAR(10);
CASE i
WHEN 10 THEN SET str_i="10";
WHEN 20 THEN
BEGIN
set str_i="20";
CASE
WHEN j=1 THEN SET str_j="1";
WHEN j=2 THEN SET str_j="2";
WHEN j=3 THEN SET str_j="3";
ELSE SET str_j="unknown";
END CASE;
select "i was 20";
END;
WHEN 30 THEN SET str_i="30";
WHEN 40 THEN SET str_i="40";
ELSE SET str_i="unknown";
END CASE;
SELECT str_i, str_j;
END|
CREATE PROCEDURE proc_19194_nested_2(i int, j int)
BEGIN
DECLARE str_i CHAR(10);
DECLARE str_j CHAR(10);
CASE
WHEN i=10 THEN SET str_i="10";
WHEN i=20 THEN
BEGIN
set str_i="20";
CASE j
WHEN 1 THEN SET str_j="1";
WHEN 2 THEN SET str_j="2";
WHEN 3 THEN SET str_j="3";
ELSE SET str_j="unknown";
END CASE;
select "i was 20";
END;
WHEN i=30 THEN SET str_i="30";
WHEN i=40 THEN SET str_i="40";
ELSE SET str_i="unknown";
END CASE;
SELECT str_i, str_j;
END|
CREATE PROCEDURE proc_19194_nested_3(i int, j int)
BEGIN
DECLARE str_i CHAR(10);
DECLARE str_j CHAR(10);
CASE i
WHEN 10 THEN SET str_i="10";
WHEN 20 THEN
BEGIN
set str_i="20";
CASE j
WHEN 1 THEN SET str_j="1";
WHEN 2 THEN SET str_j="2";
WHEN 3 THEN SET str_j="3";
ELSE SET str_j="unknown";
END CASE;
select "i was 20";
END;
WHEN 30 THEN SET str_i="30";
WHEN 40 THEN SET str_i="40";
ELSE SET str_i="unknown";
END CASE;
SELECT str_i, str_j;
END|
CREATE PROCEDURE proc_19194_nested_4(i int, j int)
BEGIN
DECLARE str_i CHAR(10);
DECLARE str_j CHAR(10);
CASE
WHEN i=10 THEN SET str_i="10";
WHEN i=20 THEN
BEGIN
set str_i="20";
CASE
WHEN j=1 THEN SET str_j="1";
WHEN j=2 THEN SET str_j="2";
WHEN j=3 THEN SET str_j="3";
ELSE SET str_j="unknown";
END CASE;
select "i was 20";
END;
WHEN i=30 THEN SET str_i="30";
WHEN i=40 THEN SET str_i="40";
ELSE SET str_i="unknown";
END CASE;
SELECT str_i, str_j;
END|
SHOW PROCEDURE CODE proc_19194_simple;
Pos Instruction
0 set str@1 NULL
1 set_case_expr (12) 0 i@0
2 jump_if_not 5(12) (case_expr@0 = 1)
3 set str@1 _latin1'1'
4 jump 12
5 jump_if_not 8(12) (case_expr@0 = 2)
6 set str@1 _latin1'2'
7 jump 12
8 jump_if_not 11(12) (case_expr@0 = 3)
9 set str@1 _latin1'3'
10 jump 12
11 set str@1 _latin1'unknown'
12 stmt 0 "SELECT str"
SHOW PROCEDURE CODE proc_19194_searched;
Pos Instruction
0 set str@1 NULL
1 jump_if_not 4(11) (i@0 = 1)
2 set str@1 _latin1'1'
3 jump 11
4 jump_if_not 7(11) (i@0 = 2)
5 set str@1 _latin1'2'
6 jump 11
7 jump_if_not 10(11) (i@0 = 3)
8 set str@1 _latin1'3'
9 jump 11
10 set str@1 _latin1'unknown'
11 stmt 0 "SELECT str"
SHOW PROCEDURE CODE proc_19194_nested_1;
Pos Instruction
0 set str_i@2 NULL
1 set str_j@3 NULL
2 set_case_expr (27) 0 i@0
3 jump_if_not 6(27) (case_expr@0 = 10)
4 set str_i@2 _latin1'10'
5 jump 27
6 jump_if_not 20(27) (case_expr@0 = 20)
7 set str_i@2 _latin1'20'
8 jump_if_not 11(18) (j@1 = 1)
9 set str_j@3 _latin1'1'
10 jump 18
11 jump_if_not 14(18) (j@1 = 2)
12 set str_j@3 _latin1'2'
13 jump 18
14 jump_if_not 17(18) (j@1 = 3)
15 set str_j@3 _latin1'3'
16 jump 18
17 set str_j@3 _latin1'unknown'
18 stmt 0 "select "i was 20""
19 jump 27
20 jump_if_not 23(27) (case_expr@0 = 30)
21 set str_i@2 _latin1'30'
22 jump 27
23 jump_if_not 26(27) (case_expr@0 = 40)
24 set str_i@2 _latin1'40'
25 jump 27
26 set str_i@2 _latin1'unknown'
27 stmt 0 "SELECT str_i, str_j"
SHOW PROCEDURE CODE proc_19194_nested_2;
Pos Instruction
0 set str_i@2 NULL
1 set str_j@3 NULL
2 jump_if_not 5(27) (i@0 = 10)
3 set str_i@2 _latin1'10'
4 jump 27
5 jump_if_not 20(27) (i@0 = 20)
6 set str_i@2 _latin1'20'
7 set_case_expr (18) 0 j@1
8 jump_if_not 11(18) (case_expr@0 = 1)
9 set str_j@3 _latin1'1'
10 jump 18
11 jump_if_not 14(18) (case_expr@0 = 2)
12 set str_j@3 _latin1'2'
13 jump 18
14 jump_if_not 17(18) (case_expr@0 = 3)
15 set str_j@3 _latin1'3'
16 jump 18
17 set str_j@3 _latin1'unknown'
18 stmt 0 "select "i was 20""
19 jump 27
20 jump_if_not 23(27) (i@0 = 30)
21 set str_i@2 _latin1'30'
22 jump 27
23 jump_if_not 26(27) (i@0 = 40)
24 set str_i@2 _latin1'40'
25 jump 27
26 set str_i@2 _latin1'unknown'
27 stmt 0 "SELECT str_i, str_j"
SHOW PROCEDURE CODE proc_19194_nested_3;
Pos Instruction
0 set str_i@2 NULL
1 set str_j@3 NULL
2 set_case_expr (28) 0 i@0
3 jump_if_not 6(28) (case_expr@0 = 10)
4 set str_i@2 _latin1'10'
5 jump 28
6 jump_if_not 21(28) (case_expr@0 = 20)
7 set str_i@2 _latin1'20'
8 set_case_expr (19) 1 j@1
9 jump_if_not 12(19) (case_expr@1 = 1)
10 set str_j@3 _latin1'1'
11 jump 19
12 jump_if_not 15(19) (case_expr@1 = 2)
13 set str_j@3 _latin1'2'
14 jump 19
15 jump_if_not 18(19) (case_expr@1 = 3)
16 set str_j@3 _latin1'3'
17 jump 19
18 set str_j@3 _latin1'unknown'
19 stmt 0 "select "i was 20""
20 jump 28
21 jump_if_not 24(28) (case_expr@0 = 30)
22 set str_i@2 _latin1'30'
23 jump 28
24 jump_if_not 27(28) (case_expr@0 = 40)
25 set str_i@2 _latin1'40'
26 jump 28
27 set str_i@2 _latin1'unknown'
28 stmt 0 "SELECT str_i, str_j"
SHOW PROCEDURE CODE proc_19194_nested_4;
Pos Instruction
0 set str_i@2 NULL
1 set str_j@3 NULL
2 jump_if_not 5(26) (i@0 = 10)
3 set str_i@2 _latin1'10'
4 jump 26
5 jump_if_not 19(26) (i@0 = 20)
6 set str_i@2 _latin1'20'
7 jump_if_not 10(17) (j@1 = 1)
8 set str_j@3 _latin1'1'
9 jump 17
10 jump_if_not 13(17) (j@1 = 2)
11 set str_j@3 _latin1'2'
12 jump 17
13 jump_if_not 16(17) (j@1 = 3)
14 set str_j@3 _latin1'3'
15 jump 17
16 set str_j@3 _latin1'unknown'
17 stmt 0 "select "i was 20""
18 jump 26
19 jump_if_not 22(26) (i@0 = 30)
20 set str_i@2 _latin1'30'
21 jump 26
22 jump_if_not 25(26) (i@0 = 40)
23 set str_i@2 _latin1'40'
24 jump 26
25 set str_i@2 _latin1'unknown'
26 stmt 0 "SELECT str_i, str_j"
CALL proc_19194_nested_1(10, 1);
str_i str_j
10 NULL
CALL proc_19194_nested_1(25, 1);
str_i str_j
unknown NULL
CALL proc_19194_nested_1(20, 1);
i was 20
i was 20
str_i str_j
20 1
CALL proc_19194_nested_1(20, 2);
i was 20
i was 20
str_i str_j
20 2
CALL proc_19194_nested_1(20, 3);
i was 20
i was 20
str_i str_j
20 3
CALL proc_19194_nested_1(20, 4);
i was 20
i was 20
str_i str_j
20 unknown
CALL proc_19194_nested_1(30, 1);
str_i str_j
30 NULL
CALL proc_19194_nested_1(40, 1);
str_i str_j
40 NULL
CALL proc_19194_nested_1(0, 0);
str_i str_j
unknown NULL
CALL proc_19194_nested_2(10, 1);
str_i str_j
10 NULL
CALL proc_19194_nested_2(25, 1);
str_i str_j
unknown NULL
CALL proc_19194_nested_2(20, 1);
i was 20
i was 20
str_i str_j
20 1
CALL proc_19194_nested_2(20, 2);
i was 20
i was 20
str_i str_j
20 2
CALL proc_19194_nested_2(20, 3);
i was 20
i was 20
str_i str_j
20 3
CALL proc_19194_nested_2(20, 4);
i was 20
i was 20
str_i str_j
20 unknown
CALL proc_19194_nested_2(30, 1);
str_i str_j
30 NULL
CALL proc_19194_nested_2(40, 1);
str_i str_j
40 NULL
CALL proc_19194_nested_2(0, 0);
str_i str_j
unknown NULL
CALL proc_19194_nested_3(10, 1);
str_i str_j
10 NULL
CALL proc_19194_nested_3(25, 1);
str_i str_j
unknown NULL
CALL proc_19194_nested_3(20, 1);
i was 20
i was 20
str_i str_j
20 1
CALL proc_19194_nested_3(20, 2);
i was 20
i was 20
str_i str_j
20 2
CALL proc_19194_nested_3(20, 3);
i was 20
i was 20
str_i str_j
20 3
CALL proc_19194_nested_3(20, 4);
i was 20
i was 20
str_i str_j
20 unknown
CALL proc_19194_nested_3(30, 1);
str_i str_j
30 NULL
CALL proc_19194_nested_3(40, 1);
str_i str_j
40 NULL
CALL proc_19194_nested_3(0, 0);
str_i str_j
unknown NULL
CALL proc_19194_nested_4(10, 1);
str_i str_j
10 NULL
CALL proc_19194_nested_4(25, 1);
str_i str_j
unknown NULL
CALL proc_19194_nested_4(20, 1);
i was 20
i was 20
str_i str_j
20 1
CALL proc_19194_nested_4(20, 2);
i was 20
i was 20
str_i str_j
20 2
CALL proc_19194_nested_4(20, 3);
i was 20
i was 20
str_i str_j
20 3
CALL proc_19194_nested_4(20, 4);
i was 20
i was 20
str_i str_j
20 unknown
CALL proc_19194_nested_4(30, 1);
str_i str_j
30 NULL
CALL proc_19194_nested_4(40, 1);
str_i str_j
40 NULL
CALL proc_19194_nested_4(0, 0);
str_i str_j
unknown NULL
DROP PROCEDURE proc_19194_simple;
DROP PROCEDURE proc_19194_searched;
DROP PROCEDURE proc_19194_nested_1;
DROP PROCEDURE proc_19194_nested_2;
DROP PROCEDURE proc_19194_nested_3;
DROP PROCEDURE proc_19194_nested_4;
DROP PROCEDURE IF EXISTS p1;
CREATE PROCEDURE p1() CREATE INDEX idx ON t1 (c1);
SHOW PROCEDURE CODE p1;
...
...
mysql-test/r/sp_stress_case.result
0 → 100644
View file @
bf1005a1
DROP PROCEDURE IF EXISTS proc_19194_codegen;
DROP PROCEDURE IF EXISTS bug_19194_simple;
DROP PROCEDURE IF EXISTS bug_19194_searched;
CREATE PROCEDURE proc_19194_codegen(
IN proc_name VARCHAR(50),
IN count INTEGER,
IN simple INTEGER,
OUT body MEDIUMTEXT)
BEGIN
DECLARE code MEDIUMTEXT;
DECLARE i INT DEFAULT 1;
SET code = concat("CREATE PROCEDURE ", proc_name, "(i INT)\n");
SET code = concat(code, "BEGIN\n");
SET code = concat(code, " DECLARE str CHAR(10);\n");
IF (simple)
THEN
SET code = concat(code, " CASE i\n");
ELSE
SET code = concat(code, " CASE\n");
END IF;
WHILE (i <= count)
DO
IF (simple)
THEN
SET code = concat(code, " WHEN ", i, " THEN SET str=\"", i, "\";\n");
ELSE
SET code = concat(code, " WHEN i=", i, " THEN SET str=\"", i, "\";\n");
END IF;
SET i = i + 1;
END WHILE;
SET code = concat(code, " ELSE SET str=\"unknown\";\n");
SET code = concat(code, " END CASE;\n");
SET code = concat(code, " SELECT str;\n");
SET code = concat(code, "END\n");
SET body = code;
END|
set @body="";
call proc_19194_codegen("test_simple", 10, 1, @body);
select @body;
@body
CREATE PROCEDURE test_simple(i INT)
BEGIN
DECLARE str CHAR(10);
CASE i
WHEN 1 THEN SET str="1";
WHEN 2 THEN SET str="2";
WHEN 3 THEN SET str="3";
WHEN 4 THEN SET str="4";
WHEN 5 THEN SET str="5";
WHEN 6 THEN SET str="6";
WHEN 7 THEN SET str="7";
WHEN 8 THEN SET str="8";
WHEN 9 THEN SET str="9";
WHEN 10 THEN SET str="10";
ELSE SET str="unknown";
END CASE;
SELECT str;
END
call proc_19194_codegen("test_searched", 10, 0, @body);
select @body;
@body
CREATE PROCEDURE test_searched(i INT)
BEGIN
DECLARE str CHAR(10);
CASE
WHEN i=1 THEN SET str="1";
WHEN i=2 THEN SET str="2";
WHEN i=3 THEN SET str="3";
WHEN i=4 THEN SET str="4";
WHEN i=5 THEN SET str="5";
WHEN i=6 THEN SET str="6";
WHEN i=7 THEN SET str="7";
WHEN i=8 THEN SET str="8";
WHEN i=9 THEN SET str="9";
WHEN i=10 THEN SET str="10";
ELSE SET str="unknown";
END CASE;
SELECT str;
END
CALL bug_19194_simple(1);
str
1
CALL bug_19194_simple(2);
str
2
CALL bug_19194_simple(1000);
str
1000
CALL bug_19194_simple(4998);
str
4998
CALL bug_19194_simple(4999);
str
4999
CALL bug_19194_simple(9999);
str
unknown
CALL bug_19194_searched(1);
str
1
CALL bug_19194_searched(2);
str
2
CALL bug_19194_searched(1000);
str
1000
CALL bug_19194_searched(4998);
str
4998
CALL bug_19194_searched(4999);
str
4999
CALL bug_19194_searched(9999);
str
unknown
DROP PROCEDURE proc_19194_codegen;
DROP PROCEDURE bug_19194_simple;
DROP PROCEDURE bug_19194_searched;
mysql-test/r/view.result
View file @
bf1005a1
...
...
@@ -3014,4 +3014,13 @@ i j
6 3
DROP VIEW v1, v2;
DROP TABLE t1;
DROP VIEW IF EXISTS v1;
CREATE VIEW v1 AS SELECT 'The\ZEnd';
SELECT * FROM v1;
TheEnd
TheEnd
SHOW CREATE VIEW v1;
View Create View
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _latin1'The\ZEnd' AS `TheEnd`
DROP VIEW v1;
End of 5.0 tests.
mysql-test/t/log.sh
View file @
bf1005a1
#!/bin/
ba
sh
#!/bin/sh
###########################################################################
...
...
mysql-test/t/sp-code.test
View file @
bf1005a1
...
...
@@ -191,6 +191,241 @@ show procedure code sudoku_solve;
drop
procedure
sudoku_solve
;
#
# Bug#19194 (Right recursion in parser for CASE causes excessive stack
# usage, limitation)
# This bug also exposed a flaw in the generated code with nested case
# statements
#
--
disable_warnings
DROP
PROCEDURE
IF
EXISTS
proc_19194_simple
;
DROP
PROCEDURE
IF
EXISTS
proc_19194_searched
;
DROP
PROCEDURE
IF
EXISTS
proc_19194_nested_1
;
DROP
PROCEDURE
IF
EXISTS
proc_19194_nested_2
;
DROP
PROCEDURE
IF
EXISTS
proc_19194_nested_3
;
DROP
PROCEDURE
IF
EXISTS
proc_19194_nested_4
;
--
enable_warnings
delimiter
|
;
CREATE
PROCEDURE
proc_19194_simple
(
i
int
)
BEGIN
DECLARE
str
CHAR
(
10
);
CASE
i
WHEN
1
THEN
SET
str
=
"1"
;
WHEN
2
THEN
SET
str
=
"2"
;
WHEN
3
THEN
SET
str
=
"3"
;
ELSE
SET
str
=
"unknown"
;
END
CASE
;
SELECT
str
;
END
|
CREATE
PROCEDURE
proc_19194_searched
(
i
int
)
BEGIN
DECLARE
str
CHAR
(
10
);
CASE
WHEN
i
=
1
THEN
SET
str
=
"1"
;
WHEN
i
=
2
THEN
SET
str
=
"2"
;
WHEN
i
=
3
THEN
SET
str
=
"3"
;
ELSE
SET
str
=
"unknown"
;
END
CASE
;
SELECT
str
;
END
|
# Outer SIMPLE case, inner SEARCHED case
CREATE
PROCEDURE
proc_19194_nested_1
(
i
int
,
j
int
)
BEGIN
DECLARE
str_i
CHAR
(
10
);
DECLARE
str_j
CHAR
(
10
);
CASE
i
WHEN
10
THEN
SET
str_i
=
"10"
;
WHEN
20
THEN
BEGIN
set
str_i
=
"20"
;
CASE
WHEN
j
=
1
THEN
SET
str_j
=
"1"
;
WHEN
j
=
2
THEN
SET
str_j
=
"2"
;
WHEN
j
=
3
THEN
SET
str_j
=
"3"
;
ELSE
SET
str_j
=
"unknown"
;
END
CASE
;
select
"i was 20"
;
END
;
WHEN
30
THEN
SET
str_i
=
"30"
;
WHEN
40
THEN
SET
str_i
=
"40"
;
ELSE
SET
str_i
=
"unknown"
;
END
CASE
;
SELECT
str_i
,
str_j
;
END
|
# Outer SEARCHED case, inner SIMPLE case
CREATE
PROCEDURE
proc_19194_nested_2
(
i
int
,
j
int
)
BEGIN
DECLARE
str_i
CHAR
(
10
);
DECLARE
str_j
CHAR
(
10
);
CASE
WHEN
i
=
10
THEN
SET
str_i
=
"10"
;
WHEN
i
=
20
THEN
BEGIN
set
str_i
=
"20"
;
CASE
j
WHEN
1
THEN
SET
str_j
=
"1"
;
WHEN
2
THEN
SET
str_j
=
"2"
;
WHEN
3
THEN
SET
str_j
=
"3"
;
ELSE
SET
str_j
=
"unknown"
;
END
CASE
;
select
"i was 20"
;
END
;
WHEN
i
=
30
THEN
SET
str_i
=
"30"
;
WHEN
i
=
40
THEN
SET
str_i
=
"40"
;
ELSE
SET
str_i
=
"unknown"
;
END
CASE
;
SELECT
str_i
,
str_j
;
END
|
# Outer SIMPLE case, inner SIMPLE case
CREATE
PROCEDURE
proc_19194_nested_3
(
i
int
,
j
int
)
BEGIN
DECLARE
str_i
CHAR
(
10
);
DECLARE
str_j
CHAR
(
10
);
CASE
i
WHEN
10
THEN
SET
str_i
=
"10"
;
WHEN
20
THEN
BEGIN
set
str_i
=
"20"
;
CASE
j
WHEN
1
THEN
SET
str_j
=
"1"
;
WHEN
2
THEN
SET
str_j
=
"2"
;
WHEN
3
THEN
SET
str_j
=
"3"
;
ELSE
SET
str_j
=
"unknown"
;
END
CASE
;
select
"i was 20"
;
END
;
WHEN
30
THEN
SET
str_i
=
"30"
;
WHEN
40
THEN
SET
str_i
=
"40"
;
ELSE
SET
str_i
=
"unknown"
;
END
CASE
;
SELECT
str_i
,
str_j
;
END
|
# Outer SEARCHED case, inner SEARCHED case
CREATE
PROCEDURE
proc_19194_nested_4
(
i
int
,
j
int
)
BEGIN
DECLARE
str_i
CHAR
(
10
);
DECLARE
str_j
CHAR
(
10
);
CASE
WHEN
i
=
10
THEN
SET
str_i
=
"10"
;
WHEN
i
=
20
THEN
BEGIN
set
str_i
=
"20"
;
CASE
WHEN
j
=
1
THEN
SET
str_j
=
"1"
;
WHEN
j
=
2
THEN
SET
str_j
=
"2"
;
WHEN
j
=
3
THEN
SET
str_j
=
"3"
;
ELSE
SET
str_j
=
"unknown"
;
END
CASE
;
select
"i was 20"
;
END
;
WHEN
i
=
30
THEN
SET
str_i
=
"30"
;
WHEN
i
=
40
THEN
SET
str_i
=
"40"
;
ELSE
SET
str_i
=
"unknown"
;
END
CASE
;
SELECT
str_i
,
str_j
;
END
|
delimiter
;
|
SHOW
PROCEDURE
CODE
proc_19194_simple
;
SHOW
PROCEDURE
CODE
proc_19194_searched
;
SHOW
PROCEDURE
CODE
proc_19194_nested_1
;
SHOW
PROCEDURE
CODE
proc_19194_nested_2
;
SHOW
PROCEDURE
CODE
proc_19194_nested_3
;
SHOW
PROCEDURE
CODE
proc_19194_nested_4
;
CALL
proc_19194_nested_1
(
10
,
1
);
#
# Before 19194, the generated code was:
# 20 jump_if_not 23(27) 30
# 21 set str_i@2 _latin1'30'
# As opposed to the expected:
# 20 jump_if_not 23(27) (case_expr@0 = 30)
# 21 set str_i@2 _latin1'30'
#
# and as a result, this call returned "30",
# because the expression 30 is always true,
# masking the case 40, case 0 and the else.
#
CALL
proc_19194_nested_1
(
25
,
1
);
CALL
proc_19194_nested_1
(
20
,
1
);
CALL
proc_19194_nested_1
(
20
,
2
);
CALL
proc_19194_nested_1
(
20
,
3
);
CALL
proc_19194_nested_1
(
20
,
4
);
CALL
proc_19194_nested_1
(
30
,
1
);
CALL
proc_19194_nested_1
(
40
,
1
);
CALL
proc_19194_nested_1
(
0
,
0
);
CALL
proc_19194_nested_2
(
10
,
1
);
#
# Before 19194, the generated code was:
# 20 jump_if_not 23(27) (case_expr@0 = (i@0 = 30))
# 21 set str_i@2 _latin1'30'
# As opposed to the expected:
# 20 jump_if_not 23(27) (i@0 = 30)
# 21 set str_i@2 _latin1'30'
# and as a result, this call crashed the server, because there is no
# such variable as "case_expr@0".
#
CALL
proc_19194_nested_2
(
25
,
1
);
CALL
proc_19194_nested_2
(
20
,
1
);
CALL
proc_19194_nested_2
(
20
,
2
);
CALL
proc_19194_nested_2
(
20
,
3
);
CALL
proc_19194_nested_2
(
20
,
4
);
CALL
proc_19194_nested_2
(
30
,
1
);
CALL
proc_19194_nested_2
(
40
,
1
);
CALL
proc_19194_nested_2
(
0
,
0
);
CALL
proc_19194_nested_3
(
10
,
1
);
CALL
proc_19194_nested_3
(
25
,
1
);
CALL
proc_19194_nested_3
(
20
,
1
);
CALL
proc_19194_nested_3
(
20
,
2
);
CALL
proc_19194_nested_3
(
20
,
3
);
CALL
proc_19194_nested_3
(
20
,
4
);
CALL
proc_19194_nested_3
(
30
,
1
);
CALL
proc_19194_nested_3
(
40
,
1
);
CALL
proc_19194_nested_3
(
0
,
0
);
CALL
proc_19194_nested_4
(
10
,
1
);
CALL
proc_19194_nested_4
(
25
,
1
);
CALL
proc_19194_nested_4
(
20
,
1
);
CALL
proc_19194_nested_4
(
20
,
2
);
CALL
proc_19194_nested_4
(
20
,
3
);
CALL
proc_19194_nested_4
(
20
,
4
);
CALL
proc_19194_nested_4
(
30
,
1
);
CALL
proc_19194_nested_4
(
40
,
1
);
CALL
proc_19194_nested_4
(
0
,
0
);
DROP
PROCEDURE
proc_19194_simple
;
DROP
PROCEDURE
proc_19194_searched
;
DROP
PROCEDURE
proc_19194_nested_1
;
DROP
PROCEDURE
proc_19194_nested_2
;
DROP
PROCEDURE
proc_19194_nested_3
;
DROP
PROCEDURE
proc_19194_nested_4
;
#
# Bug#19207: Final parenthesis omitted for CREATE INDEX in Stored
...
...
mysql-test/t/sp_stress_case.test
0 → 100644
View file @
bf1005a1
#
# Bug#19194 (Right recursion in parser for CASE causes excessive stack
# usage, limitation)
#
--
disable_warnings
DROP
PROCEDURE
IF
EXISTS
proc_19194_codegen
;
DROP
PROCEDURE
IF
EXISTS
bug_19194_simple
;
DROP
PROCEDURE
IF
EXISTS
bug_19194_searched
;
--
enable_warnings
delimiter
|
;
CREATE
PROCEDURE
proc_19194_codegen
(
IN
proc_name
VARCHAR
(
50
),
IN
count
INTEGER
,
IN
simple
INTEGER
,
OUT
body
MEDIUMTEXT
)
BEGIN
DECLARE
code
MEDIUMTEXT
;
DECLARE
i
INT
DEFAULT
1
;
SET
code
=
concat
(
"CREATE PROCEDURE "
,
proc_name
,
"(i INT)
\n
"
);
SET
code
=
concat
(
code
,
"BEGIN
\n
"
);
SET
code
=
concat
(
code
,
" DECLARE str CHAR(10);
\n
"
);
IF
(
simple
)
THEN
SET
code
=
concat
(
code
,
" CASE i
\n
"
);
ELSE
SET
code
=
concat
(
code
,
" CASE
\n
"
);
END
IF
;
WHILE
(
i
<=
count
)
DO
IF
(
simple
)
THEN
SET
code
=
concat
(
code
,
" WHEN "
,
i
,
" THEN SET str=
\"
"
,
i
,
"
\"
;
\n
"
);
ELSE
SET
code
=
concat
(
code
,
" WHEN i="
,
i
,
" THEN SET str=
\"
"
,
i
,
"
\"
;
\n
"
);
END
IF
;
SET
i
=
i
+
1
;
END
WHILE
;
SET
code
=
concat
(
code
,
" ELSE SET str=
\"
unknown
\"
;
\n
"
);
SET
code
=
concat
(
code
,
" END CASE;
\n
"
);
SET
code
=
concat
(
code
,
" SELECT str;
\n
"
);
SET
code
=
concat
(
code
,
"END
\n
"
);
SET
body
=
code
;
END
|
delimiter
;
|
set
@
body
=
""
;
call
proc_19194_codegen
(
"test_simple"
,
10
,
1
,
@
body
);
select
@
body
;
call
proc_19194_codegen
(
"test_searched"
,
10
,
0
,
@
body
);
select
@
body
;
--
disable_query_log
call
proc_19194_codegen
(
"bug_19194_simple"
,
5000
,
1
,
@
body
);
let
$proc_body
=
`select @body`
;
eval
$proc_body
;
call
proc_19194_codegen
(
"bug_19194_searched"
,
5000
,
1
,
@
body
);
let
$proc_body
=
`select @body`
;
eval
$proc_body
;
--
enable_query_log
CALL
bug_19194_simple
(
1
);
CALL
bug_19194_simple
(
2
);
CALL
bug_19194_simple
(
1000
);
CALL
bug_19194_simple
(
4998
);
CALL
bug_19194_simple
(
4999
);
CALL
bug_19194_simple
(
9999
);
CALL
bug_19194_searched
(
1
);
CALL
bug_19194_searched
(
2
);
CALL
bug_19194_searched
(
1000
);
CALL
bug_19194_searched
(
4998
);
CALL
bug_19194_searched
(
4999
);
CALL
bug_19194_searched
(
9999
);
DROP
PROCEDURE
proc_19194_codegen
;
DROP
PROCEDURE
bug_19194_simple
;
DROP
PROCEDURE
bug_19194_searched
;
mysql-test/t/view.test
View file @
bf1005a1
...
...
@@ -2960,4 +2960,19 @@ DROP VIEW v1, v2;
DROP
TABLE
t1
;
#
# BUG#24293: '\Z' token is not handled correctly in views
#
--
disable_warnings
DROP
VIEW
IF
EXISTS
v1
;
--
enable_warnings
CREATE
VIEW
v1
AS
SELECT
'The\ZEnd'
;
SELECT
*
FROM
v1
;
SHOW
CREATE
VIEW
v1
;
DROP
VIEW
v1
;
--
echo
End
of
5.0
tests
.
server-tools/instance-manager/listener.cc
View file @
bf1005a1
...
...
@@ -187,7 +187,7 @@ void Listener_thread::run()
else
{
shutdown
(
client_fd
,
SHUT_RDWR
);
close
(
client_fd
);
close
socket
(
client_fd
);
}
}
}
...
...
@@ -199,7 +199,7 @@ void Listener_thread::run()
log_info
(
"Listener_thread::run(): shutdown requested, exiting..."
);
for
(
i
=
0
;
i
<
num_sockets
;
i
++
)
close
(
sockets
[
i
]);
close
socket
(
sockets
[
i
]);
#ifndef __WIN__
unlink
(
unix_socket_address
.
sun_path
);
...
...
@@ -212,7 +212,7 @@ void Listener_thread::run()
err:
// we have to close the ip sockets in case of error
for
(
i
=
0
;
i
<
num_sockets
;
i
++
)
close
(
sockets
[
i
]);
close
socket
(
sockets
[
i
]);
thread_registry
.
unregister_thread
(
&
thread_info
);
thread_registry
.
request_shutdown
();
...
...
@@ -259,7 +259,7 @@ int Listener_thread::create_tcp_socket()
{
log_error
(
"Listener_thread::run(): bind(ip socket) failed, '%s'"
,
strerror
(
errno
));
close
(
ip_socket
);
close
socket
(
ip_socket
);
return
-
1
;
}
...
...
@@ -267,7 +267,7 @@ int Listener_thread::create_tcp_socket()
{
log_error
(
"Listener_thread::run(): listen(ip socket) failed, %s"
,
strerror
(
errno
));
close
(
ip_socket
);
close
socket
(
ip_socket
);
return
-
1
;
}
...
...
sql/item_func.cc
View file @
bf1005a1
...
...
@@ -3688,8 +3688,9 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
char
*
pos
=
(
char
*
)
entry
+
ALIGN_SIZE
(
sizeof
(
user_var_entry
));
if
(
entry
->
value
==
pos
)
entry
->
value
=
0
;
if
(
!
(
entry
->
value
=
(
char
*
)
my_realloc
(
entry
->
value
,
length
,
MYF
(
MY_ALLOW_ZERO_PTR
))))
entry
->
value
=
(
char
*
)
my_realloc
(
entry
->
value
,
length
,
MYF
(
MY_ALLOW_ZERO_PTR
|
MY_WME
));
if
(
!
entry
->
value
)
return
1
;
}
}
...
...
sql/sp_head.cc
View file @
bf1005a1
...
...
@@ -605,27 +605,6 @@ sp_head::create(THD *thd)
DBUG_PRINT
(
"info"
,
(
"type: %d name: %s params: %s body: %s"
,
m_type
,
m_name
.
str
,
m_params
.
str
,
m_body
.
str
));
#ifndef DBUG_OFF
optimize
();
{
String
s
;
sp_instr
*
i
;
uint
ip
=
0
;
while
((
i
=
get_instr
(
ip
)))
{
char
buf
[
8
];
sprintf
(
buf
,
"%4u: "
,
ip
);
s
.
append
(
buf
);
i
->
print
(
&
s
);
s
.
append
(
'\n'
);
ip
+=
1
;
}
s
.
append
(
'\0'
);
DBUG_PRINT
(
"info"
,
(
"Code %s
\n
%s"
,
m_qname
.
str
,
s
.
ptr
()));
}
#endif
if
(
m_type
==
TYPE_ENUM_FUNCTION
)
ret
=
sp_create_function
(
thd
,
this
);
else
...
...
@@ -2173,7 +2152,7 @@ sp_head::show_create_function(THD *thd)
This is the main mark and move loop; it relies on the following methods
in sp_instr and its subclasses:
opt_mark() Mark instruction as reachable
(will recurse for jumps)
opt_mark() Mark instruction as reachable
opt_shortcut_jump() Shortcut jumps to the final destination;
used by opt_mark().
opt_move() Update moved instruction
...
...
@@ -2186,7 +2165,7 @@ void sp_head::optimize()
sp_instr
*
i
;
uint
src
,
dst
;
opt_mark
(
0
);
opt_mark
();
bp
.
empty
();
src
=
dst
=
0
;
...
...
@@ -2220,13 +2199,50 @@ void sp_head::optimize()
bp
.
empty
();
}
void
sp_head
::
add_mark_lead
(
uint
ip
,
List
<
sp_instr
>
*
leads
)
{
sp_instr
*
i
=
get_instr
(
ip
);
if
(
i
&&
!
i
->
marked
)
leads
->
push_front
(
i
);
}
void
sp_head
::
opt_mark
(
uint
ip
)
sp_head
::
opt_mark
()
{
uint
ip
;
sp_instr
*
i
;
List
<
sp_instr
>
leads
;
while
((
i
=
get_instr
(
ip
))
&&
!
i
->
marked
)
ip
=
i
->
opt_mark
(
this
);
/*
Forward flow analysis algorithm in the instruction graph:
- first, add the entry point in the graph (the first instruction) to the
'leads' list of paths to explore.
- while there are still leads to explore:
- pick one lead, and follow the path forward. Mark instruction reached.
Stop only if the end of the routine is reached, or the path converge
to code already explored (marked).
- while following a path, collect in the 'leads' list any fork to
another path (caused by conditional jumps instructions), so that these
paths can be explored as well.
*/
/* Add the entry point */
i
=
get_instr
(
0
);
leads
.
push_front
(
i
);
/* For each path of code ... */
while
(
leads
.
elements
!=
0
)
{
i
=
leads
.
pop
();
/* Mark the entire path, collecting new leads. */
while
(
i
&&
!
i
->
marked
)
{
ip
=
i
->
opt_mark
(
this
,
&
leads
);
i
=
get_instr
(
ip
);
}
}
}
...
...
@@ -2619,7 +2635,7 @@ sp_instr_jump::print(String *str)
}
uint
sp_instr_jump
::
opt_mark
(
sp_head
*
sp
)
sp_instr_jump
::
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
m_dest
=
opt_shortcut_jump
(
sp
,
this
);
if
(
m_dest
!=
m_ip
+
1
)
/* Jumping to following instruction? */
...
...
@@ -2713,7 +2729,7 @@ sp_instr_jump_if_not::print(String *str)
uint
sp_instr_jump_if_not
::
opt_mark
(
sp_head
*
sp
)
sp_instr_jump_if_not
::
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
sp_instr
*
i
;
...
...
@@ -2723,13 +2739,13 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp)
m_dest
=
i
->
opt_shortcut_jump
(
sp
,
this
);
m_optdest
=
sp
->
get_instr
(
m_dest
);
}
sp
->
opt_mark
(
m_dest
);
sp
->
add_mark_lead
(
m_dest
,
leads
);
if
((
i
=
sp
->
get_instr
(
m_cont_dest
)))
{
m_cont_dest
=
i
->
opt_shortcut_jump
(
sp
,
this
);
m_cont_optdest
=
sp
->
get_instr
(
m_cont_dest
);
}
sp
->
opt_mark
(
m_cont_dest
);
sp
->
add_mark_lead
(
m_cont_dest
,
leads
);
return
m_ip
+
1
;
}
...
...
@@ -2850,7 +2866,7 @@ sp_instr_hpush_jump::print(String *str)
uint
sp_instr_hpush_jump
::
opt_mark
(
sp_head
*
sp
)
sp_instr_hpush_jump
::
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
sp_instr
*
i
;
...
...
@@ -2860,7 +2876,7 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp)
m_dest
=
i
->
opt_shortcut_jump
(
sp
,
this
);
m_optdest
=
sp
->
get_instr
(
m_dest
);
}
sp
->
opt_mark
(
m_dest
);
sp
->
add_mark_lead
(
m_dest
,
leads
);
return
m_ip
+
1
;
}
...
...
@@ -2925,15 +2941,13 @@ sp_instr_hreturn::print(String *str)
uint
sp_instr_hreturn
::
opt_mark
(
sp_head
*
sp
)
sp_instr_hreturn
::
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
if
(
m_dest
)
return
sp_instr_jump
::
opt_mark
(
sp
);
else
{
marked
=
1
;
return
UINT_MAX
;
}
return
sp_instr_jump
::
opt_mark
(
sp
,
leads
);
marked
=
1
;
return
UINT_MAX
;
}
...
...
@@ -3276,7 +3290,7 @@ sp_instr_set_case_expr::print(String *str)
}
uint
sp_instr_set_case_expr
::
opt_mark
(
sp_head
*
sp
)
sp_instr_set_case_expr
::
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
sp_instr
*
i
;
...
...
@@ -3286,7 +3300,7 @@ sp_instr_set_case_expr::opt_mark(sp_head *sp)
m_cont_dest
=
i
->
opt_shortcut_jump
(
sp
,
this
);
m_cont_optdest
=
sp
->
get_instr
(
m_cont_dest
);
}
sp
->
opt_mark
(
m_cont_dest
);
sp
->
add_mark_lead
(
m_cont_dest
,
leads
);
return
m_ip
+
1
;
}
...
...
sql/sp_head.h
View file @
bf1005a1
...
...
@@ -301,8 +301,19 @@ public:
void
restore_thd_mem_root
(
THD
*
thd
);
/**
Optimize the code.
*/
void
optimize
();
void
opt_mark
(
uint
ip
);
/**
Helper used during flow analysis during code optimization.
See the implementation of <code>opt_mark()</code>.
@param ip the instruction to add to the leads list
@param leads the list of remaining paths to explore in the graph that
represents the code, during flow analysis.
*/
void
add_mark_lead
(
uint
ip
,
List
<
sp_instr
>
*
leads
);
void
recursion_level_error
(
THD
*
thd
);
...
...
@@ -392,6 +403,12 @@ private:
bool
execute
(
THD
*
thd
);
/**
Perform a forward flow analysis in the generated code.
Mark reachable instructions, for the optimizer.
*/
void
opt_mark
();
/*
Merge the list of tables used by query into the multi-set of tables used
by routine.
...
...
@@ -459,10 +476,10 @@ public:
/*
Mark this instruction as reachable during optimization and return the
index to the next instruction. Jump instruction will
mark
their
destination to
o recursively
.
index to the next instruction. Jump instruction will
add
their
destination to
the leads list
.
*/
virtual
uint
opt_mark
(
sp_head
*
sp
)
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
marked
=
1
;
return
m_ip
+
1
;
...
...
@@ -734,7 +751,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
);
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
);
virtual
uint
opt_shortcut_jump
(
sp_head
*
sp
,
sp_instr
*
start
);
...
...
@@ -784,7 +801,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
);
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
);
/* Override sp_instr_jump's shortcut; we stop here */
virtual
uint
opt_shortcut_jump
(
sp_head
*
sp
,
sp_instr
*
start
)
...
...
@@ -830,7 +847,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
)
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
marked
=
1
;
return
UINT_MAX
;
...
...
@@ -867,7 +884,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
);
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
);
/* Override sp_instr_jump's shortcut; we stop here. */
virtual
uint
opt_shortcut_jump
(
sp_head
*
sp
,
sp_instr
*
start
)
...
...
@@ -932,7 +949,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
);
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
);
private:
...
...
@@ -1102,7 +1119,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
)
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
)
{
marked
=
1
;
return
UINT_MAX
;
...
...
@@ -1135,7 +1152,7 @@ public:
virtual
void
print
(
String
*
str
);
virtual
uint
opt_mark
(
sp_head
*
sp
);
virtual
uint
opt_mark
(
sp_head
*
sp
,
List
<
sp_instr
>
*
leads
);
virtual
void
opt_move
(
uint
dst
,
List
<
sp_instr
>
*
ibp
);
...
...
sql/sql_class.cc
View file @
bf1005a1
...
...
@@ -884,6 +884,13 @@ void select_result::cleanup()
/* do nothing */
}
bool
select_result
::
check_simple_select
()
const
{
my_error
(
ER_SP_BAD_CURSOR_QUERY
,
MYF
(
0
));
return
TRUE
;
}
static
String
default_line_term
(
"
\n
"
,
default_charset_info
);
static
String
default_escaped
(
"
\\
"
,
default_charset_info
);
static
String
default_field_term
(
"
\t
"
,
default_charset_info
);
...
...
@@ -1521,6 +1528,13 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
}
bool
select_dumpvar
::
check_simple_select
()
const
{
my_error
(
ER_SP_BAD_CURSOR_SELECT
,
MYF
(
0
));
return
TRUE
;
}
void
select_dumpvar
::
cleanup
()
{
row_count
=
0
;
...
...
sql/sql_class.h
View file @
bf1005a1
...
...
@@ -1723,7 +1723,14 @@ public:
virtual
bool
initialize_tables
(
JOIN
*
join
=
0
)
{
return
0
;
}
virtual
void
send_error
(
uint
errcode
,
const
char
*
err
);
virtual
bool
send_eof
()
=
0
;
virtual
bool
simple_select
()
{
return
0
;
}
/**
Check if this query returns a result set and therefore is allowed in
cursors and set an error message if it is not the case.
@retval FALSE success
@retval TRUE error, an error message is set
*/
virtual
bool
check_simple_select
()
const
;
virtual
void
abort
()
{}
/*
Cleanup instance of this class for next execution of a prepared
...
...
@@ -1761,7 +1768,7 @@ public:
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flags
);
bool
send_data
(
List
<
Item
>
&
items
);
bool
send_eof
();
bool
simple_select
()
{
return
1
;
}
virtual
bool
check_simple_select
()
const
{
return
FALSE
;
}
void
abort
();
};
...
...
@@ -2200,6 +2207,7 @@ public:
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_data
(
List
<
Item
>
&
items
);
bool
send_eof
();
virtual
bool
check_simple_select
()
const
;
void
cleanup
();
};
...
...
sql/sql_lex.cc
View file @
bf1005a1
...
...
@@ -1163,7 +1163,6 @@ void st_select_lex::init_select()
options
=
0
;
sql_cache
=
SQL_CACHE_UNSPECIFIED
;
braces
=
0
;
when_list
.
empty
();
expr_list
.
empty
();
udf_list
.
empty
();
interval_list
.
empty
();
...
...
sql/sql_lex.h
View file @
bf1005a1
...
...
@@ -517,7 +517,6 @@ public:
SQL_LIST
order_list
;
/* ORDER clause */
List
<
List_item
>
expr_list
;
List
<
List_item
>
when_list
;
/* WHEN clause (expression) */
SQL_LIST
*
gorder_list
;
Item
*
select_limit
,
*
offset_limit
;
/* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list
...
...
sql/sql_prepare.cc
View file @
bf1005a1
...
...
@@ -2902,10 +2902,9 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
in INSERT ... SELECT and similar commands.
*/
if
(
open_cursor
&&
lex
->
result
&&
!
lex
->
result
->
simple_select
())
if
(
open_cursor
&&
lex
->
result
&&
lex
->
result
->
check_
simple_select
())
{
DBUG_PRINT
(
"info"
,(
"Cursor asked for not SELECT stmt"
));
my_error
(
ER_SP_BAD_CURSOR_QUERY
,
MYF
(
0
));
return
TRUE
;
}
...
...
sql/sql_string.cc
View file @
bf1005a1
...
...
@@ -1032,8 +1032,8 @@ void String::print(String *str)
case
'\r'
:
str
->
append
(
STRING_WITH_LEN
(
"
\\
r"
));
break
;
case
26
:
//
Ctrl-Z
str
->
append
(
STRING_WITH_LEN
(
"
\\
z
"
));
case
'\032'
:
//
Ctrl-Z
str
->
append
(
STRING_WITH_LEN
(
"
\\
Z
"
));
break
;
default:
str
->
append
(
c
);
...
...
sql/sql_yacc.yy
View file @
bf1005a1
...
...
@@ -95,6 +95,187 @@ void turn_parser_debug_on()
}
#endif
/**
Helper action for a case statement (entering the CASE).
This helper is used for both 'simple' and 'searched' cases.
This helper, with the other case_stmt_action_..., is executed when
the following SQL code is parsed:
<pre>
CREATE PROCEDURE proc_19194_simple(i int)
BEGIN
DECLARE str CHAR(10);
CASE i
WHEN 1 THEN SET str="1";
WHEN 2 THEN SET str="2";
WHEN 3 THEN SET str="3";
ELSE SET str="unknown";
END CASE;
SELECT str;
END
</pre>
The actions are used to generate the following code:
<pre>
SHOW PROCEDURE CODE proc_19194_simple;
Pos Instruction
0 set str@1 NULL
1 set_case_expr (12) 0 i@0
2 jump_if_not 5(12) (case_expr@0 = 1)
3 set str@1 _latin1'1'
4 jump 12
5 jump_if_not 8(12) (case_expr@0 = 2)
6 set str@1 _latin1'2'
7 jump 12
8 jump_if_not 11(12) (case_expr@0 = 3)
9 set str@1 _latin1'3'
10 jump 12
11 set str@1 _latin1'unknown'
12 stmt 0 "SELECT str"
</pre>
@param lex the parser lex context
*/
void case_stmt_action_case(LEX *lex)
{
lex->sphead->new_cont_backpatch(NULL);
/*
BACKPATCH: Creating target label for the jump to
"case_stmt_action_end_case"
(Instruction 12 in the example)
*/
lex->spcont->push_label((char *)"", lex->sphead->instructions());
}
/**
Helper action for a case expression statement (the expr in 'CASE expr').
This helper is used for 'searched' cases only.
@param lex the parser lex context
@param expr the parsed expression
@return 0 on success
*/
int case_stmt_action_expr(LEX *lex, Item* expr)
{
sp_head *sp= lex->sphead;
sp_pcontext *parsing_ctx= lex->spcont;
int case_expr_id= parsing_ctx->register_case_expr();
sp_instr_set_case_expr *i;
if (parsing_ctx->push_case_expr_id(case_expr_id))
return 1;
i= new sp_instr_set_case_expr(sp->instructions(),
parsing_ctx, case_expr_id, expr, lex);
sp->add_cont_backpatch(i);
sp->add_instr(i);
return 0;
}
/**
Helper action for a case when condition.
This helper is used for both 'simple' and 'searched' cases.
@param lex the parser lex context
@param when the parsed expression for the WHEN clause
@param simple true for simple cases, false for searched cases
*/
void case_stmt_action_when(LEX *lex, Item *when, bool simple)
{
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
sp_instr_jump_if_not *i;
Item_case_expr *var;
Item *expr;
if (simple)
{
var= new Item_case_expr(ctx->get_current_case_expr_id());
#ifndef DBUG_OFF
if (var)
{
var->m_sp= sp;
}
#endif
expr= new Item_func_eq(var, when);
i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
}
else
i= new sp_instr_jump_if_not(ip, ctx, when, lex);
/*
BACKPATCH: Registering forward jump from
"case_stmt_action_when" to "case_stmt_action_then"
(jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
*/
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->add_cont_backpatch(i);
sp->add_instr(i);
}
/**
Helper action for a case then statements.
This helper is used for both 'simple' and 'searched' cases.
@param lex the parser lex context
*/
void case_stmt_action_then(LEX *lex)
{
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip, ctx);
sp->add_instr(i);
/*
BACKPATCH: Resolving forward jump from
"case_stmt_action_when" to "case_stmt_action_then"
(jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
*/
sp->backpatch(ctx->pop_label());
/*
BACKPATCH: Registering forward jump from
"case_stmt_action_then" to "case_stmt_action_end_case"
(jump from instruction 4 to 12, 7 to 12 ... in the example)
*/
sp->push_backpatch(i, ctx->last_label());
}
/**
Helper action for an end case.
This helper is used for both 'simple' and 'searched' cases.
@param lex the parser lex context
@param simple true for simple cases, false for searched cases
*/
void case_stmt_action_end_case(LEX *lex, bool simple)
{
/*
BACKPATCH: Resolving forward jump from
"case_stmt_action_then" to "case_stmt_action_end_case"
(jump from instruction 4 to 12, 7 to 12 ... in the example)
*/
lex->sphead->backpatch(lex->spcont->pop_label());
if (simple)
lex->spcont->pop_case_expr_id();
lex->sphead->do_cont_backpatch();
}
%}
%union {
int num;
...
...
@@ -831,7 +1012,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
when_list2
expr_list2 udf_expr_list3 handler
expr_list2 udf_expr_list3 handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock
...
...
@@ -859,6 +1040,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
view_suid view_tail view_list_opt view_list view_select
view_check_option trigger_tail sp_tail
case_stmt_specification simple_case_stmt searched_case_stmt
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
...
...
@@ -1993,43 +2175,7 @@ sp_proc_stmt:
{ Lex->sphead->new_cont_backpatch(NULL); }
sp_if END IF
{ Lex->sphead->do_cont_backpatch(); }
| CASE_SYM WHEN_SYM
{
Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE;
Lex->sphead->new_cont_backpatch(NULL);
}
sp_case END CASE_SYM { Lex->sphead->do_cont_backpatch(); }
| CASE_SYM
{
Lex->sphead->reset_lex(YYTHD);
Lex->sphead->new_cont_backpatch(NULL);
}
expr WHEN_SYM
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *parsing_ctx= lex->spcont;
int case_expr_id= parsing_ctx->register_case_expr();
sp_instr_set_case_expr *i;
if (parsing_ctx->push_case_expr_id(case_expr_id))
YYABORT;
i= new sp_instr_set_case_expr(sp->instructions(),
parsing_ctx,
case_expr_id,
$3,
lex);
sp->add_cont_backpatch(i);
sp->add_instr(i);
sp->m_flags|= sp_head::IN_SIMPLE_CASE;
sp->restore_lex(YYTHD);
}
sp_case END CASE_SYM
{
Lex->spcont->pop_case_expr_id();
Lex->sphead->do_cont_backpatch();
}
| case_stmt_specification
| sp_labeled_control
{}
| { /* Unlabeled controls get a secret label. */
...
...
@@ -2240,72 +2386,114 @@ sp_elseifs:
| ELSE sp_proc_stmts1
;
sp_case:
{ Lex->sphead->reset_lex(YYTHD); }
expr THEN_SYM
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
sp_instr_jump_if_not *i;
if (! (sp->m_flags & sp_head::IN_SIMPLE_CASE))
i= new sp_instr_jump_if_not(ip, ctx, $2, lex);
else
{ /* Simple case: <caseval> = <whenval> */
case_stmt_specification:
simple_case_stmt
| searched_case_stmt
;
Item_case_expr *var;
Item *expr;
simple_case_stmt:
CASE_SYM
{
LEX *lex= Lex;
case_stmt_action_case(lex);
lex->sphead->reset_lex(YYTHD); /* For expr $3 */
}
expr
{
LEX *lex= Lex;
if (case_stmt_action_expr(lex, $3))
YYABORT;
var= new Item_case_expr(ctx->get_current_case_expr_id());
lex->sphead->restore_lex(YYTHD); /* For expr $3 */
}
simple_when_clause_list
else_clause_opt
END
CASE_SYM
{
LEX *lex= Lex;
case_stmt_action_end_case(lex, true);
}
;
#ifndef DBUG_OFF
if (var)
var->m_sp= sp;
#endif
searched_case_stmt:
CASE_SYM
{
LEX *lex= Lex;
case_stmt_action_case(lex);
}
searched_when_clause_list
else_clause_opt
END
CASE_SYM
{
LEX *lex= Lex;
case_stmt_action_end_case(lex, false);
}
;
expr= new Item_func_eq(var, $2);
simple_when_clause_list:
simple_when_clause
| simple_when_clause_list simple_when_clause
;
i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
}
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->add_cont_backpatch(i);
sp->add_instr(i);
sp->restore_lex(YYTHD);
}
sp_proc_stmts1
{
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip, ctx);
searched_when_clause_list:
searched_when_clause
| searched_when_clause_list searched_when_clause
;
sp->add_instr(i);
sp->backpatch(ctx->pop_label());
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
}
sp_whens
{
LEX *lex= Lex;
simple_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
}
expr
{
/* Simple case: <caseval> = <whenval> */
lex->sphead->backpatch(lex->spcont->pop_label());
}
;
LEX *lex= Lex;
case_stmt_action_when(lex, $3, true);
lex->sphead->restore_lex(YYTHD); /* For expr $3 */
}
THEN_SYM
sp_proc_stmts1
{
LEX *lex= Lex;
case_stmt_action_then(lex);
}
;
sp_whens:
/* Empty */
{
sp_head *sp= Lex->sphead;
uint ip= sp->instructions();
sp_instr_error *i= new sp_instr_error(ip, Lex->spcont,
ER_SP_CASE_NOT_FOUND);
searched_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
}
expr
{
LEX *lex= Lex;
case_stmt_action_when(lex, $3, false);
lex->sphead->restore_lex(YYTHD); /* For expr $3 */
}
THEN_SYM
sp_proc_stmts1
{
LEX *lex= Lex;
case_stmt_action_then(lex);
}
;
sp->add_instr(i);
}
| ELSE sp_proc_stmts1 {}
| WHEN_SYM sp_case {}
;
else_clause_opt:
/* empty */
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
sp_instr_error *i= new sp_instr_error(ip, lex->spcont,
ER_SP_CASE_NOT_FOUND);
sp->add_instr(i);
}
| ELSE sp_proc_stmts1
;
sp_labeled_control:
label_ident ':'
...
...
@@ -4372,8 +4560,8 @@ simple_expr:
if (!$$)
YYABORT;
}
| CASE_SYM opt_expr
WHEN_SYM
when_list opt_else END
{ $$= new Item_func_case(* $
4, $2, $5
); }
| CASE_SYM opt_expr when_list opt_else END
{ $$= new Item_func_case(* $
3, $2, $4
); }
| CONVERT_SYM '(' expr ',' cast_type ')'
{
$$= create_func_cast($3, $5,
...
...
@@ -5182,23 +5370,19 @@ opt_else:
| ELSE expr { $$= $2; };
when_list:
{ Select->when_list.push_front(new List<Item>); }
when_list2
{ $$= Select->when_list.pop(); };
when_list2:
expr THEN_SYM expr
{
SELECT_LEX *sel=Select;
sel->when_list.head()->push_back($1);
sel->when_list.head()->push_back($3);
}
| when_list2 WHEN_SYM expr THEN_SYM expr
{
SELECT_LEX *sel=Select;
sel->when_list.head()->push_back($3);
sel->when_list.head()->push_back($5);
};
WHEN_SYM expr THEN_SYM expr
{
$$= new List<Item>;
$$->push_back($2);
$$->push_back($4);
}
| when_list WHEN_SYM expr THEN_SYM expr
{
$1->push_back($3);
$1->push_back($5);
$$= $1;
}
;
/* Warning - may return NULL in case of incomplete SELECT */
table_ref:
...
...
tests/mysql_client_test.c
View file @
bf1005a1
...
...
@@ -15455,6 +15455,33 @@ static void test_bug21635()
DBUG_VOID_RETURN
;
}
/*
Bug#24179 "select b into $var" fails with --cursor_protocol"
The failure is correct, check that the returned message is meaningful.
*/
static
void
test_bug24179
()
{
int
rc
;
MYSQL_STMT
*
stmt
;
DBUG_ENTER
(
"test_bug24179"
);
myheader
(
"test_bug24179"
);
stmt
=
open_cursor
(
"select 1 into @a"
);
rc
=
mysql_stmt_execute
(
stmt
);
DIE_UNLESS
(
rc
);
if
(
!
opt_silent
)
{
printf
(
"Got error (as expected): %d %s
\n
"
,
mysql_stmt_errno
(
stmt
),
mysql_stmt_error
(
stmt
));
}
DIE_UNLESS
(
mysql_stmt_errno
(
stmt
)
==
1323
);
DBUG_VOID_RETURN
;
}
/*
Read and parse arguments and MySQL options from my.cnf
...
...
@@ -15734,6 +15761,7 @@ static struct my_tests_st my_tests[]= {
{
"test_bug21726"
,
test_bug21726
},
{
"test_bug23383"
,
test_bug23383
},
{
"test_bug21635"
,
test_bug21635
},
{
"test_bug24179"
,
test_bug24179
},
{
0
,
0
}
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment