From: Marc Alff Date: July 15 2008 4:30pm Subject: bzr commit into mysql-6.0 tree (marc.alff:2717) Bug#35577, Bug#37669 List-Archive: http://lists.mysql.com/commits/49774 X-Bug: 37669 Message-Id: <20080715163039.989FD1DC614@lambda.WEBLAB> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============5820914271392841212==" --===============5820914271392841212== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/malff/BZR-TREE/mysql-6.0-35577-merge/ ------------------------------------------------------------ revno: 2717 revision-id: marc.alff@stripped parent: gshchepa@stripped parent: marc.alff@stripped committer: Marc Alff branch nick: mysql-6.0-35577-merge timestamp: Tue 2008-07-15 10:29:51 -0600 message: Bug#35577, manual merge mysql-5.1-bugteam -> mysql-6.0-bugteam added: mysql-test/r/parser_stack.result parser_stack.result-20080710213555-qr1nm5k011b23116-1 mysql-test/t/parser_stack.test parser_stack.test-20080710213601-cvl5jef5im7hzzbl-1 modified: sql/event_data_objects.cc sp1f-event_timed.cc-20051205104456-ckd2gzuwhr4u5umqbncmt43nvv45pxmf sql/mysql_priv.h sp1f-mysql_priv.h-19700101030959-4fl65tqpop5zfgxaxkqotu2fa2ree5ci sql/sp.cc sp1f-sp.cc-20021212121421-6xwuvxq5bku2b4yv655kp2e5gsvautd5 sql/sp_head.cc sp1f-sp_head.cc-20021208185920-jtgc5wvyqdnu2gvcdus3gazrfhxbofxd sql/sql_class.cc sp1f-sql_class.cc-19700101030959-rpotnweaff2pikkozh3butrf7mv3oero sql/sql_class.h sp1f-sql_class.h-19700101030959-jnqnbrjyqsvgncsibnumsmg3lyi7pa5s sql/sql_lex.cc sp1f-sql_lex.cc-19700101030959-4pizwlu5rqkti27gcwsvxkawq6bc2kph sql/sql_lex.h sp1f-sql_lex.h-19700101030959-sgldb2sooc7twtw5q7pgjx7qzqiaa3sn sql/sql_parse.cc sp1f-sql_parse.cc-19700101030959-ehcre3rwhv5l3mlxqhaxg36ujenxnrcd sql/sql_partition.cc sp1f-sql_partition.cc-20050718113038-57h5bzswps6cel2y7k7qideue3ghbg3u sql/sql_plugin.cc sp1f-sql_plugin.cc-20051105112032-hrm64p6xfjq33ud6zy3uivpo7azm75a2 sql/sql_prepare.cc sp1f-sql_prepare.cc-20020612210720-gtqjjiu7vpmfxb5xct2qke7urmqcabli sql/sql_trigger.cc sp1f-sql_trigger.cc-20040907122911-35k3wamrp6g7qsupxe7hisftpobcwin5 sql/sql_view.cc sp1f-sql_view.cc-20040715221517-nw4p4mja6nzzlvwwhzfgfqb4umxqobe4 sql/sql_yacc.yy sp1f-sql_yacc.yy-19700101030959-wvn4qyy2drpmge7kaq3dysprbhlrv27j ------------------------------------------------------------ revno: 2497.345.3 revision-id: marc.alff@stripped parent: ramil@stripped parent: marc.alff@stripped committer: Marc Alff branch nick: mysql-5.1-35577-merge timestamp: Mon 2008-07-14 19:43:12 -0600 message: Bug#35577, manual merge mysql-5.0-bugteam -> mysql-5.1-bugteam added: mysql-test/r/parser_stack.result parser_stack.result-20080710213555-qr1nm5k011b23116-1 mysql-test/t/parser_stack.test parser_stack.test-20080710213601-cvl5jef5im7hzzbl-1 modified: sql/event_data_objects.cc sp1f-event_timed.cc-20051205104456-ckd2gzuwhr4u5umqbncmt43nvv45pxmf sql/mysql_priv.h sp1f-mysql_priv.h-19700101030959-4fl65tqpop5zfgxaxkqotu2fa2ree5ci sql/sp.cc sp1f-sp.cc-20021212121421-6xwuvxq5bku2b4yv655kp2e5gsvautd5 sql/sp_head.cc sp1f-sp_head.cc-20021208185920-jtgc5wvyqdnu2gvcdus3gazrfhxbofxd sql/sql_class.cc sp1f-sql_class.cc-19700101030959-rpotnweaff2pikkozh3butrf7mv3oero sql/sql_class.h sp1f-sql_class.h-19700101030959-jnqnbrjyqsvgncsibnumsmg3lyi7pa5s sql/sql_lex.cc sp1f-sql_lex.cc-19700101030959-4pizwlu5rqkti27gcwsvxkawq6bc2kph sql/sql_lex.h sp1f-sql_lex.h-19700101030959-sgldb2sooc7twtw5q7pgjx7qzqiaa3sn sql/sql_parse.cc sp1f-sql_parse.cc-19700101030959-ehcre3rwhv5l3mlxqhaxg36ujenxnrcd sql/sql_partition.cc sp1f-sql_partition.cc-20050718113038-57h5bzswps6cel2y7k7qideue3ghbg3u sql/sql_prepare.cc sp1f-sql_prepare.cc-20020612210720-gtqjjiu7vpmfxb5xct2qke7urmqcabli sql/sql_trigger.cc sp1f-sql_trigger.cc-20040907122911-35k3wamrp6g7qsupxe7hisftpobcwin5 sql/sql_view.cc sp1f-sql_view.cc-20040715221517-nw4p4mja6nzzlvwwhzfgfqb4umxqobe4 sql/sql_yacc.yy sp1f-sql_yacc.yy-19700101030959-wvn4qyy2drpmge7kaq3dysprbhlrv27j ------------------------------------------------------------ revno: 1810.3752.2 revision-id: marc.alff@stripped parent: marc.alff@stripped parent: gshchepa@stripped committer: Marc Alff branch nick: mysql-5.0-35577-merge timestamp: Mon 2008-07-14 15:47:34 -0600 message: Merge modified: sql/item_strfunc.cc sp1f-item_strfunc.cc-19700101030959-yl2pwnrngmla3nmlgiuiwrztx3iu4ffl ------------------------------------------------------------ revno: 1810.3752.1 revision-id: marc.alff@stripped parent: azundris@stripped committer: Marc Alff branch nick: mysql-5.0-35577-merge timestamp: Mon 2008-07-14 15:41:30 -0600 message: Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) The crash was caused by freeing the internal parser stack during the parser execution. This occured only for complex stored procedures, after reallocating the parser stack using my_yyoverflow(), with the following C call stack: - MYSQLparse() - any rule calling sp_head::restore_lex() - lex_end() - x_free(lex->yacc_yyss), xfree(lex->yacc_yyvs) The root cause is the implementation of stored procedures, which breaks the assumption from 4.1 that there is only one LEX structure per parser call. The solution is to separate the LEX structure into: - attributes that represent a statement (the current LEX structure), - attributes that relate to the syntax parser itself (Yacc_state), so that parsing multiple statements in stored programs can create multiple LEX structures while not changing the unique Yacc_state. Now, Yacc_state and the existing Lex_input_stream are aggregated into Parser_state, a structure that represent the complete state of the (Lexical + Syntax) parser. added: mysql-test/r/parser_stack.result parser_stack.result-20080710213555-qr1nm5k011b23116-1 mysql-test/t/parser_stack.test parser_stack.test-20080710213601-cvl5jef5im7hzzbl-1 modified: sql/sp.cc sp1f-sp.cc-20021212121421-6xwuvxq5bku2b4yv655kp2e5gsvautd5 sql/sp_head.cc sp1f-sp_head.cc-20021208185920-jtgc5wvyqdnu2gvcdus3gazrfhxbofxd sql/sql_class.cc sp1f-sql_class.cc-19700101030959-rpotnweaff2pikkozh3butrf7mv3oero sql/sql_class.h sp1f-sql_class.h-19700101030959-jnqnbrjyqsvgncsibnumsmg3lyi7pa5s sql/sql_lex.cc sp1f-sql_lex.cc-19700101030959-4pizwlu5rqkti27gcwsvxkawq6bc2kph sql/sql_lex.h sp1f-sql_lex.h-19700101030959-sgldb2sooc7twtw5q7pgjx7qzqiaa3sn sql/sql_parse.cc sp1f-sql_parse.cc-19700101030959-ehcre3rwhv5l3mlxqhaxg36ujenxnrcd sql/sql_prepare.cc sp1f-sql_prepare.cc-20020612210720-gtqjjiu7vpmfxb5xct2qke7urmqcabli sql/sql_trigger.cc sp1f-sql_trigger.cc-20040907122911-35k3wamrp6g7qsupxe7hisftpobcwin5 sql/sql_view.cc sp1f-sql_view.cc-20040715221517-nw4p4mja6nzzlvwwhzfgfqb4umxqobe4 sql/sql_yacc.yy sp1f-sql_yacc.yy-19700101030959-wvn4qyy2drpmge7kaq3dysprbhlrv27j ------------------------------------------------------------ revno: 2497.345.2 revision-id: ramil@stripped parent: ramil@stripped parent: gshchepa@stripped committer: Ramil Kalimullin branch nick: b37669.5.1 timestamp: Mon 2008-07-14 15:57:56 +0500 message: auto-merge modified: client/mysqltest.c sp1f-mysqltest.c-20001010065317-ix4zw26srlev7yugcz455ux22zwyynyf configure.in sp1f-configure.in-19700101030959-mgdpoxtnh2ewmvusvfpkreuhwvffkcjw libmysqld/emb_qcache.cc sp1f-emb_qcache.cc-20031201131847-myynfuq6x72jc2677yvwpv5prufpnvxa mysql-test/r/func_in.result sp1f-func_in.result-20001228015633-taucsvp7ggm45m64jbcfu6nyfgdhosnc mysql-test/r/func_misc.result sp1f-func_misc.result-20001228015633-4sy6dzzt7xcs4ubzcxloyguc7zhougbr mysql-test/r/max_user_connections_func.result sp1f-max_user_connections-20080410131337-xnqivtwdj7e4yub53fr3ci6bnioqsabo mysql-test/r/mysqltest.result sp1f-mysqltest.result-20041022024801-dfor5httbrm4yhbhqtfjzpkst5hoejym mysql-test/suite/funcs_1/datadict/charset_collation.inc sp1f-charset_collation.in-20080307163305-edrudf23pcobanheiax4mtuw42llel37 mysql-test/suite/funcs_1/t/charset_collation_1.test sp1f-charset_collation_1.-20080307163303-xoj2pleizxk54stjeffsheamxhopuxni mysql-test/suite/funcs_1/t/charset_collation_3.test sp1f-charset_collation_3.-20080307163303-wvj3wrresuqmlxzn3dvqppaajsi2ajdp mysql-test/suite/funcs_2/charset/charset_master.test sp1f-charset_master.test-20070206175440-sgefy4i6nwwi43svr5asovdpgvmycuvr mysql-test/suite/funcs_2/t/innodb_charset.test sp1f-innodb_charset.test-20070206180358-jwznkkalaqtecydoobuidk436pokqmvc mysql-test/suite/funcs_2/t/memory_charset.test sp1f-memory_charset.test-20070206180358-5uoxm3xp5xysaoi3lql7pj3vous7wi6k mysql-test/suite/funcs_2/t/myisam_charset.test sp1f-myisam_charset.test-20070206180358-4ddnsur4zeb2tsnsl24l2b4pm463jajn mysql-test/suite/funcs_2/t/ndb_charset.test sp1f-ndb_charset.test-20070206180358-jzvzee7vehbt3ze2rsdpfbms3xbnqoha mysql-test/suite/parts/inc/partition_check_drop.inc sp1f-partition_check_drop-20070206122150-msiad4yh2rpz5rw4mvio2uhtkeugbsfx mysql-test/suite/parts/inc/partition_layout.inc sp1f-partition_layout.inc-20060117062739-bl3wqlg6o3we423funhz77o77spxqykx mysql-test/suite/parts/inc/partition_layout_check1.inc sp1f-partition_layout_che-20070206122235-d5cge7vx544iv42gnrlln4yigezn4tq2 mysql-test/suite/parts/inc/partition_layout_check2.inc sp1f-partition_layout_che-20070206122235-e5lxxz4xjjgth6tesls4x7hxdzhydp5m mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result sp1f-partition_alter1_1_2-20080513231048-ibvqvplo53vrvjs2wzrkrh5vaxmodixm mysql-test/suite/parts/r/partition_alter1_1_myisam.result sp1f-partition_alter1_1_m-20080513231048-c6i674jghn6f4qszjht76lxfxtfshxxp mysql-test/suite/parts/r/partition_alter1_2_myisam.result sp1f-partition_alter1_2_m-20080513231048-js52yzqp26p7455im7swficligsnnaki mysql-test/suite/parts/r/partition_alter2_myisam.result sp1f-partition_alter2_myi-20070206122236-jpkrr2v2pgpksws5xs3ecgy3jjd5od6c mysql-test/suite/parts/r/partition_alter3_innodb.result sp1f-partition_alter3_inn-20070206122236-wzwsaoeagleydj364f2u2pt2lslwqwwb mysql-test/suite/parts/r/partition_alter3_myisam.result sp1f-partition_alter3_myi-20070206122236-yu3lt72hpugp3xt5bnd2lspl35fg6eit mysql-test/suite/parts/r/partition_basic_innodb.result sp1f-partition_basic_inno-20070206122237-pzpy2hvit34fxpvkxic73muh7h66lqhm mysql-test/suite/parts/r/partition_basic_myisam.result sp1f-partition_basic_myis-20070206122237-ra3v2mwwwyd2tuddpu2ahvjvhg6wipqy mysql-test/suite/parts/r/partition_basic_symlink_myisam.result sp1f-partition_basic_syml-20080206141352-wwg6qk37quijmoqlubhbsgrkvybphmoc mysql-test/suite/parts/r/partition_engine_myisam.result sp1f-partition_engine_myi-20070206122237-2dovgbiyyvkmhmgarswhz3lgwi3awwq4 mysql-test/suite/parts/r/partition_syntax_myisam.result sp1f-partition_syntax_myi-20070206122237-kr377sndti562n6qtkc5s52iqnptrigq mysql-test/t/func_in.test sp1f-func_in.test-20001228015635-dykb2qebuowolk7cf6gpa4brezc4m5gk mysql-test/t/func_misc.test sp1f-func_misc.test-20001228015635-kayguwcdgtjnekzavvdzbsnqcdwfm36c mysql-test/t/max_user_connections_func.test sp1f-max_user_connections-20080410131402-7hd5q3zzxki2pkvu5ungk3ealjczqpch mysql-test/t/mysqltest.test sp1f-mysqltest.test-20041022024800-v3hvkzs4236l6rpunai7xttdltot7rvz sql/item_cmpfunc.cc sp1f-item_cmpfunc.cc-19700101030959-hrk7pi2n6qpwxauufnkizirsoucdcx2e sql/item_strfunc.cc sp1f-item_strfunc.cc-19700101030959-yl2pwnrngmla3nmlgiuiwrztx3iu4ffl ------------------------------------------------------------ revno: 2497.345.1 revision-id: ramil@stripped parent: marc.alff@stripped committer: Ramil Kalimullin branch nick: b37669.5.1 timestamp: Wed 2008-07-09 16:52:26 +0500 message: Fix for bug#37669: Server crash by setting "@@session.innodb_table_locks" Problem: reading/writing data from/to an address without proper alignment leads to SIGBUS on some platforms. Fix: use the correct data type when dereferencing variable values. modified: sql/sql_plugin.cc sp1f-sql_plugin.cc-20051105112032-hrm64p6xfjq33ud6zy3uivpo7azm75a2 --===============5820914271392841212== MIME-Version: 1.0 Content-Type: text/text/x-diff; charset="us-ascii"; name="patch-2717.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline === added file 'mysql-test/r/parser_stack.result' --- a/mysql-test/r/parser_stack.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/r/parser_stack.result 2008-07-14 21:41:30 +0000 @@ -0,0 +1,306 @@ +use test; +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; +1 +1 +prepare stmt from +" +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +" +; +execute stmt; +1 +1 +drop view if exists view_overflow; +CREATE VIEW view_overflow AS +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; +SELECT * from view_overflow; +1 +1 +drop view view_overflow; +drop procedure if exists proc_overflow; +CREATE PROCEDURE proc_overflow() +BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +select 1; +select 2; +select 3; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END $$ +call proc_overflow(); +1 +1 +2 +2 +3 +3 +drop procedure proc_overflow; +drop function if exists func_overflow; +create function func_overflow() returns int +BEGIN +DECLARE x int default 0; +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +SET x=x+1; +SET x=x+2; +SET x=x+3; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +return x; +END $$ +select func_overflow(); +func_overflow() +6 +drop function func_overflow; +drop table if exists table_overflow; +create table table_overflow(a int, b int); +create trigger trigger_overflow before insert on table_overflow +for each row +BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +SET NEW.b := NEW.a; +SET NEW.b := NEW.b + 1; +SET NEW.b := NEW.b + 2; +SET NEW.b := NEW.b + 3; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END $$ +insert into table_overflow set a=10; +insert into table_overflow set a=20; +select * from table_overflow; +a b +10 16 +20 26 +drop table table_overflow; +drop procedure if exists proc_35577; +CREATE PROCEDURE proc_35577() +BEGIN +DECLARE z_done INT DEFAULT 0; +DECLARE t_done VARCHAR(5000); +outer_loop: LOOP +IF t_done=1 THEN +LEAVE outer_loop; +END IF; +inner_block:BEGIN +DECLARE z_done INT DEFAULT 0; +SET z_done = 0; +inner_loop: LOOP +IF z_done=1 THEN +LEAVE inner_loop; +END IF; +IF (t_done = 'a') THEN +IF (t_done <> 0) THEN +IF ( t_done > 0) THEN +IF (t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF (t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +END IF; +END IF; +END IF; +END IF; +END LOOP inner_loop; +END inner_block; +END LOOP outer_loop; +END $$ +drop procedure proc_35577; +drop procedure if exists p_37269; +create procedure p_37269() +begin +declare done int default 0; +declare varb int default 0; +declare vara int default 0; +repeat +select now(); +until done end repeat; +while varb do +select now(); +begin +select now(); +repeat +select now(); +until done end repeat; +if vara then +select now(); +repeat +select now(); +loop +select now(); +end loop; +repeat +select now(); +label1: while varb do +select now(); +end while label1; +if vara then +select now(); +repeat +select now(); +until done end repeat; +begin +select now(); +while varb do +select now(); +label1: while varb do +select now(); +end while label1; +if vara then +select now(); +while varb do +select now(); +loop +select now(); +end loop; +repeat +select now(); +loop +select now(); +while varb do +select now(); +end while; +repeat +select now(); +label1: loop +select now(); +if vara then +select now(); +end if; +end loop label1; +until done end repeat; +end loop; +until done end repeat; +end while; +end if; +end while; +end; +end if; +until done end repeat; +until done end repeat; +end if; +end; +end while; +end $$ +drop procedure p_37269; +drop procedure if exists p_37228; +create procedure p_37228 () +BEGIN +DECLARE v INT DEFAULT 123; +IF (v > 1) THEN SET v = 1; +ELSEIF (v < 10) THEN SET v = 10; +ELSEIF (v < 11) THEN SET v = 11; +ELSEIF (v < 12) THEN SET v = 12; +ELSEIF (v < 13) THEN SET v = 13; +ELSEIF (v < 14) THEN SET v = 14; +ELSEIF (v < 15) THEN SET v = 15; +ELSEIF (v < 16) THEN SET v = 16; +ELSEIF (v < 17) THEN SET v = 17; +ELSEIF (v < 18) THEN SET v = 18; +ELSEIF (v < 19) THEN SET v = 19; +ELSEIF (v < 20) THEN SET v = 20; +ELSEIF (v < 21) THEN SET v = 21; +ELSEIF (v < 22) THEN SET v = 22; +ELSEIF (v < 23) THEN SET v = 23; +ELSEIF (v < 24) THEN SET v = 24; +ELSEIF (v < 25) THEN SET v = 25; +ELSEIF (v < 26) THEN SET v = 26; +ELSEIF (v < 27) THEN SET v = 27; +ELSEIF (v < 28) THEN SET v = 28; +ELSEIF (v < 29) THEN SET v = 29; +ELSEIF (v < 30) THEN SET v = 30; +ELSEIF (v < 31) THEN SET v = 31; +ELSEIF (v < 32) THEN SET v = 32; +ELSEIF (v < 33) THEN SET v = 33; +ELSEIF (v < 34) THEN SET v = 34; +ELSEIF (v < 35) THEN SET v = 35; +ELSEIF (v < 36) THEN SET v = 36; +ELSEIF (v < 37) THEN SET v = 37; +ELSEIF (v < 38) THEN SET v = 38; +ELSEIF (v < 39) THEN SET v = 39; +END IF; +END $$ +drop procedure p_37228; === added file 'mysql-test/t/parser_stack.test' --- a/mysql-test/t/parser_stack.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/parser_stack.test 2008-07-14 21:41:30 +0000 @@ -0,0 +1,402 @@ +# Copyright (C) 2008 Sun Microsystems, Inc +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# +# These tests are designed to cause an internal parser stack overflow, +# and trigger my_yyoverflow(). +# + +use test; + +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; + +prepare stmt from +" +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +" +; + +execute stmt; + +--disable_warnings +drop view if exists view_overflow; +--enable_warnings + +CREATE VIEW view_overflow AS +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; + +SELECT * from view_overflow; + +drop view view_overflow; + +--disable_warnings +drop procedure if exists proc_overflow; +--enable_warnings + +delimiter $$; + +CREATE PROCEDURE proc_overflow() +BEGIN + + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + + select 1; + select 2; + select 3; + + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + +END $$ + +delimiter ;$$ + +call proc_overflow(); + +drop procedure proc_overflow; + +--disable_warnings +drop function if exists func_overflow; +--enable_warnings + +delimiter $$; + +create function func_overflow() returns int +BEGIN + DECLARE x int default 0; + + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + + SET x=x+1; + SET x=x+2; + SET x=x+3; + + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + + return x; +END $$ + +delimiter ;$$ + +select func_overflow(); + +drop function func_overflow; + +--disable_warnings +drop table if exists table_overflow; +--enable_warnings + +create table table_overflow(a int, b int); + +delimiter $$; + +create trigger trigger_overflow before insert on table_overflow +for each row +BEGIN + + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + + SET NEW.b := NEW.a; + SET NEW.b := NEW.b + 1; + SET NEW.b := NEW.b + 2; + SET NEW.b := NEW.b + 3; + + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + +END $$ + +delimiter ;$$ + +insert into table_overflow set a=10; +insert into table_overflow set a=20; +select * from table_overflow; + +drop table table_overflow; + +--disable_warnings +drop procedure if exists proc_35577; +--enable_warnings + +delimiter $$; + +CREATE PROCEDURE proc_35577() +BEGIN + DECLARE z_done INT DEFAULT 0; + DECLARE t_done VARCHAR(5000); + outer_loop: LOOP + IF t_done=1 THEN + LEAVE outer_loop; + END IF; + + inner_block:BEGIN + DECLARE z_done INT DEFAULT 0; + SET z_done = 0; + inner_loop: LOOP + IF z_done=1 THEN + LEAVE inner_loop; + END IF; + IF (t_done = 'a') THEN + IF (t_done <> 0) THEN + IF ( t_done > 0) THEN + IF (t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF (t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + END IF; + END IF; + END IF; + END IF; + END LOOP inner_loop; + END inner_block; + END LOOP outer_loop; +END $$ + +delimiter ;$$ + +drop procedure proc_35577; + +# +# Bug#37269 (parser crash when creating stored procedure) +# + +--disable_warnings +drop procedure if exists p_37269; +--enable_warnings + +delimiter $$; + +create procedure p_37269() +begin + declare done int default 0; + declare varb int default 0; + declare vara int default 0; + + repeat + select now(); + until done end repeat; + while varb do + select now(); + begin + select now(); + repeat + select now(); + until done end repeat; + if vara then + select now(); + repeat + select now(); + loop + select now(); + end loop; + repeat + select now(); + label1: while varb do + select now(); + end while label1; + if vara then + select now(); + repeat + select now(); + until done end repeat; + begin + select now(); + while varb do + select now(); + label1: while varb do + select now(); + end while label1; + if vara then + select now(); + while varb do + select now(); + loop + select now(); + end loop; + repeat + select now(); + loop + select now(); + while varb do + select now(); + end while; + repeat + select now(); + label1: loop + select now(); + if vara then + select now(); + end if; + end loop label1; + until done end repeat; + end loop; + until done end repeat; + end while; + end if; + end while; + end; + end if; + until done end repeat; + until done end repeat; + end if; + end; + end while; +end $$ + +delimiter ;$$ + +drop procedure p_37269; + +# +# Bug#37228 (Sever crashes when creating stored procedure with more than +# 10 IF/ELSEIF) +# + +--disable_warnings +drop procedure if exists p_37228; +--enable_warnings + +delimiter $$; + +create procedure p_37228 () +BEGIN + DECLARE v INT DEFAULT 123; + + IF (v > 1) THEN SET v = 1; + ELSEIF (v < 10) THEN SET v = 10; + ELSEIF (v < 11) THEN SET v = 11; + ELSEIF (v < 12) THEN SET v = 12; + ELSEIF (v < 13) THEN SET v = 13; + ELSEIF (v < 14) THEN SET v = 14; + ELSEIF (v < 15) THEN SET v = 15; + ELSEIF (v < 16) THEN SET v = 16; + ELSEIF (v < 17) THEN SET v = 17; + ELSEIF (v < 18) THEN SET v = 18; + ELSEIF (v < 19) THEN SET v = 19; + ELSEIF (v < 20) THEN SET v = 20; + ELSEIF (v < 21) THEN SET v = 21; + ELSEIF (v < 22) THEN SET v = 22; + ELSEIF (v < 23) THEN SET v = 23; + ELSEIF (v < 24) THEN SET v = 24; + ELSEIF (v < 25) THEN SET v = 25; + ELSEIF (v < 26) THEN SET v = 26; + ELSEIF (v < 27) THEN SET v = 27; + ELSEIF (v < 28) THEN SET v = 28; + ELSEIF (v < 29) THEN SET v = 29; + ELSEIF (v < 30) THEN SET v = 30; + ELSEIF (v < 31) THEN SET v = 31; + ELSEIF (v < 32) THEN SET v = 32; + ELSEIF (v < 33) THEN SET v = 33; + ELSEIF (v < 34) THEN SET v = 34; + ELSEIF (v < 35) THEN SET v = 35; + ELSEIF (v < 36) THEN SET v = 36; + ELSEIF (v < 37) THEN SET v = 37; + ELSEIF (v < 38) THEN SET v = 38; + ELSEIF (v < 39) THEN SET v = 39; + END IF; +END $$ + +delimiter ;$$ + +drop procedure p_37228; + + === modified file 'sql/event_data_objects.cc' --- a/sql/event_data_objects.cc 2008-06-17 20:04:19 +0000 +++ b/sql/event_data_objects.cc 2008-07-15 16:29:51 +0000 @@ -1438,10 +1438,10 @@ thd->query_length= sp_sql.length(); { - Lex_input_stream lip(thd, thd->query, thd->query_length); + Parser_state parser_state(thd, thd->query, thd->query_length); lex_start(thd); - if (parse_sql(thd, &lip, creation_ctx)) + if (parse_sql(thd, & parser_state, creation_ctx)) { sql_print_error("Event Scheduler: " "%serror during compilation of %s.%s", === modified file 'sql/mysql_priv.h' --- a/sql/mysql_priv.h 2008-06-28 11:00:59 +0000 +++ b/sql/mysql_priv.h 2008-07-15 16:29:51 +0000 @@ -53,6 +53,8 @@ #include #endif +class Parser_state; + /** Query type constants. @@ -863,8 +865,8 @@ bool test_if_data_home_dir(const char *dir); bool parse_sql(THD *thd, - class Lex_input_stream *lip, - class Object_creation_ctx *creation_ctx); + Parser_state *parser_state, + Object_creation_ctx *creation_ctx); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, === modified file 'sql/sp.cc' --- a/sql/sp.cc 2008-06-04 11:18:52 +0000 +++ b/sql/sp.cc 2008-07-15 16:29:51 +0000 @@ -539,12 +539,12 @@ thd->variables.sql_mode= sql_mode; thd->variables.select_limit= HA_POS_ERROR; - Lex_input_stream lip(thd, defstr->c_ptr(), defstr->length()); + Parser_state parser_state(thd, defstr->c_ptr(), defstr->length()); lex_start(thd); thd->push_internal_handler(&warning_handler); thd->spcont= 0; - if (parse_sql(thd, &lip, creation_ctx) || thd->lex == NULL) + if (parse_sql(thd, & parser_state, creation_ctx) || thd->lex == NULL) { sp= thd->lex->sphead; delete sp; === modified file 'sql/sp_head.cc' --- a/sql/sp_head.cc 2008-06-28 11:00:59 +0000 +++ b/sql/sp_head.cc 2008-07-15 16:29:51 +0000 @@ -620,14 +620,14 @@ sp_head::set_body_start(THD *thd, const char *begin_ptr) { m_body_begin= begin_ptr; - thd->m_lip->body_utf8_start(thd, begin_ptr); + thd->m_parser_state->m_lip.body_utf8_start(thd, begin_ptr); } void sp_head::set_stmt_end(THD *thd) { - Lex_input_stream *lip= thd->m_lip; /* shortcut */ + Lex_input_stream *lip= & thd->m_parser_state->m_lip; /* shortcut */ const char *end_ptr= lip->get_cpp_ptr(); /* shortcut */ /* Make the string of parameters. */ === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2008-06-28 11:00:59 +0000 +++ b/sql/sql_class.cc 2008-07-15 16:29:51 +0000 @@ -528,7 +528,7 @@ bootstrap(0), derived_tables_processing(FALSE), spcont(NULL), - m_lip(NULL), + m_parser_state(NULL), /* @todo The following is a work around for online backup and the DDL blocker. It should be removed when the generalized solution is in place. === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2008-06-28 11:00:59 +0000 +++ b/sql/sql_class.h 2008-07-15 16:29:51 +0000 @@ -77,7 +77,7 @@ class Slave_log_event; class sp_rcontext; class sp_cache; -class Lex_input_stream; +class Parser_state; class Rows_log_event; enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; @@ -1918,13 +1918,11 @@ } binlog_evt_union; /** - Character input stream consumed by the lexical analyser, - used during parsing. - Note that since the parser is not re-entrant, we keep only one input - stream here. This member is valid only when executing code during parsing, - and may point to invalid memory after that. + Internal parser state. + Note that since the parser is not re-entrant, we keep only one parser + state here. This member is valid only when executing code during parsing. */ - Lex_input_stream *m_lip; + Parser_state *m_parser_state; /* @todo The following is a work around for online backup and the DDL blocker. === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2008-07-07 23:15:08 +0000 +++ b/sql/sql_lex.cc 2008-07-15 16:29:51 +0000 @@ -381,13 +381,6 @@ { DBUG_ENTER("lex_end"); DBUG_PRINT("enter", ("lex: %p", lex)); - if (lex->yacc_yyss) - { - my_free(lex->yacc_yyss, MYF(0)); - my_free(lex->yacc_yyvs, MYF(0)); - lex->yacc_yyss= 0; - lex->yacc_yyvs= 0; - } /* release used plugins */ plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, @@ -397,6 +390,14 @@ DBUG_VOID_RETURN; } +Yacc_state::~Yacc_state() +{ + if (yacc_yyss) + { + my_free(yacc_yyss, MYF(0)); + my_free(yacc_yyvs, MYF(0)); + } +} static int find_keyword(Lex_input_stream *lip, uint len, bool function) { @@ -732,7 +733,7 @@ int MYSQLlex(void *arg, void *yythd) { THD *thd= (THD *)yythd; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; YYSTYPE *yylval=(YYSTYPE*) arg; int token; @@ -791,7 +792,7 @@ uint length; enum my_lex_states state; THD *thd= (THD *)yythd; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; LEX *lex= thd->lex; YYSTYPE *yylval=(YYSTYPE*) arg; CHARSET_INFO *cs= thd->charset(); @@ -2210,7 +2211,7 @@ */ st_lex::st_lex() - :result(0), yacc_yyss(0), yacc_yyvs(0), + :result(0), sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0) { === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2008-04-21 23:37:29 +0000 +++ b/sql/sql_lex.h 2008-07-15 16:29:51 +0000 @@ -1536,7 +1536,6 @@ LEX_STRING comment, ident; LEX_USER *grant_user; XID *xid; - uchar* yacc_yyss, *yacc_yyvs; THD *thd; /* maintain a list of used plugins for this LEX */ @@ -1876,6 +1875,59 @@ } } LEX; + +/** + The internal state of the syntax parser. + This object is only available during parsing, + and is private to the syntax parser implementation (sql_yacc.yy). +*/ +class Yacc_state +{ +public: + Yacc_state() + : yacc_yyss(NULL), yacc_yyvs(NULL) + {} + + ~Yacc_state(); + + /** + Bison internal state stack, yyss, when dynamically allocated using + my_yyoverflow(). + */ + uchar *yacc_yyss; + + /** + Bison internal semantic value stack, yyvs, when dynamically allocated using + my_yyoverflow(). + */ + uchar *yacc_yyvs; + + /* + TODO: move more attributes from the LEX structure here. + */ +}; + +/** + Internal state of the parser. + The complete state consist of: + - state data used during lexical parsing, + - state data used during syntactic parsing. +*/ +class Parser_state +{ +public: + Parser_state(THD *thd, const char* buff, unsigned int length) + : m_lip(thd, buff, length), m_yacc() + {} + + ~Parser_state() + {} + + Lex_input_stream m_lip; + Yacc_state m_yacc; +}; + + struct st_lex_local: public st_lex { static void *operator new(size_t size) throw() === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2008-07-10 23:29:27 +0000 +++ b/sql/sql_parse.cc 2008-07-15 16:29:51 +0000 @@ -5482,29 +5482,35 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) { - LEX *lex= current_thd->lex; + Yacc_state *state= & current_thd->m_parser_state->m_yacc; ulong old_info=0; + DBUG_ASSERT(state); if ((uint) *yystacksize >= MY_YACC_MAX) return 1; - if (!lex->yacc_yyvs) + if (!state->yacc_yyvs) old_info= *yystacksize; *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX); - if (!(lex->yacc_yyvs= (uchar*) - my_realloc(lex->yacc_yyvs, - *yystacksize*sizeof(**yyvs), - MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) || - !(lex->yacc_yyss= (uchar*) - my_realloc(lex->yacc_yyss, - *yystacksize*sizeof(**yyss), - MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR)))) + if (!(state->yacc_yyvs= (uchar*) + my_realloc(state->yacc_yyvs, + *yystacksize*sizeof(**yyvs), + MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) || + !(state->yacc_yyss= (uchar*) + my_realloc(state->yacc_yyss, + *yystacksize*sizeof(**yyss), + MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR)))) return 1; if (old_info) - { // Copy old info from stack - memcpy(lex->yacc_yyss, (uchar*) *yyss, old_info*sizeof(**yyss)); - memcpy(lex->yacc_yyvs, (uchar*) *yyvs, old_info*sizeof(**yyvs)); + { + /* + Only copy the old stack on the first call to my_yyoverflow(), + when replacing a static stack (YYINITDEPTH) by a dynamic stack. + For subsequent calls, my_realloc already did preserve the old stack. + */ + memcpy(state->yacc_yyss, *yyss, old_info*sizeof(**yyss)); + memcpy(state->yacc_yyvs, *yyvs, old_info*sizeof(**yyvs)); } - *yyss=(short*) lex->yacc_yyss; - *yyvs=(YYSTYPE*) lex->yacc_yyvs; + *yyss= (short*) state->yacc_yyss; + *yyvs= (YYSTYPE*) state->yacc_yyvs; return 0; } @@ -5770,10 +5776,10 @@ sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_func_cache); - Lex_input_stream lip(thd, inBuf, length); + Parser_state parser_state(thd, inBuf, length); - bool err= parse_sql(thd, &lip, NULL); - *found_semicolon= lip.found_semicolon; + bool err= parse_sql(thd, & parser_state, NULL); + *found_semicolon= parser_state.m_lip.found_semicolon; if (!err) { @@ -5858,11 +5864,11 @@ bool error= 0; DBUG_ENTER("mysql_test_parse_for_slave"); - Lex_input_stream lip(thd, inBuf, length); + Parser_state parser_state(thd, inBuf, length); lex_start(thd); mysql_reset_thd_for_next_command(thd); - if (!parse_sql(thd, &lip, NULL) && + if (!parse_sql(thd, & parser_state, NULL) && all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) error= 1; /* Ignore question */ thd->end_statement(); @@ -6920,7 +6926,7 @@ if (lex->current_select != &lex->select_lex) { char command[80]; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; strmake(command, lip->yylval->symbol.str, min(lip->yylval->symbol.length, sizeof(command)-1)); my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command); @@ -7669,7 +7675,7 @@ instead of MYSQLparse(). @param thd Thread context. - @param lip Lexer context. + @param parser_state Parser state. @param creation_ctx Object creation context. @return Error status. @@ -7678,11 +7684,11 @@ */ bool parse_sql(THD *thd, - Lex_input_stream *lip, + Parser_state *parser_state, Object_creation_ctx *creation_ctx) { bool mysql_parse_status; - DBUG_ASSERT(thd->m_lip == NULL); + DBUG_ASSERT(thd->m_parser_state == NULL); /* Backup creation context. */ @@ -7691,10 +7697,10 @@ if (creation_ctx) backup_ctx= creation_ctx->set_n_backup(thd); - /* Set Lex_input_stream. */ + /* Set parser state. */ - lip->set_echo(TRUE); - thd->m_lip= lip; + parser_state->m_lip.set_echo(TRUE); + thd->m_parser_state= parser_state; /* Parse the query. */ @@ -7704,9 +7710,9 @@ DBUG_ASSERT(!mysql_parse_status || thd->is_error()); - /* Reset Lex_input_stream. */ + /* Reset parser state. */ - thd->m_lip= NULL; + thd->m_parser_state= NULL; /* Restore creation context. */ === modified file 'sql/sql_partition.cc' --- a/sql/sql_partition.cc 2008-06-11 11:49:58 +0000 +++ b/sql/sql_partition.cc 2008-07-15 16:29:51 +0000 @@ -3755,7 +3755,7 @@ thd->lex= &lex; thd->variables.character_set_client= system_charset_info; - Lex_input_stream lip(thd, part_buf, part_info_len); + Parser_state parser_state(thd, part_buf, part_info_len); lex_start(thd); *work_part_info_used= false; @@ -3785,7 +3785,7 @@ lex.part_info->part_state= part_state; lex.part_info->part_state_len= part_state_len; DBUG_PRINT("info", ("Parse: %s", part_buf)); - if (parse_sql(thd, &lip, NULL)) + if (parse_sql(thd, & parser_state, NULL)) { thd->free_items(); goto end; === modified file 'sql/sql_plugin.cc' --- a/sql/sql_plugin.cc 2008-06-28 11:00:59 +0000 +++ b/sql/sql_plugin.cc 2008-07-15 16:29:51 +0000 @@ -1890,7 +1890,7 @@ } result= (int) tmp; } - *(int*)save= -result; + *(my_bool *) save= -result; return 0; err: my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); @@ -2071,7 +2071,7 @@ static void update_func_bool(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save) { - *(my_bool *) tgt= *(int *) save ? 1 : 0; + *(my_bool *) tgt= *(my_bool *) save ? TRUE : FALSE; } === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2008-07-10 23:29:27 +0000 +++ b/sql/sql_prepare.cc 2008-07-15 16:29:51 +0000 @@ -3020,11 +3020,11 @@ old_stmt_arena= thd->stmt_arena; thd->stmt_arena= this; - Lex_input_stream lip(thd, thd->query, thd->query_length); - lip.stmt_prepare_mode= TRUE; + Parser_state parser_state(thd, thd->query, thd->query_length); + parser_state.m_lip.stmt_prepare_mode= TRUE; lex_start(thd); - error= parse_sql(thd, &lip, NULL) || + error= parse_sql(thd, & parser_state, NULL) || thd->is_error() || init_param_array(this); === modified file 'sql/sql_trigger.cc' --- a/sql/sql_trigger.cc 2008-06-11 11:49:58 +0000 +++ b/sql/sql_trigger.cc 2008-07-15 16:29:51 +0000 @@ -1289,7 +1289,9 @@ thd->variables.sql_mode= (ulong)*trg_sql_mode; - Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length); + Parser_state parser_state(thd, + trg_create_str->str, + trg_create_str->length); Trigger_creation_ctx *creation_ctx= Trigger_creation_ctx::create(thd, @@ -1302,7 +1304,7 @@ lex_start(thd); thd->spcont= NULL; - if (parse_sql(thd, &lip, creation_ctx)) + if (parse_sql(thd, & parser_state, creation_ctx)) { /* Currently sphead is always deleted in case of a parse error */ DBUG_ASSERT(lex.sphead == 0); === modified file 'sql/sql_view.cc' --- a/sql/sql_view.cc 2008-06-26 18:56:36 +0000 +++ b/sql/sql_view.cc 2008-07-15 16:29:51 +0000 @@ -1158,9 +1158,9 @@ char old_db_buf[NAME_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; - Lex_input_stream lip(thd, - table->select_stmt.str, - table->select_stmt.length); + Parser_state parser_state(thd, + table->select_stmt.str, + table->select_stmt.length); /* Use view db name as thread default database, in order to ensure @@ -1204,7 +1204,7 @@ /* Parse the query. */ - parse_status= parse_sql(thd, &lip, table->view_creation_ctx); + parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx); /* Restore environment. */ === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2008-07-10 23:29:27 +0000 +++ b/sql/sql_yacc.yy 2008-07-15 16:29:51 +0000 @@ -28,6 +28,7 @@ #define YYPARSE_PARAM yythd #define YYLEX_PARAM yythd #define YYTHD ((THD *)yythd) +#define YYLIP (& YYTHD->m_parser_state->m_lip) #define MYSQL_YACC #define YYINITDEPTH 100 @@ -119,7 +120,7 @@ void my_parse_error(const char *s) { THD *thd= current_thd; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; const char *yytext= lip->get_tok_start(); /* Push an error into the error stack */ @@ -1467,11 +1468,11 @@ MYSQL_YYABORT; } thd->lex->sql_command= SQLCOM_EMPTY_QUERY; - thd->m_lip->found_semicolon= NULL; + YYLIP->found_semicolon= NULL; } | verb_clause { - Lex_input_stream *lip = YYTHD->m_lip; + Lex_input_stream *lip = YYLIP; if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) && ! lip->stmt_prepare_mode && @@ -1497,7 +1498,7 @@ | verb_clause END_OF_INPUT { /* Single query, not terminated. */ - YYTHD->m_lip->found_semicolon= NULL; + YYLIP->found_semicolon= NULL; } ; @@ -2069,7 +2070,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; /* This stops the following : @@ -2726,7 +2727,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; lex->sphead->reset_lex(thd); lex->sphead->m_tmp_query= lip->get_tok_start(); @@ -2735,7 +2736,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_head *sp= lex->sphead; sp->m_flags|= sp_get_flags_for_command(lex); @@ -6825,17 +6826,13 @@ remember_name: { - THD *thd= YYTHD; - Lex_input_stream *lip= thd->m_lip; - $$= (char*) lip->get_cpp_tok_start(); + $$= (char*) YYLIP->get_cpp_tok_start(); } ; remember_end: { - THD *thd= YYTHD; - Lex_input_stream *lip= thd->m_lip; - $$= (char*) lip->get_cpp_tok_end(); + $$= (char*) YYLIP->get_cpp_tok_end(); } ; @@ -10078,7 +10075,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead) { @@ -10101,10 +10098,7 @@ } opt_duplicate INTO { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - lex->fname_end= lip->get_ptr(); + Lex->fname_end= YYLIP->get_ptr(); } TABLE_SYM table_ident { @@ -10348,7 +10342,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; Item_param *item; if (! lex->parsing_options.allows_variable) { @@ -10380,7 +10374,7 @@ | NULL_SYM { $$ = new Item_null(); - YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT; + YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT; } | FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); } | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); } @@ -10510,7 +10504,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_variable_t *spv; sp_pcontext *spc = lex->spcont; if (spc && (spv = spc->find_variable(&$1))) @@ -11207,7 +11201,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead) { @@ -11238,7 +11232,7 @@ { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead) { @@ -12612,19 +12606,17 @@ { THD *thd= YYTHD; LEX *lex= Lex; - Lex_input_stream *lip= thd->m_lip; lex->parsing_options.allows_variable= FALSE; lex->parsing_options.allows_select_into= FALSE; lex->parsing_options.allows_select_procedure= FALSE; lex->parsing_options.allows_derived= FALSE; - lex->create_view_select.str= (char *) lip->get_cpp_ptr(); + lex->create_view_select.str= (char *) YYLIP->get_cpp_ptr(); } view_select_aux view_check_option { THD *thd= YYTHD; LEX *lex= Lex; - Lex_input_stream *lip= thd->m_lip; - uint len= lip->get_cpp_ptr() - lex->create_view_select.str; + uint len= YYLIP->get_cpp_ptr() - lex->create_view_select.str; void *create_view_select= thd->memdup(lex->create_view_select.str, len); lex->create_view_select.length= len; lex->create_view_select.str= (char *) create_view_select; @@ -12667,26 +12659,20 @@ ON remember_name /* $7 */ { /* $8 */ - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - lex->raw_trg_on_table_name_begin= lip->get_tok_start(); + Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start(); } table_ident /* $9 */ FOR_SYM remember_name /* $11 */ { /* $12 */ - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - lex->raw_trg_on_table_name_end= lip->get_tok_start(); + Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start(); } EACH_SYM ROW_SYM { /* $15 */ THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_head *sp; if (lex->sphead) @@ -12790,7 +12776,7 @@ { /* $5 */ THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_head *sp; const char* tmp_param_begin; @@ -12818,11 +12804,7 @@ sp_fdparam_list /* $6 */ ')' /* $7 */ { /* $8 */ - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - - lex->sphead->m_param_end= lip->get_cpp_tok_start(); + Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start(); } RETURNS_SYM /* $9 */ { /* $10 */ @@ -12859,7 +12841,7 @@ { /* $14 */ THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); @@ -12944,33 +12926,28 @@ } '(' { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; const char* tmp_param_begin; - tmp_param_begin= lip->get_cpp_tok_start(); + tmp_param_begin= YYLIP->get_cpp_tok_start(); tmp_param_begin++; - lex->sphead->m_param_begin= tmp_param_begin; + Lex->sphead->m_param_begin= tmp_param_begin; } sp_pdparam_list ')' { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - lex->sphead->m_param_end= lip->get_cpp_tok_start(); + lex->sphead->m_param_end= YYLIP->get_cpp_tok_start(); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } sp_c_chistics { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); + lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); } sp_proc_stmt { --===============5820914271392841212==--