diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 82dd7c65039..6851f4c9d49 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -202,7 +202,14 @@ SYST=0 REALT=0 FAST_START="" MYSQL_TMP_DIR=$MYSQL_TEST_DIR/var/tmp -SLAVE_LOAD_TMPDIR=../../var/tmp #needs to be same length to test logging + +# Use a relative path for where the slave will find the dumps +# generated by "LOAD DATA" on the master. The path is relative +# since it must have fixed length to test logging +# i.e otherwise the output from "SHOW MASTER STATUS" will vary +# with the strlen() of MYSQL_TEST_DIR +SLAVE_LOAD_TMPDIR=../tmp + RES_SPACE=" " MYSQLD_SRC_DIRS="strings mysys include extra regex myisam \ myisammrg heap sql" @@ -651,8 +658,10 @@ fi [ -d $MYSQL_TEST_DIR/var/tmp ] || mkdir $MYSQL_TEST_DIR/var/tmp [ -d $MYSQL_TEST_DIR/var/run ] || mkdir $MYSQL_TEST_DIR/var/run [ -d $MYSQL_TEST_DIR/var/log ] || mkdir $MYSQL_TEST_DIR/var/log -ln -s $MYSQL_TEST_DIR/std_data $MYSQL_TEST_DIR/var/std_data_ln - +if ! test -L $MYSQL_TEST_DIR/var/std_data_ln ; then + ln -s $MYSQL_TEST_DIR/std_data/ $MYSQL_TEST_DIR/var/std_data_ln +fi + if test ${COLUMNS:-0} -lt 80 ; then COLUMNS=80 ; fi E=`$EXPR $COLUMNS - 8` DASH72=`$ECHO '-------------------------------------------------------'|$CUT -c 1-$E` diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result index 434a5df1e17..214c9466c8c 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -506,3 +506,12 @@ d1 d2 02 February 01 January drop table t1; +select str_to_date( 1, NULL ); +str_to_date( 1, NULL ) +NULL +select str_to_date( NULL, 1 ); +str_to_date( NULL, 1 ) +NULL +select str_to_date( 1, IF(1=1,NULL,NULL) ); +str_to_date( 1, IF(1=1,NULL,NULL) ) +NULL diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 4391889fec9..c1e7533bcee 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1530,7 +1530,7 @@ CREATE TABLE federated.t1 ( PRIMARY KEY (`id`) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 -CONNECTION='mysql://root@127.0.0.1:9308/federated/t1'; +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; INSERT INTO federated.t1 VALUES (); SELECT LAST_INSERT_ID(); LAST_INSERT_ID() diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index 943471c2261..bb0adae6bab 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -1,3 +1,5 @@ +drop procedure if exists empty; +drop procedure if exists code_sample; create procedure empty() begin end; @@ -60,3 +62,140 @@ Pos Instruction 20 cpop 1 21 stmt 0 "select t.name, t.idx from t2 t order ..." drop procedure code_sample; +drop procedure if exists sudoku_solve; +create procedure sudoku_solve(p_naive boolean, p_all boolean) +deterministic +modifies sql data +begin +drop temporary table if exists sudoku_work, sudoku_schedule; +create temporary table sudoku_work +( +row smallint not null, +col smallint not null, +dig smallint not null, +cnt smallint, +key using btree (cnt), +key using btree (row), +key using btree (col), +unique key using hash (row,col) +); +create temporary table sudoku_schedule +( +idx int not null auto_increment primary key, +row smallint not null, +col smallint not null +); +call sudoku_init(); +if p_naive then +update sudoku_work set cnt = 0 where dig = 0; +else +call sudoku_count(); +end if; +insert into sudoku_schedule (row,col) +select row,col from sudoku_work where cnt is not null order by cnt desc; +begin +declare v_scounter bigint default 0; +declare v_i smallint default 1; +declare v_dig smallint; +declare v_schedmax smallint; +select count(*) into v_schedmax from sudoku_schedule; +more: +loop +begin +declare v_tcounter bigint default 0; +sched: +while v_i <= v_schedmax do +begin +declare v_row, v_col smallint; +select row,col into v_row,v_col from sudoku_schedule where v_i = idx; +select dig into v_dig from sudoku_work +where v_row = row and v_col = col; +case v_dig +when 0 then +set v_dig = 1; +update sudoku_work set dig = 1 +where v_row = row and v_col = col; +when 9 then +if v_i > 0 then +update sudoku_work set dig = 0 +where v_row = row and v_col = col; +set v_i = v_i - 1; +iterate sched; +else +select v_scounter as 'Solutions'; +leave more; +end if; +else +set v_dig = v_dig + 1; +update sudoku_work set dig = v_dig +where v_row = row and v_col = col; +end case; +set v_tcounter = v_tcounter + 1; +if not sudoku_digit_ok(v_row, v_col, v_dig) then +iterate sched; +end if; +set v_i = v_i + 1; +end; +end while sched; +select dig from sudoku_work; +select v_tcounter as 'Tests'; +set v_scounter = v_scounter + 1; +if p_all and v_i > 0 then +set v_i = v_i - 1; +else +leave more; +end if; +end; +end loop more; +end; +drop temporary table sudoku_work, sudoku_schedule; +end// +show procedure code sudoku_solve; +Pos Instruction +0 stmt 9 "drop temporary table if exists sudoku..." +1 stmt 1 "create temporary table sudoku_work ( ..." +2 stmt 1 "create temporary table sudoku_schedul..." +3 stmt 94 "call sudoku_init(" +4 jump_if_not 7(8) p_naive@0 +5 stmt 4 "update sudoku_work set cnt = 0 where ..." +6 jump 8 +7 stmt 94 "call sudoku_count(" +8 stmt 6 "insert into sudoku_schedule (row,col)..." +9 set v_scounter@2 0 +10 set v_i@3 1 +11 set v_dig@4 NULL +12 set v_schedmax@5 NULL +13 stmt 0 "select count(*) into v_schedmax from ..." +14 set v_tcounter@6 0 +15 jump_if_not 39(39) (v_i@3 <= v_schedmax@5) +16 set v_row@7 NULL +17 set v_col@8 NULL +18 stmt 0 "select row,col into v_row,v_col from ..." +19 stmt 0 "select dig into v_dig from sudoku_wor..." +20 set_case_expr 0 v_dig@4 +21 jump_if_not 25(34) (case_expr@0 = 0) +22 set v_dig@4 1 +23 stmt 4 "update sudoku_work set dig = 1 where ..." +24 jump 34 +25 jump_if_not 32(34) (case_expr@0 = 9) +26 jump_if_not 30(34) (v_i@3 > 0) +27 stmt 4 "update sudoku_work set dig = 0 where ..." +28 set v_i@3 (v_i@3 - 1) +29 jump 15 +30 stmt 0 "select v_scounter as 'Solutions'" +31 jump 45 +32 set v_dig@4 (v_dig@4 + 1) +33 stmt 4 "update sudoku_work set dig = v_dig wh..." +34 set v_tcounter@6 (v_tcounter@6 + 1) +35 jump_if_not 37(37) not(`test`.`sudoku_digit_ok`(v_row@7,v_col@8,v_dig@4)) +36 jump 15 +37 set v_i@3 (v_i@3 + 1) +38 jump 15 +39 stmt 0 "select dig from sudoku_work" +40 stmt 0 "select v_tcounter as 'Tests'" +41 set v_scounter@2 (v_scounter@2 + 1) +42 jump_if_not 45(14) (p_all@1 and (v_i@3 > 0)) +43 set v_i@3 (v_i@3 - 1) +44 jump 14 +45 stmt 9 "drop temporary table sudoku_work, sud..." +drop procedure sudoku_solve; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index d26f0029001..885b7827370 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1134,3 +1134,32 @@ show procedure status; Db Name Type Definer Modified Created Security_type Comment test bug15658 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER drop procedure ` bug15658`; +drop function if exists bug14270; +drop table if exists t1; +create table t1 (s1 int primary key); +create function bug14270() returns int +begin +load index into cache t1; +return 1; +end| +ERROR 0A000: Not allowed to return a result set from a function +create function bug14270() returns int +begin +cache index t1 key (`primary`) in keycache1; +return 1; +end| +ERROR 0A000: Not allowed to return a result set from a function +drop table t1; +drop procedure if exists bug15091; +create procedure bug15091() +begin +declare selectstr varchar(6000) default ' '; +declare conditionstr varchar(5000) default ''; +set selectstr = concat(selectstr, +' and ', +c.operatorid, +'in (',conditionstr, ')'); +end| +call bug15091(); +ERROR 42S02: Unknown table 'c' in field list +drop procedure bug15091; diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index b223c0cd487..ff729e87f97 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -291,3 +291,26 @@ drop user user1_bug14834@localhost; drop user user2_bug14834@localhost; drop user user3_bug14834@localhost; drop database db_bug14834; +create database db_bug14533; +use db_bug14533; +create table t1 (id int); +create user user_bug14533@localhost identified by ''; +create procedure bug14533_1() +sql security definer +desc db_bug14533.t1; +create procedure bug14533_2() +sql security definer +select * from db_bug14533.t1; +grant execute on procedure db_bug14533.bug14533_1 to user_bug14533@localhost; +grant execute on procedure db_bug14533.bug14533_2 to user_bug14533@localhost; +call db_bug14533.bug14533_1(); +Field Type Null Key Default Extra +id int(11) YES NULL +call db_bug14533.bug14533_2(); +id +desc db_bug14533.t1; +ERROR 42000: SELECT command denied to user 'user_bug14533'@'localhost' for table 't1' +select * from db_bug14533.t1; +ERROR 42000: SELECT command denied to user 'user_bug14533'@'localhost' for table 't1' +drop user user_bug14533@localhost; +drop database db_bug14533; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ea4420c8e70..761d4b83a39 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4425,4 +4425,23 @@ drop procedure if exists bug15231_1| drop procedure if exists bug15231_2| drop procedure if exists bug15231_3| drop procedure if exists bug15231_4| +drop procedure if exists bug15011| +create table t3 (c1 int primary key)| +insert into t3 values (1)| +create procedure bug15011() +deterministic +begin +declare continue handler for 1062 +select 'Outer' as 'Handler'; +begin +declare continue handler for 1062 +select 'Inner' as 'Handler'; +insert into t3 values (1); +end; +end| +call bug15011()| +Handler +Inner +drop procedure bug15011| +drop table t3| drop table t1,t2; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index d125f4451d8..62c0d01327d 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -785,3 +785,8 @@ create trigger test.t1_bi before insert on t1 for each row set @a:=0; ERROR 3D000: No database selected drop trigger t1_bi; ERROR 3D000: No database selected +create table t1 (i int); +create trigger t1_bi before insert on t1 for each row return 0; +ERROR 42000: RETURN is only allowed in a FUNCTION +insert into t1 values (1); +drop table t1; diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index 88106ae6956..2e1af51efa7 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -272,4 +272,11 @@ insert into t1 (f1) values ("2005-01-01"); insert into t1 (f1) values ("2005-02-01"); select date_format(f1, "%m") as d1, date_format(f1, "%M") as d2 from t1 order by date_format(f1, "%M"); drop table t1; + +# +# Bug #15828 +# +select str_to_date( 1, NULL ); +select str_to_date( NULL, 1 ); +select str_to_date( 1, IF(1=1,NULL,NULL) ); # End of 4.1 tests diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 627244daa6c..a6587aa6a13 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1237,6 +1237,7 @@ CREATE TABLE federated.t1 ( connection master; DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, PRIMARY KEY (`id`) diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test index 6644bc3ab43..0a26ea644f6 100644 --- a/mysql-test/t/sp-code.test +++ b/mysql-test/t/sp-code.test @@ -4,6 +4,11 @@ -- source include/is_debug_build.inc +--disable_warnings +drop procedure if exists empty; +drop procedure if exists code_sample; +--enable_warnings + create procedure empty() begin end; @@ -47,3 +52,141 @@ end// delimiter ;// show procedure code code_sample; drop procedure code_sample; + + +# +# BUG#15737: Stored procedure optimizer bug with LEAVE +# +# This is a much more extensive test case than is strictly needed, +# but it was kept as is for two reasons: +# - The bug occurs under some quite special circumstances, so it +# wasn't trivial to create a smaller test, +# - There's some value in having another more complex code sample +# in this test file. This might catch future code generation bugs +# that doesn't show in behaviour in any obvious way. + +--disable_warnings +drop procedure if exists sudoku_solve; +--enable_warnings + +delimiter //; +create procedure sudoku_solve(p_naive boolean, p_all boolean) + deterministic + modifies sql data +begin + drop temporary table if exists sudoku_work, sudoku_schedule; + + create temporary table sudoku_work + ( + row smallint not null, + col smallint not null, + dig smallint not null, + cnt smallint, + key using btree (cnt), + key using btree (row), + key using btree (col), + unique key using hash (row,col) + ); + + create temporary table sudoku_schedule + ( + idx int not null auto_increment primary key, + row smallint not null, + col smallint not null + ); + + call sudoku_init(); + + if p_naive then + update sudoku_work set cnt = 0 where dig = 0; + else + call sudoku_count(); + end if; + insert into sudoku_schedule (row,col) + select row,col from sudoku_work where cnt is not null order by cnt desc; + + begin + declare v_scounter bigint default 0; + declare v_i smallint default 1; + declare v_dig smallint; + declare v_schedmax smallint; + + select count(*) into v_schedmax from sudoku_schedule; + + more: + loop + begin + declare v_tcounter bigint default 0; + + sched: + while v_i <= v_schedmax do + begin + declare v_row, v_col smallint; + + select row,col into v_row,v_col from sudoku_schedule where v_i = idx; + + select dig into v_dig from sudoku_work + where v_row = row and v_col = col; + + case v_dig + when 0 then + set v_dig = 1; + update sudoku_work set dig = 1 + where v_row = row and v_col = col; + when 9 then + if v_i > 0 then + update sudoku_work set dig = 0 + where v_row = row and v_col = col; + set v_i = v_i - 1; + iterate sched; + else + select v_scounter as 'Solutions'; + leave more; + end if; + else + set v_dig = v_dig + 1; + update sudoku_work set dig = v_dig + where v_row = row and v_col = col; + end case; + + set v_tcounter = v_tcounter + 1; + if not sudoku_digit_ok(v_row, v_col, v_dig) then + iterate sched; + end if; + set v_i = v_i + 1; + end; + end while sched; + + select dig from sudoku_work; + select v_tcounter as 'Tests'; + set v_scounter = v_scounter + 1; + + if p_all and v_i > 0 then + set v_i = v_i - 1; + else + leave more; + end if; + end; + end loop more; + end; + + drop temporary table sudoku_work, sudoku_schedule; +end// +delimiter ;// + +# The interestings parts are where the code for the two "leave" are: +# ... +#| 26 | jump_if_not 30 (v_i@3 > 0) | +# ... +#| 30 | stmt 0 "select v_scounter as 'Solutions'" | +#| 31 | jump 45 | +# ... +#| 42 | jump_if_not 45 (p_all@1 and (v_i@3 > 0)) | +#| 43 | set v_i@3 (v_i@3 - 1) | +#| 44 | jump 14 | +#| 45 | stmt 9 "drop temporary table sudoku_work, sud..." | +#+-----+-----------------------------------------------------------------------+ +# The bug appeared at position 42 (with the wrong destination). +show procedure code sudoku_solve; + +drop procedure sudoku_solve; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index d7044bee632..63185ea9a88 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1621,6 +1621,66 @@ show procedure status; drop procedure ` bug15658`; +# +# BUG#14270: Stored procedures: crash if load index +# +--disable_warnings +drop function if exists bug14270; +drop table if exists t1; +--enable_warnings + +create table t1 (s1 int primary key); + +delimiter |; +--error ER_SP_NO_RETSET +create function bug14270() returns int +begin + load index into cache t1; + return 1; +end| + +--error ER_SP_NO_RETSET +create function bug14270() returns int +begin + cache index t1 key (`primary`) in keycache1; + return 1; +end| +delimiter ;| + +drop table t1; + + +# +# BUG#15091: Sp Returns Unknown error in order clause....and +# there is no order by clause +# +--disable_warnings +drop procedure if exists bug15091; +--enable_warnings + +delimiter |; +create procedure bug15091() +begin + declare selectstr varchar(6000) default ' '; + declare conditionstr varchar(5000) default ''; + + set selectstr = concat(selectstr, + ' and ', + c.operatorid, + 'in (',conditionstr, ')'); +end| +delimiter ;| + +# The error message used to be: +# ERROR 1109 (42S02): Unknown table 'c' in order clause +# but is now rephrased to something less misleading: +# ERROR 1109 (42S02): Unknown table 'c' in field list +--error ER_UNKNOWN_TABLE +call bug15091(); + +drop procedure bug15091; + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 223bc09b9fc..90160780618 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -487,4 +487,42 @@ drop user user2_bug14834@localhost; drop user user3_bug14834@localhost; drop database db_bug14834; + +# +# BUG#14533: 'desc tbl' in stored procedure causes error 1142 +# +create database db_bug14533; +use db_bug14533; +create table t1 (id int); +create user user_bug14533@localhost identified by ''; + +create procedure bug14533_1() + sql security definer + desc db_bug14533.t1; + +create procedure bug14533_2() + sql security definer + select * from db_bug14533.t1; + +grant execute on procedure db_bug14533.bug14533_1 to user_bug14533@localhost; +grant execute on procedure db_bug14533.bug14533_2 to user_bug14533@localhost; + +connect (user_bug14533,localhost,user_bug14533,,test); + +# These should work +call db_bug14533.bug14533_1(); +call db_bug14533.bug14533_2(); + +# For reference, these should not work +--error ER_TABLEACCESS_DENIED_ERROR +desc db_bug14533.t1; +--error ER_TABLEACCESS_DENIED_ERROR +select * from db_bug14533.t1; + +# Cleanup +connection default; +disconnect user_bug14533; +drop user user_bug14533@localhost; +drop database db_bug14533; + # End of 5.0 bugs. diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 02772313d01..74585a0d3b7 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5198,6 +5198,37 @@ drop procedure if exists bug15231_3| drop procedure if exists bug15231_4| +# +# BUG#15011: error handler in nested block not activated +# +--disable_warnings +drop procedure if exists bug15011| +--enable_warnings + +create table t3 (c1 int primary key)| + +insert into t3 values (1)| + +create procedure bug15011() + deterministic +begin + declare continue handler for 1062 + select 'Outer' as 'Handler'; + + begin + declare continue handler for 1062 + select 'Inner' as 'Handler'; + + insert into t3 values (1); + end; +end| + +call bug15011()| + +drop procedure bug15011| +drop table t3| + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test index dc863bd8e32..c0a12c3ecb5 100644 --- a/mysql-test/t/trigger-grant.test +++ b/mysql-test/t/trigger-grant.test @@ -362,9 +362,9 @@ CREATE TRIGGER trg5 BEFORE DELETE ON t1 FOR EACH ROW SET @a = 5; ---exec egrep -v '^definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG ---exec echo "definers='' '@' '@abc@def@@' '@hostname' '@abcdef@@@hostname'" >> $MYSQL_TEST_DIR/var/tmp/t1.TRG ---exec mv $MYSQL_TEST_DIR/var/tmp/t1.TRG $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG +--exec egrep -v '^definers=' $MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG > $MYSQLTEST_VARDIR/tmp/t1.TRG +--exec echo "definers='' '@' '@abc@def@@' '@hostname' '@abcdef@@@hostname'" >> $MYSQLTEST_VARDIR/tmp/t1.TRG +--exec mv $MYSQLTEST_VARDIR/tmp/t1.TRG $MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG --echo diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 492e37d9543..c3cc8e3f8e8 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -958,3 +958,12 @@ create trigger test.t1_bi before insert on t1 for each row set @a:=0; --error ER_NO_DB_ERROR drop trigger t1_bi; connection default; + +# Test for bug #16829 "Firing trigger with RETURN crashes the server" +# RETURN is not supposed to be used anywhere except functions, so error +# should be returned when one attempts to create trigger with RETURN. +create table t1 (i int); +--error ER_SP_BADRETURN +create trigger t1_bi before insert on t1 for each row return 0; +insert into t1 values (1); +drop table t1; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 112ce053648..2effe3a615c 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2967,9 +2967,9 @@ void Item_func_str_to_date::fix_length_and_dec() cached_field_type= MYSQL_TYPE_STRING; max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; cached_timestamp_type= MYSQL_TIMESTAMP_NONE; - if ((const_item= args[1]->const_item())) + format= args[1]->val_str(&format_str); + if (!args[1]->null_value && (const_item= args[1]->const_item())) { - format= args[1]->val_str(&format_str); cached_format_type= get_date_time_result_type(format->ptr(), format->length()); switch (cached_format_type) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e4e87eb5620..62de35cc109 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2026,6 +2026,15 @@ sp_head::show_create_function(THD *thd) 1) Mark used instructions 1.1) While doing this, shortcut jumps to jump instructions 2) Compact the code, removing unused instructions + + 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_shortcut_jump() Shortcut jumps to the final destination; + used by opt_mark(). + opt_move() Update moved instruction + set_destination() Set the new destination (jump instructions only) */ void sp_head::optimize() @@ -2718,12 +2727,6 @@ sp_instr_hpop::print(String *str) str->qs_append(m_count); } -void -sp_instr_hpop::backpatch(uint dest, sp_pcontext *dst_ctx) -{ - m_count= m_ctx->diff_handlers(dst_ctx); -} - /* sp_instr_hreturn class functions @@ -2845,12 +2848,6 @@ sp_instr_cpop::print(String *str) str->qs_append(m_count); } -void -sp_instr_cpop::backpatch(uint dest, sp_pcontext *dst_ctx) -{ - m_count= m_ctx->diff_cursors(dst_ctx); -} - /* sp_instr_copen class functions diff --git a/sql/sp_head.h b/sql/sp_head.h index c4b6cb36090..f9c37090322 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -460,17 +460,34 @@ public: virtual void backpatch(uint dest, sp_pcontext *dst_ctx) {} + /* + Mark this instruction as reachable during optimization and return the + index to the next instruction. Jump instruction will mark their + destination too recursively. + */ virtual uint opt_mark(sp_head *sp) { marked= 1; return m_ip+1; } + /* + Short-cut jumps to jumps during optimization. This is used by the + jump instructions' opt_mark() methods. 'start' is the starting point, + used to prevent the mark sweep from looping for ever. Return the + end destination. + */ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) { return m_ip; } + /* + Inform the instruction that it has been moved during optimization. + Most instructions will simply update its index, but jump instructions + must also take care of their destination pointers. Forward jumps get + pushed to the backpatch list 'ibp'. + */ virtual void opt_move(uint dst, List *ibp) { m_ip= dst; @@ -695,6 +712,9 @@ public: m_dest= dest; } + /* + Update the destination; used by the optimizer. + */ virtual void set_destination(uint old_dest, uint new_dest) { if (m_dest == old_dest) @@ -738,6 +758,7 @@ public: virtual uint opt_mark(sp_head *sp); + /* Override sp_instr_jump's shortcut; we stop here */ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) { return m_ip; @@ -821,6 +842,7 @@ public: virtual uint opt_mark(sp_head *sp); + /* Override sp_instr_jump's shortcut; we stop here. */ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) { return m_ip; @@ -858,15 +880,6 @@ public: virtual void print(String *str); - virtual void backpatch(uint dest, sp_pcontext *dst_ctx); - - virtual uint opt_mark(sp_head *sp) - { - if (m_count) - marked= 1; - return m_ip+1; - } - private: uint m_count; @@ -952,15 +965,6 @@ public: virtual void print(String *str); - virtual void backpatch(uint dest, sp_pcontext *dst_ctx); - - virtual uint opt_mark(sp_head *sp) - { - if (m_count) - marked= 1; - return m_ip+1; - } - private: uint m_count; diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 215de01e657..af4e41c29be 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -164,6 +164,33 @@ sp_rcontext::set_return_value(THD *thd, Item *return_value_item) #define IS_NOT_FOUND_CONDITION(S) ((S)[0] == '0' && (S)[1] == '2') #define IS_EXCEPTION_CONDITION(S) ((S)[0] != '0' || (S)[1] > '2') +/* + Find a handler for the given errno. + This is called from all error message functions (e.g. push_warning, + net_send_error, et al) when a sp_rcontext is in effect. If a handler + is found, no error is sent, and the the SP execution loop will instead + invoke the found handler. + This might be called several times before we get back to the execution + loop, so m_hfound can be >= 0 if a handler has already been found. + (In which case we don't search again - the first found handler will + be used.) + Handlers are pushed on the stack m_handler, with the latest/innermost + one on the top; we then search for matching handlers from the top and + down. + We search through all the handlers, looking for the most specific one + (sql_errno more specific than sqlstate more specific than the rest). + Note that mysql error code handlers is a MySQL extension, not part of + the standard. + + SYNOPSIS + sql_errno The error code + level Warning level + + RETURN + 1 if a handler was found, m_hfound is set to its index (>= 0) + 0 if not found, m_hfound is -1 +*/ + bool sp_rcontext::find_handler(uint sql_errno, MYSQL_ERROR::enum_warning_level level) @@ -174,11 +201,13 @@ sp_rcontext::find_handler(uint sql_errno, const char *sqlstate= mysql_errno_to_sqlstate(sql_errno); int i= m_hcount, found= -1; + /* Search handlers from the latest (innermost) to the oldest (outermost) */ while (i--) { sp_cond_type_t *cond= m_handler[i].cond; int j= m_ihsp; + /* Check active handlers, to avoid invoking one recursively */ while (j--) if (m_in_handler[j] == m_handler[i].handler) break; @@ -188,7 +217,8 @@ sp_rcontext::find_handler(uint sql_errno, switch (cond->type) { case sp_cond_type_t::number: - if (sql_errno == cond->mysqlerr) + if (sql_errno == cond->mysqlerr && + (found < 0 || m_handler[found].cond->type > sp_cond_type_t::number)) found= i; // Always the most specific break; case sp_cond_type_t::state: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cded92618ec..79651f2e49e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2361,7 +2361,7 @@ sp_proc_stmt_return: LEX *lex= Lex; sp_head *sp= lex->sphead; - if (sp->m_type == TYPE_ENUM_PROCEDURE) + if (sp->m_type != TYPE_ENUM_FUNCTION) { my_message(ER_SP_BADRETURN, ER(ER_SP_BADRETURN), MYF(0)); YYABORT; @@ -2450,17 +2450,16 @@ sp_proc_stmt_leave: } else { - uint ip= sp->instructions(); sp_instr_jump *i; - sp_instr_hpop *ih; - sp_instr_cpop *ic; + uint ip= sp->instructions(); + uint n; - ih= new sp_instr_hpop(ip++, ctx, 0); - sp->push_backpatch(ih, lab); - sp->add_instr(ih); - ic= new sp_instr_cpop(ip++, ctx, 0); - sp->push_backpatch(ic, lab); - sp->add_instr(ic); + n= ctx->diff_handlers(lab->ctx); + if (n) + sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); + n= ctx->diff_cursors(lab->ctx); + if (n) + sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); i= new sp_instr_jump(ip, ctx); sp->push_backpatch(i, lab); /* Jumping forward */ sp->add_instr(i); diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp index 41a705fea2d..e0324c2c8ea 100644 --- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp +++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp @@ -431,6 +431,7 @@ void AsyncFile::openReq(Request* request) m_fs.EXECUTE_DIRECT(block, GSN_FSWRITEREQ, signal, FsReadWriteReq::FixedLength + 1); + retry: Uint32 size = request->par.open.page_size; char* buf = (char*)m_page_ptr.p; while(size > 0){ @@ -457,7 +458,7 @@ void AsyncFile::openReq(Request* request) close(theFd); theFd = ::open(theFileName.c_str(), new_flags, mode); if (theFd != -1) - continue; + goto retry; } #endif close(theFd); diff --git a/win/cmakefiles/base b/win/cmakefiles/base index 6cc11a1e174..f8ac9969a26 100644 --- a/win/cmakefiles/base +++ b/win/cmakefiles/base @@ -6,6 +6,13 @@ EXEC_PROGRAM(cscript.exe win ARGS config-version.js OUT_VARIABLE out) SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D DBUG_OFF") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D DBUG_OFF") +IF(CMAKE_GENERATOR MATCHES "Visual Studio 8") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /wd4996") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4996") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /wd4996") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /wd4996") +ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8") + IF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR CMAKE_GENERATOR MATCHES "Visual Studio 8") # replace /MDd with /MTd STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG_INIT ${CMAKE_CXX_FLAGS_DEBUG_INIT}) diff --git a/win/cmakefiles/client b/win/cmakefiles/client index 711a5bf499b..7c0c6f2400b 100644 --- a/win/cmakefiles/client +++ b/win/cmakefiles/client @@ -2,7 +2,10 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") ADD_DEFINITIONS(-DUSE_TLS -DMYSQL_CLIENT) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/extra/yassl/include ${CMAKE_SOURCE_DIR}/libmysql) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/zlib + ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${CMAKE_SOURCE_DIR}/libmysql) ADD_LIBRARY(mysqlclient ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/bmove_upp.c ../mysys/charset-def.c ../mysys/charset.c @@ -38,10 +41,9 @@ ADD_LIBRARY(mysqlclient ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c - ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c - ${PROJECT_SOURCE_DIR}/include/mysql_version.h) + ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c) -ADD_DEPENDENCIES(mysqlclient comp_err) +ADD_DEPENDENCIES(mysqlclient GenError) ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc) LINK_DIRECTORIES(${MYSQL_BINARY_DIR}/mysys ${MYSQL_BINARY_DIR}/zlib) TARGET_LINK_LIBRARIES(mysql mysqlclient mysys yassl zlib dbug yassl taocrypt wsock32) diff --git a/win/cmakefiles/extra b/win/cmakefiles/extra index 5fedfcac2b9..40327eac0ad 100644 --- a/win/cmakefiles/extra +++ b/win/cmakefiles/extra @@ -6,4 +6,16 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) ADD_EXECUTABLE(comp_err comp_err.c) TARGET_LINK_LIBRARIES(comp_err dbug mysys strings wsock32) +GET_TARGET_PROPERTY(COMP_ERR_EXE comp_err LOCATION) + +ADD_CUSTOM_TARGET(GenError + ${COMP_ERR_EXE} --charset=${PROJECT_SOURCE_DIR}/sql/share/charsets + --out-dir=${PROJECT_SOURCE_DIR}/sql/share/ + --header_file=${PROJECT_SOURCE_DIR}/include/mysqld_error.h + --name_file=${PROJECT_SOURCE_DIR}/include/mysqld_ername.h + --state_file=${PROJECT_SOURCE_DIR}/include/sql_state.h + --in_file=${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt + DEPENDS comp_err ${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt) + + diff --git a/win/cmakefiles/sql b/win/cmakefiles/sql index 8361038bf4f..ee53436a1a6 100644 --- a/win/cmakefiles/sql +++ b/win/cmakefiles/sql @@ -1,7 +1,11 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR") -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/extra/yassl/include ${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex ${CMAKE_SOURCE_DIR}/zlib) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/zlib) SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/message.rc ${CMAKE_SOURCE_DIR}/sql/message.h @@ -46,6 +50,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc discover. ${PROJECT_SOURCE_DIR}/sql/handlerton.cc ${PROJECT_SOURCE_DIR}/sql/lex_hash.h) TARGET_LINK_LIBRARIES(mysqld heap myisam myisammrg innobase mysys yassl zlib dbug yassl taocrypt strings vio regex wsock32) +ADD_DEPENDENCIES(mysqld GenError) # Sql Parser custom command ADD_CUSTOM_COMMAND( @@ -82,30 +87,30 @@ ADD_CUSTOM_COMMAND( DEPENDS ${PROJECT_SOURCE_DIR}/sql/handlerton.cc.in) # Error file -GET_TARGET_PROPERTY(COMP_ERR_EXE comp_err LOCATION) -ADD_CUSTOM_COMMAND( - SOURCE ${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt - OUTPUT ${PROJECT_SOURCE_DIR}/include/mysqld_error.h - COMMAND ${COMP_ERR_EXE} - ARGS --charset=${PROJECT_SOURCE_DIR}/sql/share/charsets - --out-dir=${PROJECT_SOURCE_DIR}/sql/share/ - --header_file=${PROJECT_SOURCE_DIR}/include/mysqld_error.h - --name_file=${PROJECT_SOURCE_DIR}/include/mysqld_ername.h - --state_file=${PROJECT_SOURCE_DIR}/include/sql_state.h - --in_file=${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt - DEPENDS ${COMP_ERR_EXE} share/errmsg.txt) +#GET_TARGET_PROPERTY(COMP_ERR_EXE comp_err LOCATION) +#ADD_CUSTOM_COMMAND( + #SOURCE ${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt + #OUTPUT ${PROJECT_SOURCE_DIR}/include/mysqld_error.h + #COMMAND ${COMP_ERR_EXE} + #ARGS --charset=${PROJECT_SOURCE_DIR}/sql/share/charsets + # --out-dir=${PROJECT_SOURCE_DIR}/sql/share/ +## --header_file=${PROJECT_SOURCE_DIR}/include/mysqld_error.h +# --name_file=${PROJECT_SOURCE_DIR}/include/mysqld_ername.h +# --state_file=${PROJECT_SOURCE_DIR}/include/sql_state.h + # --in_file=${PROJECT_SOURCE_DIR}/sql/share/errmsg.txt + # DEPENDS ${COMP_ERR_EXE} share/errmsg.txt) -ADD_CUSTOM_COMMAND( - OUTPUT ${PROJECT_SOURCE_DIR}/include/mysqld_ername.h - COMMAND echo - DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_error.h -) +#ADD_CUSTOM_COMMAND( +# OUTPUT ${PROJECT_SOURCE_DIR}/include/mysqld_ername.h +# COMMAND echo +# DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_error.h +#) -ADD_CUSTOM_COMMAND( - OUTPUT ${PROJECT_SOURCE_DIR}/include/sql_state.h - COMMAND echo - DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_ername.h -) +#ADD_CUSTOM_COMMAND( +# OUTPUT ${PROJECT_SOURCE_DIR}/include/sql_state.h +# COMMAND echo +# DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_ername.h +#) # Gen_lex_hash