From 898adb8cfc2e5d4bdf01ae9085f042a82f85c3f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Nov 2005 15:37:39 +0100 Subject: [PATCH 01/12] Fixed BUG#14498: Stored procedures: hang if undefined variable and exception The problem was to continue at the right place in the code after the test expression in a flow control statement fails with an exception (internally, the test in sp_instr_jump_if_not), and the exception is caught by a continue handler. Execution must then be resumed after the the entire flow control statement (END IF, END WHILE, etc). mysql-test/r/sp.result: New test case for BUG#14498. mysql-test/t/sp.test: New test case for BUG#14498. (Note that one call is disabled at the moment. Depends on BUG#14643.) sql/sp_head.cc: Added a continuation destination for sp_instr_jump_if_not, for the case when an error in the test expression causes a continue handler to catch. This includes new members in sp_instr_jump_if_not, adjustment of the optmizer (mark and move methods), and separate backpatching code (since we can't use the normal one for this). Also removed the class sp_instr_jump, since it's never used. ...and added some comments to the optimizer. sql/sp_head.h: Added a continuation destination for sp_instr_jump_if_not, for the case when an error in the test expression causes a continue handler to catch. This includes new members in sp_instr_jump_if_not, adjustment of the optmizer (mark and move methods), and separate backpatching code (since we can't use the normal one for this). Also removed the class sp_instr_jump, since it's never used. sql/sql_yacc.yy: Added backpatching of the continue destination for all conditional statements (using sp_instr_jump_if_not). --- mysql-test/r/sp.result | 84 +++++++++++++++++++++++++ mysql-test/t/sp.test | 86 +++++++++++++++++++++++++ sql/sp_head.cc | 140 ++++++++++++++++++++++------------------- sql/sp_head.h | 88 ++++++++++++++------------ sql/sql_yacc.yy | 20 +++++- 5 files changed, 308 insertions(+), 110 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 1f3f7dba7da..7a3d519ebb9 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3575,4 +3575,88 @@ DROP VIEW bug13095_v1 DROP PROCEDURE IF EXISTS bug13095; DROP VIEW IF EXISTS bug13095_v1; DROP TABLE IF EXISTS bug13095_t1; +drop procedure if exists bug14498_1| +drop procedure if exists bug14498_2| +drop procedure if exists bug14498_3| +drop procedure if exists bug14498_4| +drop procedure if exists bug14498_5| +create procedure bug14498_1() +begin +declare continue handler for sqlexception select 'error' as 'Handler'; +if v then +select 'yes' as 'v'; +else +select 'no' as 'v'; +end if; +select 'done' as 'End'; +end| +create procedure bug14498_2() +begin +declare continue handler for sqlexception select 'error' as 'Handler'; +while v do +select 'yes' as 'v'; +end while; +select 'done' as 'End'; +end| +create procedure bug14498_3() +begin +declare continue handler for sqlexception select 'error' as 'Handler'; +repeat +select 'maybe' as 'v'; +until v end repeat; +select 'done' as 'End'; +end| +create procedure bug14498_4() +begin +declare continue handler for sqlexception select 'error' as 'Handler'; +case v +when 1 then +select '1' as 'v'; +when 2 then +select '2' as 'v'; +else +select '?' as 'v'; +end case; +select 'done' as 'End'; +end| +create procedure bug14498_5() +begin +declare continue handler for sqlexception select 'error' as 'Handler'; +case +when v = 1 then +select '1' as 'v'; +when v = 2 then +select '2' as 'v'; +else +select '?' as 'v'; +end case; +select 'done' as 'End'; +end| +call bug14498_1()| +Handler +error +End +done +call bug14498_2()| +Handler +error +End +done +call bug14498_3()| +v +maybe +Handler +error +End +done +call bug14498_5()| +Handler +error +End +done +drop procedure bug14498_1| +drop procedure bug14498_2| +drop procedure bug14498_3| +drop procedure bug14498_4| +drop procedure bug14498_5| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ab57139bb77..19169273cba 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4489,6 +4489,92 @@ DROP TABLE IF EXISTS bug13095_t1; delimiter |; +# +# BUG#14498: Stored procedures: hang if undefined variable and exception +# +--disable_warnings +drop procedure if exists bug14498_1| +drop procedure if exists bug14498_2| +drop procedure if exists bug14498_3| +drop procedure if exists bug14498_4| +drop procedure if exists bug14498_5| +--enable_warnings + +create procedure bug14498_1() +begin + declare continue handler for sqlexception select 'error' as 'Handler'; + + if v then + select 'yes' as 'v'; + else + select 'no' as 'v'; + end if; + select 'done' as 'End'; +end| + +create procedure bug14498_2() +begin + declare continue handler for sqlexception select 'error' as 'Handler'; + + while v do + select 'yes' as 'v'; + end while; + select 'done' as 'End'; +end| + +create procedure bug14498_3() +begin + declare continue handler for sqlexception select 'error' as 'Handler'; + + repeat + select 'maybe' as 'v'; + until v end repeat; + select 'done' as 'End'; +end| + +create procedure bug14498_4() +begin + declare continue handler for sqlexception select 'error' as 'Handler'; + + case v + when 1 then + select '1' as 'v'; + when 2 then + select '2' as 'v'; + else + select '?' as 'v'; + end case; + select 'done' as 'End'; +end| + +create procedure bug14498_5() +begin + declare continue handler for sqlexception select 'error' as 'Handler'; + + case + when v = 1 then + select '1' as 'v'; + when v = 2 then + select '2' as 'v'; + else + select '?' as 'v'; + end case; + select 'done' as 'End'; +end| + +call bug14498_1()| +call bug14498_2()| +call bug14498_3()| +# QQ We can't call this at the moment, due to a known bug (BUG#14643) +#call bug14498_4()| +call bug14498_5()| + +drop procedure bug14498_1| +drop procedure bug14498_2| +drop procedure bug14498_3| +drop procedure bug14498_4| +drop procedure bug14498_5| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp_head.cc b/sql/sp_head.cc index abc66ce0b21..7d3a708a5a8 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -437,13 +437,14 @@ sp_head::operator delete(void *ptr, size_t size) sp_head::sp_head() :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), - m_flags(0), m_returns_cs(NULL) + m_flags(0), m_returns_cs(NULL), m_cont_level(0) { extern byte * sp_table_key(const byte *ptr, uint *plen, my_bool first); DBUG_ENTER("sp_head::sp_head"); m_backpatch.empty(); + m_cont_backpatch.empty(); m_lex.empty(); hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); @@ -1568,6 +1569,39 @@ sp_head::check_backpatch(THD *thd) return 0; } +void +sp_head::new_cont_backpatch(sp_instr_jump_if_not *i) +{ + m_cont_level+= 1; + if (i) + { + /* Use the cont. destination slot to store the level */ + i->m_cont_dest= m_cont_level; + (void)m_cont_backpatch.push_front(i); + } +} + +void +sp_head::add_cont_backpatch(sp_instr_jump_if_not *i) +{ + i->m_cont_dest= m_cont_level; + (void)m_cont_backpatch.push_front(i); +} + +void +sp_head::do_cont_backpatch() +{ + uint dest= instructions(); + uint lev= m_cont_level--; + sp_instr_jump_if_not *i; + + while ((i= m_cont_backpatch.head()) && i->m_cont_dest == lev) + { + i->m_cont_dest= dest; + (void)m_cont_backpatch.pop(); + } +} + void sp_head::set_info(char *definer, uint definerlen, longlong created, longlong modified, @@ -1782,7 +1816,10 @@ sp_head::show_create_function(THD *thd) /* - TODO: what does this do?? + Do some minimal optimization of the code: + 1) Mark used instructions + 1.1) While doing this, shortcut jumps to jump instructions + 2) Compact the code, removing unused instructions */ void sp_head::optimize() @@ -1805,7 +1842,7 @@ void sp_head::optimize() else { if (src != dst) - { + { // Move the instruction and update prev. jumps sp_instr *ibp; List_iterator_fast li(bp); @@ -1813,8 +1850,7 @@ void sp_head::optimize() while ((ibp= li++)) { sp_instr_jump *ji= static_cast(ibp); - if (ji->m_dest == src) - ji->m_dest= dst; + ji->set_destination(src, dst); } } i->opt_move(dst, &bp); @@ -2144,65 +2180,6 @@ sp_instr_jump::opt_move(uint dst, List *bp) } -/* - sp_instr_jump_if class functions -*/ - -int -sp_instr_jump_if::execute(THD *thd, uint *nextp) -{ - DBUG_ENTER("sp_instr_jump_if::execute"); - DBUG_PRINT("info", ("destination: %u", m_dest)); - DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this)); -} - -int -sp_instr_jump_if::exec_core(THD *thd, uint *nextp) -{ - Item *it; - int res; - - it= sp_prepare_func_item(thd, &m_expr); - if (!it) - res= -1; - else - { - res= 0; - if (it->val_bool()) - *nextp = m_dest; - else - *nextp = m_ip+1; - } - - return res; -} - -void -sp_instr_jump_if::print(String *str) -{ - str->reserve(12); - str->append("jump_if "); - str->qs_append(m_dest); - str->append(' '); - m_expr->print(str); -} - -uint -sp_instr_jump_if::opt_mark(sp_head *sp) -{ - sp_instr *i; - - marked= 1; - if ((i= sp->get_instr(m_dest))) - { - m_dest= i->opt_shortcut_jump(sp, this); - m_optdest= sp->get_instr(m_dest); - } - sp->opt_mark(m_dest); - return m_ip+1; -} - - /* sp_instr_jump_if_not class functions */ @@ -2224,7 +2201,10 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) it= sp_prepare_func_item(thd, &m_expr); if (! it) + { res= -1; + *nextp = m_cont_dest; + } else { res= 0; @@ -2241,10 +2221,12 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) void sp_instr_jump_if_not::print(String *str) { - str->reserve(16); + str->reserve(24); str->append("jump_if_not "); str->qs_append(m_dest); - str->append(' '); + str->append('('); + str->qs_append(m_cont_dest); + str->append(") "); m_expr->print(str); } @@ -2261,9 +2243,35 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp) m_optdest= sp->get_instr(m_dest); } sp->opt_mark(m_dest); + if ((i= sp->get_instr(m_cont_dest))) + { + m_cont_dest= i->opt_shortcut_jump(sp, this); + m_cont_optdest= sp->get_instr(m_cont_dest); + } + sp->opt_mark(m_cont_dest); return m_ip+1; } +void +sp_instr_jump_if_not::opt_move(uint dst, List *bp) +{ + /* + cont. destinations may point backwards after shortcutting jumps + during the mark phase. If it's still pointing forwards, only + push this for backpatching if sp_instr_jump::opt_move() will not + do it (i.e. if the m_dest points backwards). + */ + if (m_cont_dest > m_ip) + { // Forward + if (m_dest < m_ip) + bp->push_back(this); + } + else if (m_cont_optdest) + m_cont_dest= m_cont_optdest->m_ip; // Backward + /* This will take care of m_dest and m_ip */ + sp_instr_jump::opt_move(dst, bp); +} + /* sp_instr_freturn class functions diff --git a/sql/sp_head.h b/sql/sp_head.h index ed0f3987e01..e822ed96c02 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -38,6 +38,7 @@ sp_get_flags_for_command(LEX *lex); struct sp_label; class sp_instr; +class sp_instr_jump_if_not; struct sp_cond_type; struct sp_pvar; @@ -240,6 +241,18 @@ public: int check_backpatch(THD *thd); + // Start a new cont. backpatch level. If 'i' is NULL, the level is just incr. + void + new_cont_backpatch(sp_instr_jump_if_not *i); + + // Add an instruction to the current level + void + add_cont_backpatch(sp_instr_jump_if_not *i); + + // Backpatch (and pop) the current level to the current position. + void + do_cont_backpatch(); + char *name(uint *lenp = 0) const { if (lenp) @@ -309,6 +322,18 @@ private: sp_instr *instr; } bp_t; List m_backpatch; // Instructions needing backpatching + /* + We need a special list for backpatching of conditional jump's continue + destination (in the case of a continue handler catching an error in + the test), since it would otherwise interfere with the normal backpatch + mechanism - jump_if_not instructions have two different destination + which are to be patched differently. + Since these occur in a more restricted way (always the same "level" in + the code), we don't need the label. + */ + List m_cont_backpatch; + uint m_cont_level; // The current cont. backpatch level + /* Multi-set representing optimized list of tables to be locked by this routine. Does not include tables which are used by invoked routines. @@ -622,6 +647,12 @@ public: m_dest= dest; } + virtual void set_destination(uint old_dest, uint new_dest) + { + if (m_dest == old_dest) + m_dest= new_dest; + } + protected: sp_instr *m_optdest; // Used during optimization @@ -629,45 +660,6 @@ protected: }; // class sp_instr_jump : public sp_instr -class sp_instr_jump_if : public sp_instr_jump -{ - sp_instr_jump_if(const sp_instr_jump_if &); /* Prevent use of these */ - void operator=(sp_instr_jump_if &); - -public: - - sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, LEX *lex) - : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE) - {} - - sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) - : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE) - {} - - virtual ~sp_instr_jump_if() - {} - - virtual int execute(THD *thd, uint *nextp); - - virtual int exec_core(THD *thd, uint *nextp); - - virtual void print(String *str); - - virtual uint opt_mark(sp_head *sp); - - virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) - { - return m_ip; - } - -private: - - Item *m_expr; // The condition - sp_lex_keeper m_lex_keeper; - -}; // class sp_instr_jump_if : public sp_instr_jump - - class sp_instr_jump_if_not : public sp_instr_jump { sp_instr_jump_if_not(const sp_instr_jump_if_not &); /* Prevent use of these */ @@ -675,12 +667,16 @@ class sp_instr_jump_if_not : public sp_instr_jump public: + uint m_cont_dest; // Where continue handlers will go + sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex) - : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE) + : sp_instr_jump(ip, ctx), m_cont_dest(0), m_expr(i), + m_lex_keeper(lex, TRUE), m_cont_optdest(0) {} sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) - : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE) + : sp_instr_jump(ip, ctx, dest), m_cont_dest(0), m_expr(i), + m_lex_keeper(lex, TRUE), m_cont_optdest(0) {} virtual ~sp_instr_jump_if_not() @@ -699,10 +695,20 @@ public: return m_ip; } + virtual void opt_move(uint dst, List *ibp); + + virtual void set_destination(uint old_dest, uint new_dest) + { + sp_instr_jump::set_destination(old_dest, new_dest); + if (m_cont_dest == old_dest) + m_cont_dest= new_dest; + } + private: Item *m_expr; // The condition sp_lex_keeper m_lex_keeper; + sp_instr *m_cont_optdest; // Used during optimization }; // class sp_instr_jump_if_not : public sp_instr_jump diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 109dcd7e86a..a93ac1e7061 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2009,14 +2009,21 @@ sp_proc_stmt: } sp->restore_lex(YYTHD); } - | IF sp_if END IF {} + | IF + { Lex->sphead->new_cont_backpatch(NULL); } + sp_if END IF + { Lex->sphead->do_cont_backpatch(); } | CASE_SYM WHEN_SYM { Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE; + Lex->sphead->new_cont_backpatch(NULL); } - sp_case END CASE_SYM {} + sp_case END CASE_SYM { Lex->sphead->do_cont_backpatch(); } | CASE_SYM - { Lex->sphead->reset_lex(YYTHD); } + { + Lex->sphead->reset_lex(YYTHD); + Lex->sphead->new_cont_backpatch(NULL); + } expr WHEN_SYM { /* We "fake" this by using an anonymous variable which we @@ -2038,6 +2045,7 @@ sp_proc_stmt: sp_case END CASE_SYM { Lex->spcont->pop_pvar(); + Lex->sphead->do_cont_backpatch(); } | sp_labeled_control {} @@ -2306,6 +2314,7 @@ sp_if: $2, lex); sp->push_backpatch(i, ctx->push_label((char *)"", 0)); + sp->add_cont_backpatch(i); sp->add_instr(i); sp->restore_lex(YYTHD); } @@ -2360,6 +2369,7 @@ sp_case: lex->variables_used= 1; } sp->push_backpatch(i, ctx->push_label((char *)"", 0)); + sp->add_cont_backpatch(i); sp->add_instr(i); sp->restore_lex(YYTHD); } @@ -2489,6 +2499,7 @@ sp_unlabeled_control: /* Jumping forward */ sp->push_backpatch(i, lex->spcont->last_label()); + sp->new_cont_backpatch(i); sp->add_instr(i); sp->restore_lex(YYTHD); } @@ -2500,6 +2511,7 @@ sp_unlabeled_control: sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); lex->sphead->add_instr(i); + lex->sphead->do_cont_backpatch(); } | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM { Lex->sphead->reset_lex(YYTHD); } @@ -2513,6 +2525,8 @@ sp_unlabeled_control: lex); lex->sphead->add_instr(i); lex->sphead->restore_lex(YYTHD); + /* We can shortcut the cont_backpatch here */ + i->m_cont_dest= ip+1; } ; From 29915d6e1c71289fbae57aa7948e3453bf78485e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jan 2006 15:22:29 +0100 Subject: [PATCH 02/12] Post-review fix (BUG#14498). sql/sp_pcontext.h: Post-review fix. --- sql/sp_pcontext.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index bd2259cb6fb..2fd40159b6c 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -44,6 +44,15 @@ typedef struct sp_pvar #define SP_LAB_BEGIN 2 // Label at BEGIN #define SP_LAB_ITER 3 // Label at iteration control +/* + An SQL/PSM label. Can refer to the identifier used with the + "label_name:" construct which may precede some SQL/PSM statements, or + to an implicit implementation-dependent identifier which the parser + inserts before a high-level flow control statement such as + IF/WHILE/REPEAT/LOOP, when such statement is rewritten into + a combination of low-level jump/jump_if instructions and labels. +*/ + typedef struct sp_label { char *name; From c5216f4eee99fa429c9ce3cdf4e8704048847ee4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jan 2006 17:55:22 +0100 Subject: [PATCH 03/12] Post-merge fixes (BUG#14498) mysql-test/r/sp-code.result: Post-merge fix; updated result. mysql-test/t/sp.test: Post-merge fix; added comment (still can't call bug14498_4 test) --- mysql-test/r/sp-code.result | 2 +- mysql-test/t/sp.test | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index e6c4ffe1731..943471c2261 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -49,7 +49,7 @@ Pos Instruction 9 set err@1 1 10 hreturn 5 11 cfetch c@0 n@4 -12 jump_if_not 15 isnull(n@4) +12 jump_if_not 15(17) isnull(n@4) 13 set nulls@2 (nulls@2 + 1) 14 jump 17 15 set count@3 (count@3 + 1) diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 7b311088090..b5751c6da63 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5230,7 +5230,9 @@ end| call bug14498_1()| call bug14498_2()| call bug14498_3()| -# QQ We can't call this at the moment, due to a known bug (BUG#14643) +# We couldn't call this before, due to a known bug (BUG#14643) +# QQ We still can't since the new set_case_expr instruction breaks +# the semantics of case; it won't crash, but will get the wrong result. #call bug14498_4()| call bug14498_5()| From e1c4d6d8e5c75a5828e7fffe1d5f97e95b45cabd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jan 2006 22:31:13 +0300 Subject: [PATCH 04/12] A test case for Bug#7670 "Loss of precision for some integer values stored into DOUBLE column" (Can't repeat) mysql-test/r/type_decimal.result: Test results fixed (Bug#7670) mysql-test/t/type_decimal.test: A test case for Bug#7670 --- mysql-test/r/type_decimal.result | 13 +++++++++++++ mysql-test/t/type_decimal.test | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index d7f5f9fa328..df5abfe8ae3 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -772,3 +772,16 @@ productid zlevelprice 003trans 39.98 004trans 31.18 drop table t1, t2; +create table t1 (a double(53,0)); +insert into t1 values (9988317491112007680) ,(99883133042600208184115200); +select a from t1; +a +9988317491112007680 +99883133042600208184115200 +truncate t1; +insert into t1 values (9988317491112007680.0) ,(99883133042600208184115200.0); +select a from t1; +a +9988317491112007680 +99883133042600208184115200 +drop table t1; diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 1f6310cb819..e06b828f9e6 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -376,3 +376,16 @@ insert INTO t2 SELECT * FROM t1; select * from t2; drop table t1, t2; + +# +# A test case for Bug#7670 "Loss of precision for some integer values stored +# into DOUBLE column": check that there is no truncation +# when inserting big integers into double columns. +# +create table t1 (a double(53,0)); +insert into t1 values (9988317491112007680) ,(99883133042600208184115200); +select a from t1; +truncate t1; +insert into t1 values (9988317491112007680.0) ,(99883133042600208184115200.0); +select a from t1; +drop table t1; From 2337181f132d2f4a3e1ae68cd66722d6638b1a50 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Jan 2006 23:15:00 +0200 Subject: [PATCH 05/12] Changed condition similar to code in 4.1. --- sql/sql_handler.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index e9e1e79daaf..1cd7778a053 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -421,12 +421,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, if (!lock) goto err0; // mysql_lock_tables() printed error message already - if (cond && ((!cond->fixed && - cond->fix_fields(thd, &cond)) || cond->check_cols(1))) + if (cond) { if (table->query_id != thd->query_id) cond->cleanup(); // File was reopened - goto err0; + if ((!cond->fixed && + cond->fix_fields(thd, &cond)) || cond->check_cols(1)) + goto err0; } if (keyname) From 27f087b046d33e51cf67a870f8a53509c8743ac6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 00:28:00 +0300 Subject: [PATCH 06/12] A test case for Bug#6073 "ALTER TABLE minor glitch" (can't repeat) mysql-test/r/alter_table.result: Test results fixed (Bug#6073) mysql-test/t/alter_table.test: A test case for Bug#6073 --- mysql-test/r/alter_table.result | 4 ++++ mysql-test/t/alter_table.test | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index f224a10c9bd..5c50b3cd79d 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -562,3 +562,7 @@ desc t1; Field Type Null Key Default Extra mycol int(10) NO 0 drop table t1; +create table t1 (t varchar(255) default null, key t (t(80))) +engine=myisam default charset=latin1; +alter table t1 change t t text; +drop table t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index f4245abfe86..cfa6182543b 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -412,3 +412,13 @@ create table t1 (mycol int(10) not null); alter table t1 alter column mycol set default 0; desc t1; drop table t1; + +# +# Bug#6073 "ALTER table minor glich": ALTER TABLE complains that an index +# without # prefix is not allowed for TEXT columns, while index +# is defined with prefix. +# +create table t1 (t varchar(255) default null, key t (t(80))) +engine=myisam default charset=latin1; +alter table t1 change t t text; +drop table t1; From 17ccdd1a0582ea8dd864a9fa9f891d8c1b1c5002 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 01:03:03 +0300 Subject: [PATCH 07/12] A fix for Bug#13337 "ps test fails if configure wo/ usc2" mysql-test/r/ctype_ucs.result: Test results changed (Bug#13337) mysql-test/r/ps.result: Test results changed (Bug#13337) mysql-test/t/ctype_ucs.test: Fix Bug#13337 (move the test that uses UCS character set to ctype_ucs) mysql-test/t/ps.test: Fix Bug#13337 (move the test that uses UCS character set to ctype_ucs) --- mysql-test/r/ctype_ucs.result | 19 +++++++++++++++++++ mysql-test/r/ps.result | 19 ------------------- mysql-test/t/ctype_ucs.test | 14 ++++++++++++++ mysql-test/t/ps.test | 13 ------------- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 3ca56548de9..0e12ec88662 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -684,3 +684,22 @@ select f1 from t1 where f1 like 'a%'; f1 a drop table t1; +create table t1 (utext varchar(20) character set ucs2); +insert into t1 values ("lily"); +insert into t1 values ("river"); +prepare stmt from 'select utext from t1 where utext like ?'; +set @param1='%%'; +execute stmt using @param1; +utext +lily +river +execute stmt using @param1; +utext +lily +river +select utext from t1 where utext like '%%'; +utext +lily +river +drop table t1; +deallocate prepare stmt; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index aa9ff083cbb..ba9336c20bb 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -639,25 +639,6 @@ execute stmt using @a, @b; ?=? 1 deallocate prepare stmt; -create table t1 (utext varchar(20) character set ucs2); -insert into t1 values ("lily"); -insert into t1 values ("river"); -prepare stmt from 'select utext from t1 where utext like ?'; -set @param1='%%'; -execute stmt using @param1; -utext -lily -river -execute stmt using @param1; -utext -lily -river -select utext from t1 where utext like '%%'; -utext -lily -river -drop table t1; -deallocate prepare stmt; create table t1 (a int); prepare stmt from "select ??"; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 3b3c2c70f32..ed55287ca05 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -427,4 +427,18 @@ insert into t1 values('a'); create index t1f1 on t1(f1); select f1 from t1 where f1 like 'a%'; drop table t1; + +# +# Bug#9442 Set parameter make query fail if column character set is UCS2 +# +create table t1 (utext varchar(20) character set ucs2); +insert into t1 values ("lily"); +insert into t1 values ("river"); +prepare stmt from 'select utext from t1 where utext like ?'; +set @param1='%%'; +execute stmt using @param1; +execute stmt using @param1; +select utext from t1 where utext like '%%'; +drop table t1; +deallocate prepare stmt; # End of 4.1 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 23eb2e11ae3..b0755d06414 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -665,19 +665,6 @@ set @b='CHRISTINE'; execute stmt using @a, @b; deallocate prepare stmt; # -# Bug#9442 Set parameter make query fail if column character set is UCS2 -# -create table t1 (utext varchar(20) character set ucs2); -insert into t1 values ("lily"); -insert into t1 values ("river"); -prepare stmt from 'select utext from t1 where utext like ?'; -set @param1='%%'; -execute stmt using @param1; -execute stmt using @param1; -select utext from t1 where utext like '%%'; -drop table t1; -deallocate prepare stmt; -# # Bug#11299 "prepared statement makes wrong SQL syntax in binlog which stops # replication": check that errouneous queries with placeholders are not # allowed From 3d891d765dd9f684509367a1dd2309ccfc09ff75 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 01:22:01 +0300 Subject: [PATCH 08/12] A post-merge fix. --- mysql-test/t/ctype_ucs.test | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index f2f872af9d0..04de13f8228 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -429,20 +429,6 @@ insert into t1 values('a'); create index t1f1 on t1(f1); select f1 from t1 where f1 like 'a%'; drop table t1; - -# -# Bug#9442 Set parameter make query fail if column character set is UCS2 -# -create table t1 (utext varchar(20) character set ucs2); -insert into t1 values ("lily"); -insert into t1 values ("river"); -prepare stmt from 'select utext from t1 where utext like ?'; -set @param1='%%'; -execute stmt using @param1; -execute stmt using @param1; -select utext from t1 where utext like '%%'; -drop table t1; -deallocate prepare stmt; # End of 4.1 tests # From fbe2ba9fa85eae468c452c834705bdb69a31b079 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 12:48:48 +0100 Subject: [PATCH 09/12] Post-review fix. (BUG#15231) sql/sp_rcontext.cc: Post-review fix. --- sql/sp_rcontext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index c36c904f45d..215de01e657 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -220,7 +220,7 @@ sp_rcontext::find_handler(uint sql_errno, Only "exception conditions" are propagated to handlers in calling contexts. If no handler is found locally for a "completion condition" (warning or "not found") we will simply resume execution. - */ + */ if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) && level == MYSQL_ERROR::WARN_LEVEL_ERROR) return m_prev_runtime_ctx->find_handler(sql_errno, level); From 646d79050ce0e35cc4aa6de21d225b2004055ddf Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 16:48:26 +0100 Subject: [PATCH 10/12] Bug #14634 Running out of diskspace on tmpdir returns an inappropriate error sql/sql_select.cc: Backport from 5.0, catch the new errno that is returned --- sql/sql_select.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5e29c98e2c8..5c5216b8561 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5942,21 +5942,19 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) } if (table) { - int tmp; + int tmp, new_errno= 0; if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE))) { DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed")); - my_errno= tmp; - error= -1; + new_errno= tmp; } if ((tmp=table->file->ha_index_or_rnd_end())) { DBUG_PRINT("error",("ha_index_or_rnd_end() failed")); - my_errno= tmp; - error= -1; + new_errno= tmp; } - if (error == -1) - table->file->print_error(my_errno,MYF(0)); + if (new_errno) + table->file->print_error(new_errno,MYF(0)); } #ifndef DBUG_OFF if (error) From ac2c02f6fa70ec7af9b48ba10eec672e8f4e59a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 19:02:42 +0100 Subject: [PATCH 11/12] Fix for connection not being added to connection pool if "disable_abort_on_error" was used. client/mysqltest.c: If connection suceeded don't close it, just call handle_no_error which will check if an error was expected mysql-test/r/mysqltest.result: Update test result mysql-test/t/mysqltest.test: Add test for connection not being added to connection pool if "disable_abort_on_error" was used --- client/mysqltest.c | 13 +------------ mysql-test/r/mysqltest.result | 1 + mysql-test/t/mysqltest.test | 8 +++++++- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 6a2a7b072de..ca28419fa4f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2143,19 +2143,8 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, *create_conn= 0; goto err; } - else - { - handle_no_error(q); - /* - Fail if there was no error but we expected it. - We also don't want to have connection in this case. - */ - mysql_close(con); - *create_conn= 0; - error= 1; - goto err; - } + handle_no_error(q); /* TODO: change this to 0 in future versions, but the 'kill' test relies on diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 067054510c2..df530eda285 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -362,6 +362,7 @@ OK mysqltest: In included file "./var/tmp/con.sql": At line 7: Connection limit exhausted - increase MAX_CONS in mysqltest.c mysqltest: In included file "./var/tmp/con.sql": At line 3: connection 'test_con1' not found in connection pool mysqltest: In included file "./var/tmp/con.sql": At line 2: Connection test_con1 already exists +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); Output from mysqltest-x.inc Output from mysqltest-x.inc Output from mysqltest-x.inc diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 5cf49185c30..e6dc4d356c2 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -910,7 +910,13 @@ select "a" as col1, "c" as col2; --error 1 --exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1 - +# connect when "disable_abort_on_error" caused "connection not found" +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--disable_abort_on_error +connect (con1,localhost,root,,); +connection default; +connection con1; +--enable_abort_on_error # ---------------------------------------------------------------------------- # Test mysqltest arguments From 13f5fca9ba9e56f2e7aaa2d86c44551e8897fe01 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 21:10:47 +0300 Subject: [PATCH 12/12] Bug#15206: "Misleading message "No data to FETCH": reword the misleading message. mysql-test/r/sp-error.result: Test results fixed (Bug#15206) mysql-test/r/sp.result: Test results fixed (Bug#15206) mysql-test/r/type_decimal.result: Disable an unportable test case (Bug#7670) mysql-test/r/variables.result: Test results fixed (Bug#15206) mysql-test/r/view_grant.result: Test results fixed (Bug#15206) mysql-test/t/type_decimal.test: Remove an unportable (QNX) test case (Bug#7670). The test output depends on system-specific sprintf() implementation. The original complain was about erroneous conversion to long long, which was applied prior to conversion to double: but the expected behaviour can't be achieved until we have an own string -> double conversion function. --- mysql-test/r/sp-error.result | 2 +- mysql-test/r/sp.result | 16 ++++++++-------- mysql-test/r/type_decimal.result | 13 ------------- mysql-test/r/variables.result | 4 ++-- mysql-test/r/view_grant.result | 8 ++++---- mysql-test/t/type_decimal.test | 12 ------------ sql/share/errmsg.txt | 4 ++-- 7 files changed, 17 insertions(+), 42 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index d7bed7e88a7..9a148c3516e 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -535,7 +535,7 @@ fetch c into v; end| delete from t1| call bug7299()| -ERROR 02000: No data to FETCH +ERROR 02000: No data - zero rows fetched, selected, or processed drop procedure bug7299| create procedure bug9073() begin diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4c2f7b7f03b..19f3d033f53 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -522,7 +522,7 @@ delete from t1| create table t3 ( s char(16), d int)| call into_test4()| Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed select * from t3| s d into4 NULL @@ -1787,10 +1787,10 @@ end| call bug1863(10)| Warnings: Note 1051 Unknown table 'temp_t1' -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed call bug1863(10)| Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed select * from t4| f1 rc t3 2 0 NULL @@ -2084,10 +2084,10 @@ end| call bug4579_1()| call bug4579_1()| Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed call bug4579_1()| Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed drop procedure bug4579_1| drop procedure bug4579_2| drop table t3| @@ -2566,7 +2566,7 @@ call bug7743("OneWord")| var NULL Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed call bug7743("anotherword")| var 2 @@ -2574,7 +2574,7 @@ call bug7743("AnotherWord")| var NULL Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed drop procedure bug7743| drop table t4| delete from t3| @@ -4496,7 +4496,7 @@ After NOT FOUND condtition is triggered xid xdone 1 0 Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed call bug15231_3()| Result Missed it (correct) diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index df5abfe8ae3..d7f5f9fa328 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -772,16 +772,3 @@ productid zlevelprice 003trans 39.98 004trans 31.18 drop table t1, t2; -create table t1 (a double(53,0)); -insert into t1 values (9988317491112007680) ,(99883133042600208184115200); -select a from t1; -a -9988317491112007680 -99883133042600208184115200 -truncate t1; -insert into t1 values (9988317491112007680.0) ,(99883133042600208184115200.0); -select a from t1; -a -9988317491112007680 -99883133042600208184115200 -drop table t1; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index df180218a09..4f6a6569443 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -537,10 +537,10 @@ select @@query_prealloc_size = @test; create table t1 (a int); select a into @x from t1; Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed show warnings; Level Code Message -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed drop table t1; set @@warning_count=1; ERROR HY000: Variable 'warning_count' is a read only variable diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index e2ee02351d7..ede69343a29 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -348,12 +348,12 @@ select * from v1; f2() NULL Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed select * from v2; f2() NULL Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed select * from v3; ERROR HY000: View 'mysqltest.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them select * from v4; @@ -394,12 +394,12 @@ select * from v3; f2() NULL Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed select * from v4; f2() NULL Warnings: -Warning 1329 No data to FETCH +Warning 1329 No data - zero rows fetched, selected, or processed select * from v5; ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v1, v2, v3, v4, v5; diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index e06b828f9e6..07347322453 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -377,15 +377,3 @@ insert INTO t2 SELECT * FROM t1; select * from t2; drop table t1, t2; -# -# A test case for Bug#7670 "Loss of precision for some integer values stored -# into DOUBLE column": check that there is no truncation -# when inserting big integers into double columns. -# -create table t1 (a double(53,0)); -insert into t1 values (9988317491112007680) ,(99883133042600208184115200); -select a from t1; -truncate t1; -insert into t1 values (9988317491112007680.0) ,(99883133042600208184115200.0); -select a from t1; -drop table t1; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 185b4326c5c..577173a36a1 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5175,8 +5175,8 @@ ER_SP_WRONG_NO_OF_FETCH_ARGS eng "Incorrect number of FETCH variables" ger "Falsche Anzahl von FETCH-Variablen" ER_SP_FETCH_NO_DATA 02000 - eng "No data to FETCH" - ger "Keine Daten mit FETCH abzuholen" + eng "No data - zero rows fetched, selected, or processed" + ger "Keine Daten - null Zeilen geholt (fetch), ausgewählt oder verarbeitet" ER_SP_DUP_PARAM 42000 eng "Duplicate parameter: %s" ger "Doppelter Parameter: %s"