Loading mysql-test/extra/rpl_tests/rpl_insert_id.test +70 −0 Original line number Diff line number Diff line Loading @@ -86,3 +86,73 @@ INSERT INTO t1 VALUES (1),(1); sync_slave_with_master; # End of 4.1 tests # # BUG#15728: LAST_INSERT_ID function inside a stored function returns 0 # # The solution is not to reset last_insert_id on enter to sub-statement. # connection master; --disable_warnings drop function if exists bug15728; drop function if exists bug15728_insert; drop table if exists t1, t2; --enable_warnings create table t1 ( id int not null auto_increment, last_id int, primary key (id) ); create function bug15728() returns int(11) return last_insert_id(); insert into t1 (last_id) values (0); insert into t1 (last_id) values (last_insert_id()); insert into t1 (last_id) values (bug15728()); # Check that nested call replicates too. create table t2 ( id int not null auto_increment, last_id int, primary key (id) ); delimiter |; create function bug15728_insert() returns int(11) modifies sql data begin insert into t2 (last_id) values (bug15728()); return bug15728(); end| create trigger t1_bi before insert on t1 for each row begin declare res int; select bug15728_insert() into res; set NEW.last_id = res; end| delimiter ;| insert into t1 (last_id) values (0); drop trigger t1_bi; # Check that nested call doesn't affect outer context. select last_insert_id(); select bug15728_insert(); select last_insert_id(); insert into t1 (last_id) values (bug15728()); # This should be exactly one greater than in the previous call. select last_insert_id(); save_master_pos; connection slave; sync_with_master; select * from t1; select * from t2; connection master; drop function bug15728; drop function bug15728_insert; drop table t1, t2; # End of 5.0 tests sql/sql_yacc.yy +1 −97 Original line number Diff line number Diff line Loading @@ -365,7 +365,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token KEYS %token KEY_SYM %token KILL_SYM %token LABEL_SYM %token LANGUAGE_SYM %token LAST_INSERT_ID %token LAST_SYM Loading Loading @@ -893,7 +892,7 @@ END_OF_INPUT %type <NONE> sp_proc_stmt_statement sp_proc_stmt_return %type <NONE> sp_proc_stmt_if sp_proc_stmt_case_simple sp_proc_stmt_case %type <NONE> sp_labeled_control sp_proc_stmt_unlabeled sp_proc_stmt_leave %type <NONE> sp_proc_stmt_iterate sp_proc_stmt_label sp_proc_stmt_goto %type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close %type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list Loading Loading @@ -1554,8 +1553,6 @@ ev_sql_stmt_inner: | sp_proc_stmt_unlabeled | sp_proc_stmt_leave | sp_proc_stmt_iterate | sp_proc_stmt_label | sp_proc_stmt_goto | sp_proc_stmt_open | sp_proc_stmt_fetch | sp_proc_stmt_close Loading Loading @@ -2242,8 +2239,6 @@ sp_proc_stmt: | sp_proc_stmt_unlabeled | sp_proc_stmt_leave | sp_proc_stmt_iterate | sp_proc_stmt_label | sp_proc_stmt_goto | sp_proc_stmt_open | sp_proc_stmt_fetch | sp_proc_stmt_close Loading Loading @@ -2446,97 +2441,6 @@ sp_proc_stmt_iterate: } ; sp_proc_stmt_label: LABEL_SYM IDENT { #ifdef SP_GOTO LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; sp_label_t *lab= ctx->find_label($2.str); if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), $2.str); YYABORT; } else { lab= ctx->push_label($2.str, sp->instructions()); lab->type= SP_LAB_GOTO; lab->ctx= ctx; sp->backpatch(lab); } #else yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; #endif } ; sp_proc_stmt_goto: GOTO_SYM IDENT { #ifdef SP_GOTO LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; uint ip= lex->sphead->instructions(); sp_label_t *lab; sp_instr_jump *i; sp_instr_hpop *ih; sp_instr_cpop *ic; if (sp->m_in_handler) { my_message(ER_SP_GOTO_IN_HNDLR, ER(ER_SP_GOTO_IN_HNDLR), MYF(0)); YYABORT; } lab= ctx->find_label($2.str); if (! lab) { lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t)); lab->name= $2.str; lab->ip= 0; lab->type= SP_LAB_REF; lab->ctx= ctx; 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->add_instr(ic); sp->push_backpatch(ic, lab); i= new sp_instr_jump(ip, ctx); sp->push_backpatch(i, lab); /* Jumping forward */ sp->add_instr(i); } else { uint n; n= ctx->diff_handlers(lab->ctx); if (n) { ih= new sp_instr_hpop(ip++, ctx, n); sp->add_instr(ih); } n= ctx->diff_cursors(lab->ctx); if (n) { ic= new sp_instr_cpop(ip++, ctx, n); sp->add_instr(ic); } i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ sp->add_instr(i); } #else yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; #endif } ; sp_proc_stmt_open: OPEN_SYM ident { Loading Loading
mysql-test/extra/rpl_tests/rpl_insert_id.test +70 −0 Original line number Diff line number Diff line Loading @@ -86,3 +86,73 @@ INSERT INTO t1 VALUES (1),(1); sync_slave_with_master; # End of 4.1 tests # # BUG#15728: LAST_INSERT_ID function inside a stored function returns 0 # # The solution is not to reset last_insert_id on enter to sub-statement. # connection master; --disable_warnings drop function if exists bug15728; drop function if exists bug15728_insert; drop table if exists t1, t2; --enable_warnings create table t1 ( id int not null auto_increment, last_id int, primary key (id) ); create function bug15728() returns int(11) return last_insert_id(); insert into t1 (last_id) values (0); insert into t1 (last_id) values (last_insert_id()); insert into t1 (last_id) values (bug15728()); # Check that nested call replicates too. create table t2 ( id int not null auto_increment, last_id int, primary key (id) ); delimiter |; create function bug15728_insert() returns int(11) modifies sql data begin insert into t2 (last_id) values (bug15728()); return bug15728(); end| create trigger t1_bi before insert on t1 for each row begin declare res int; select bug15728_insert() into res; set NEW.last_id = res; end| delimiter ;| insert into t1 (last_id) values (0); drop trigger t1_bi; # Check that nested call doesn't affect outer context. select last_insert_id(); select bug15728_insert(); select last_insert_id(); insert into t1 (last_id) values (bug15728()); # This should be exactly one greater than in the previous call. select last_insert_id(); save_master_pos; connection slave; sync_with_master; select * from t1; select * from t2; connection master; drop function bug15728; drop function bug15728_insert; drop table t1, t2; # End of 5.0 tests
sql/sql_yacc.yy +1 −97 Original line number Diff line number Diff line Loading @@ -365,7 +365,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token KEYS %token KEY_SYM %token KILL_SYM %token LABEL_SYM %token LANGUAGE_SYM %token LAST_INSERT_ID %token LAST_SYM Loading Loading @@ -893,7 +892,7 @@ END_OF_INPUT %type <NONE> sp_proc_stmt_statement sp_proc_stmt_return %type <NONE> sp_proc_stmt_if sp_proc_stmt_case_simple sp_proc_stmt_case %type <NONE> sp_labeled_control sp_proc_stmt_unlabeled sp_proc_stmt_leave %type <NONE> sp_proc_stmt_iterate sp_proc_stmt_label sp_proc_stmt_goto %type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close %type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list Loading Loading @@ -1554,8 +1553,6 @@ ev_sql_stmt_inner: | sp_proc_stmt_unlabeled | sp_proc_stmt_leave | sp_proc_stmt_iterate | sp_proc_stmt_label | sp_proc_stmt_goto | sp_proc_stmt_open | sp_proc_stmt_fetch | sp_proc_stmt_close Loading Loading @@ -2242,8 +2239,6 @@ sp_proc_stmt: | sp_proc_stmt_unlabeled | sp_proc_stmt_leave | sp_proc_stmt_iterate | sp_proc_stmt_label | sp_proc_stmt_goto | sp_proc_stmt_open | sp_proc_stmt_fetch | sp_proc_stmt_close Loading Loading @@ -2446,97 +2441,6 @@ sp_proc_stmt_iterate: } ; sp_proc_stmt_label: LABEL_SYM IDENT { #ifdef SP_GOTO LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; sp_label_t *lab= ctx->find_label($2.str); if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), $2.str); YYABORT; } else { lab= ctx->push_label($2.str, sp->instructions()); lab->type= SP_LAB_GOTO; lab->ctx= ctx; sp->backpatch(lab); } #else yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; #endif } ; sp_proc_stmt_goto: GOTO_SYM IDENT { #ifdef SP_GOTO LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; uint ip= lex->sphead->instructions(); sp_label_t *lab; sp_instr_jump *i; sp_instr_hpop *ih; sp_instr_cpop *ic; if (sp->m_in_handler) { my_message(ER_SP_GOTO_IN_HNDLR, ER(ER_SP_GOTO_IN_HNDLR), MYF(0)); YYABORT; } lab= ctx->find_label($2.str); if (! lab) { lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t)); lab->name= $2.str; lab->ip= 0; lab->type= SP_LAB_REF; lab->ctx= ctx; 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->add_instr(ic); sp->push_backpatch(ic, lab); i= new sp_instr_jump(ip, ctx); sp->push_backpatch(i, lab); /* Jumping forward */ sp->add_instr(i); } else { uint n; n= ctx->diff_handlers(lab->ctx); if (n) { ih= new sp_instr_hpop(ip++, ctx, n); sp->add_instr(ih); } n= ctx->diff_cursors(lab->ctx); if (n) { ic= new sp_instr_cpop(ip++, ctx, n); sp->add_instr(ic); } i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ sp->add_instr(i); } #else yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; #endif } ; sp_proc_stmt_open: OPEN_SYM ident { Loading