diff options
author | unknown <ramil@mysql.com> | 2006-02-07 12:06:06 +0400 |
---|---|---|
committer | unknown <ramil@mysql.com> | 2006-02-07 12:06:06 +0400 |
commit | 79112423afaed3c4ead9542fe53e1650aacaa15b (patch) | |
tree | 747099b88908fa6cd29fc55c930fa13a07cc00c4 | |
parent | e071d7aa8793cadd6c455bc2a002de8820f586e8 (diff) | |
parent | 2ba25676d7d835d53f591b8d8eb4cde84445b313 (diff) | |
download | mariadb-git-79112423afaed3c4ead9542fe53e1650aacaa15b.tar.gz |
Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/usr/home/ram/work/5.0.b16511
-rw-r--r-- | mysql-test/r/group_min_max.result | 27 | ||||
-rw-r--r-- | mysql-test/r/sp-code.result | 2 | ||||
-rw-r--r-- | mysql-test/r/sp-destruct.result | 8 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 7 | ||||
-rw-r--r-- | mysql-test/t/group_min_max.test | 21 | ||||
-rw-r--r-- | mysql-test/t/sp-destruct.test | 11 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 5 | ||||
-rw-r--r-- | sql/opt_range.cc | 1 | ||||
-rw-r--r-- | sql/sp.cc | 53 | ||||
-rw-r--r-- | sql/sp.h | 5 | ||||
-rw-r--r-- | sql/sp_head.cc | 85 | ||||
-rw-r--r-- | sql/sp_head.h | 96 | ||||
-rw-r--r-- | sql/sql_acl.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 20 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 17 |
15 files changed, 273 insertions, 87 deletions
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 91579a7ea42..b1703c51f4e 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2043,3 +2043,30 @@ c1 c2 30 8 30 9 drop table t1; +CREATE TABLE t1 (a varchar(5), b int(11), PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES ('AA',1), ('AA',2), ('AA',3), ('BB',1), ('AA',4); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SELECT a FROM t1 WHERE a='AA' GROUP BY a; +a +AA +SELECT a FROM t1 WHERE a='BB' GROUP BY a; +a +BB +EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 3 Using where; Using index +EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 1 Using where; Using index +SELECT DISTINCT a FROM t1 WHERE a='BB'; +a +BB +SELECT DISTINCT a FROM t1 WHERE a LIKE 'B%'; +a +BB +SELECT a FROM t1 WHERE a LIKE 'B%' GROUP BY a; +a +BB +DROP TABLE t1; diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index c9fe170dda6..8bdb9a724d7 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -172,7 +172,7 @@ Pos Instruction 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 +20 set_case_expr (34) 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 ..." diff --git a/mysql-test/r/sp-destruct.result b/mysql-test/r/sp-destruct.result index 1b720be9403..4df8086c84e 100644 --- a/mysql-test/r/sp-destruct.result +++ b/mysql-test/r/sp-destruct.result @@ -72,6 +72,12 @@ drop trigger t1_ai; create trigger t1_ai after insert on t1 for each row call bug14233_3(); insert into t1 values (0); ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) -delete from mysql.proc where name like 'bug14233%'; drop trigger t1_ai; drop table t1; +drop function bug14233_1; +drop function bug14233_2; +drop procedure bug14233_3; +show procedure status; +Db Name Type Definer Modified Created Security_type Comment +show function status; +Db Name Type Definer Modified Created Security_type Comment diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 90020573df3..bec2f049bc4 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4089,8 +4089,6 @@ NULL 1 call bug14643_2()| Handler boo -2 -2 Handler boo drop procedure bug14643_1| @@ -4432,6 +4430,11 @@ Handler error End done +call bug14498_4()| +Handler +error +End +done call bug14498_5()| Handler error diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index e15ef92116c..8dc55532bbf 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -715,3 +715,24 @@ select distinct c1, c2 from t1 order by c2; select c1,min(c2) as c2 from t1 group by c1 order by c2; select c1,c2 from t1 group by c1,c2 order by c2; drop table t1; + +# +# Bug #16203: Analysis for possible min/max optimization erroneously +# returns impossible range +# + +CREATE TABLE t1 (a varchar(5), b int(11), PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES ('AA',1), ('AA',2), ('AA',3), ('BB',1), ('AA',4); +OPTIMIZE TABLE t1; + +SELECT a FROM t1 WHERE a='AA' GROUP BY a; +SELECT a FROM t1 WHERE a='BB' GROUP BY a; + +EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a; +EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a; + +SELECT DISTINCT a FROM t1 WHERE a='BB'; +SELECT DISTINCT a FROM t1 WHERE a LIKE 'B%'; +SELECT a FROM t1 WHERE a LIKE 'B%' GROUP BY a; + +DROP TABLE t1; diff --git a/mysql-test/t/sp-destruct.test b/mysql-test/t/sp-destruct.test index ac74a1be9b0..fb368a1e621 100644 --- a/mysql-test/t/sp-destruct.test +++ b/mysql-test/t/sp-destruct.test @@ -119,6 +119,15 @@ create trigger t1_ai after insert on t1 for each row call bug14233_3(); insert into t1 values (0); # Clean-up -delete from mysql.proc where name like 'bug14233%'; drop trigger t1_ai; drop table t1; + +# +# BUG#16303: erroneus stored procedures and functions should be droppable +# +drop function bug14233_1; +drop function bug14233_2; +drop procedure bug14233_3; +# Assert: These should show nothing. +show procedure status; +show function status; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 32299ad7e0b..53c15ffd05b 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5210,10 +5210,7 @@ end| call bug14498_1()| call bug14498_2()| call bug14498_3()| -# 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_4()| call bug14498_5()| drop procedure bug14498_1| diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7c4f5fbe218..1b712700b18 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7780,6 +7780,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, quick_prefix_selectivity= (double) quick_prefix_records / (double) table_records; num_groups= (uint) rint(num_groups * quick_prefix_selectivity); + set_if_bigger(num_groups, 1); } if (used_key_parts > group_key_parts) diff --git a/sql/sp.cc b/sql/sp.cc index 37a9c02124e..fe249141fea 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1002,22 +1002,26 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, } +/* + This is used by sql_acl.cc:mysql_routine_grant() and is used to find + the routines in 'routines'. +*/ int -sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error) +sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any, bool no_error) { - TABLE_LIST *table; + TABLE_LIST *routine; bool result= 0; DBUG_ENTER("sp_exists_routine"); - for (table= tables; table; table= table->next_global) + for (routine= routines; routine; routine= routine->next_global) { sp_name *name; LEX_STRING lex_db; LEX_STRING lex_name; - lex_db.length= strlen(table->db); - lex_name.length= strlen(table->table_name); - lex_db.str= thd->strmake(table->db, lex_db.length); - lex_name.str= thd->strmake(table->table_name, lex_name.length); + lex_db.length= strlen(routine->db); + lex_name.length= strlen(routine->table_name); + lex_db.str= thd->strmake(routine->db, lex_db.length); + lex_name.str= thd->strmake(routine->table_name, lex_name.length); name= new sp_name(lex_db, lex_name); name->init_qname(thd); if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, @@ -1034,7 +1038,7 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error) if (!no_error) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE", - table->table_name); + routine->table_name); DBUG_RETURN(-1); } DBUG_RETURN(0); @@ -1044,6 +1048,39 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error) } +/* + Check if a routine exists in the mysql.proc table, without actually + parsing the definition. (Used for dropping) + + SYNOPSIS + sp_routine_exists_in_table() + thd - thread context + name - name of procedure + + RETURN VALUE + 0 - Success + non-0 - Error; SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND +*/ + +int +sp_routine_exists_in_table(THD *thd, int type, sp_name *name) +{ + TABLE *table; + int ret; + Open_tables_state open_tables_state_backup; + + if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup))) + ret= SP_OPEN_TABLE_FAILED; + else + { + if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK) + ret= SP_KEY_NOT_FOUND; + close_proc_table(thd, &open_tables_state_backup); + } + return ret; +} + + int sp_create_procedure(THD *thd, sp_head *sp) { @@ -40,7 +40,10 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, bool cache_only); int -sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error); +sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any, bool no_error); + +int +sp_routine_exists_in_table(THD *thd, int type, sp_name *name); int sp_create_procedure(THD *thd, sp_head *sp); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 173c35328b1..27dc0103335 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1761,7 +1761,7 @@ sp_head::fill_field_definition(THD *thd, LEX *lex, void -sp_head::new_cont_backpatch(sp_instr_jump_if_not *i) +sp_head::new_cont_backpatch(sp_instr_opt_meta *i) { m_cont_level+= 1; if (i) @@ -1773,7 +1773,7 @@ sp_head::new_cont_backpatch(sp_instr_jump_if_not *i) } void -sp_head::add_cont_backpatch(sp_instr_jump_if_not *i) +sp_head::add_cont_backpatch(sp_instr_opt_meta *i) { i->m_cont_dest= m_cont_level; (void)m_cont_backpatch.push_front(i); @@ -1784,7 +1784,7 @@ sp_head::do_cont_backpatch() { uint dest= instructions(); uint lev= m_cont_level--; - sp_instr_jump_if_not *i; + sp_instr_opt_meta *i; while ((i= m_cont_backpatch.head()) && i->m_cont_dest == lev) { @@ -2048,10 +2048,10 @@ void sp_head::optimize() set_dynamic(&m_instr, (gptr)&i, dst); while ((ibp= li++)) - { - sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp); - ji->set_destination(src, dst); - } + { + sp_instr_opt_meta *im= static_cast<sp_instr_opt_meta *>(ibp); + im->set_destination(src, dst); + } } i->opt_move(dst, &bp); src+= 1; @@ -2073,6 +2073,10 @@ sp_head::opt_mark(uint ip) #ifndef DBUG_OFF +/* + Return the routine instructions as a result set. + Returns 0 if ok, !=0 on error. +*/ int sp_head::show_routine_code(THD *thd) { @@ -2100,6 +2104,22 @@ sp_head::show_routine_code(THD *thd) for (ip= 0; (i = get_instr(ip)) ; ip++) { + /* + Consistency check. If these are different something went wrong + during optimization. + */ + if (ip != i->m_ip) + { + const char *format= "Instruction at position %u has m_ip=%u"; + char tmp[sizeof(format) + 2*SP_INSTR_UINT_MAXLEN + 1]; + + sprintf(tmp, format, ip, i->m_ip); + /* + Since this is for debugging purposes only, we don't bother to + introduce a special error code for it. + */ + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, tmp); + } protocol->prepare_for_resend(); protocol->store((longlong)ip); @@ -2524,14 +2544,14 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) void sp_instr_jump_if_not::print(String *str) { - /* jump_if_not dest ... */ + /* jump_if_not dest(cont) ... */ if (str->reserve(2*SP_INSTR_UINT_MAXLEN+14+32)) // Add some for the expr. too return; str->qs_append(STRING_WITH_LEN("jump_if_not ")); str->qs_append(m_dest); - str->append('('); + str->qs_append('('); str->qs_append(m_cont_dest); - str->append(") "); + str->qs_append(STRING_WITH_LEN(") ")); m_expr->print(str); } @@ -3077,30 +3097,53 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) spcont->clear_handler(); thd->spcont= spcont; } + *nextp= m_cont_dest; /* For continue handler */ } + else + *nextp= m_ip+1; - *nextp = m_ip+1; - - return res; /* no error */ + return res; } void sp_instr_set_case_expr::print(String *str) { - const char CASE_EXPR_TAG[]= "set_case_expr "; - const int CASE_EXPR_TAG_LEN= sizeof(CASE_EXPR_TAG) - 1; - const int INT_STRING_MAX_LEN= 10; - - /* We must call reserve(), because qs_append() doesn't care about memory. */ - str->reserve(CASE_EXPR_TAG_LEN + INT_STRING_MAX_LEN + 2); - - str->qs_append(CASE_EXPR_TAG, CASE_EXPR_TAG_LEN); + /* set_case_expr (cont) id ... */ + str->reserve(2*SP_INSTR_UINT_MAXLEN+18+32); // Add some extra for expr too + str->qs_append(STRING_WITH_LEN("set_case_expr (")); + str->qs_append(m_cont_dest); + str->qs_append(STRING_WITH_LEN(") ")); str->qs_append(m_case_expr_id); str->qs_append(' '); m_case_expr->print(str); } +uint +sp_instr_set_case_expr::opt_mark(sp_head *sp) +{ + sp_instr *i; + + marked= 1; + 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_set_case_expr::opt_move(uint dst, List<sp_instr> *bp) +{ + if (m_cont_dest > m_ip) + bp->push_back(this); // Forward + else if (m_cont_optdest) + m_cont_dest= m_cont_optdest->m_ip; // Backward + m_ip= dst; +} + /* ------------------------------------------------------------------ */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 89e86badc09..a4dd68ee4a3 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -41,6 +41,7 @@ sp_get_flags_for_command(LEX *lex); struct sp_label; class sp_instr; +class sp_instr_opt_meta; class sp_instr_jump_if_not; struct sp_cond_type; struct sp_pvar; @@ -271,11 +272,11 @@ public: // 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); + new_cont_backpatch(sp_instr_opt_meta *i); // Add an instruction to the current level void - add_cont_backpatch(sp_instr_jump_if_not *i); + add_cont_backpatch(sp_instr_opt_meta *i); // Backpatch (and pop) the current level to the current position. void @@ -372,15 +373,15 @@ private: } bp_t; List<bp_t> m_backpatch; // Instructions needing backpatching /* - We need a special list for backpatching of conditional jump's continue + We need a special list for backpatching of instructions with a 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 + mechanism - e.g. jump_if_not instructions have two different destinations 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<sp_instr_jump_if_not> m_cont_backpatch; + List<sp_instr_opt_meta> m_cont_backpatch; uint m_cont_level; // The current cont. backpatch level /* @@ -677,21 +678,55 @@ private: }; // class sp_instr_trigger_field : public sp_instr -class sp_instr_jump : public sp_instr +/* + An abstract class for all instructions with destinations that + needs to be updated by the optimizer. + Even if not all subclasses will use both the normal destination and + the continuation destination, we put them both here for simplicity. + */ +class sp_instr_opt_meta : public sp_instr +{ +public: + + uint m_dest; // Where we will go + uint m_cont_dest; // Where continue handlers will go + + sp_instr_opt_meta(uint ip, sp_pcontext *ctx) + : sp_instr(ip, ctx), + m_dest(0), m_cont_dest(0), m_optdest(0), m_cont_optdest(0) + {} + + sp_instr_opt_meta(uint ip, sp_pcontext *ctx, uint dest) + : sp_instr(ip, ctx), + m_dest(dest), m_cont_dest(0), m_optdest(0), m_cont_optdest(0) + {} + + virtual ~sp_instr_opt_meta() + {} + + virtual void set_destination(uint old_dest, uint new_dest) + = 0; + +protected: + + sp_instr *m_optdest; // Used during optimization + sp_instr *m_cont_optdest; // Used during optimization + +}; // class sp_instr_opt_meta : public sp_instr + +class sp_instr_jump : public sp_instr_opt_meta { sp_instr_jump(const sp_instr_jump &); /* Prevent use of these */ void operator=(sp_instr_jump &); public: - uint m_dest; // Where we will go - sp_instr_jump(uint ip, sp_pcontext *ctx) - : sp_instr(ip, ctx), m_dest(0), m_optdest(0) + : sp_instr_opt_meta(ip, ctx) {} sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest) - : sp_instr(ip, ctx), m_dest(dest), m_optdest(0) + : sp_instr_opt_meta(ip, ctx, dest) {} virtual ~sp_instr_jump() @@ -722,11 +757,7 @@ public: m_dest= new_dest; } -protected: - - sp_instr *m_optdest; // Used during optimization - -}; // class sp_instr_jump : public sp_instr +}; // class sp_instr_jump : public sp_instr_opt_meta class sp_instr_jump_if_not : public sp_instr_jump @@ -736,16 +767,14 @@ 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_cont_dest(0), m_expr(i), - m_lex_keeper(lex, TRUE), m_cont_optdest(0) + : sp_instr_jump(ip, ctx), m_expr(i), + m_lex_keeper(lex, TRUE) {} sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) - : sp_instr_jump(ip, ctx, dest), m_cont_dest(0), m_expr(i), - m_lex_keeper(lex, TRUE), m_cont_optdest(0) + : sp_instr_jump(ip, ctx, dest), m_expr(i), + m_lex_keeper(lex, TRUE) {} virtual ~sp_instr_jump_if_not() @@ -778,7 +807,6 @@ 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 @@ -912,7 +940,7 @@ private: uint m_frame; -}; // class sp_instr_hreturn : public sp_instr +}; // class sp_instr_hreturn : public sp_instr_jump /* This is DECLARE CURSOR */ @@ -1089,14 +1117,18 @@ private: }; // class sp_instr_error : public sp_instr -class sp_instr_set_case_expr :public sp_instr +class sp_instr_set_case_expr : public sp_instr_opt_meta { public: sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id, Item *case_expr, LEX *lex) - :sp_instr(ip, ctx), m_case_expr_id(case_expr_id), m_case_expr(case_expr), - m_lex_keeper(lex, TRUE) + : sp_instr_opt_meta(ip, ctx), + m_case_expr_id(case_expr_id), m_case_expr(case_expr), + m_lex_keeper(lex, TRUE) + {} + + virtual ~sp_instr_set_case_expr() {} virtual int execute(THD *thd, uint *nextp); @@ -1105,13 +1137,23 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp); + + virtual void opt_move(uint dst, List<sp_instr> *ibp); + + virtual void set_destination(uint old_dest, uint new_dest) + { + if (m_cont_dest == old_dest) + m_cont_dest= new_dest; + } + private: uint m_case_expr_id; Item *m_case_expr; sp_lex_keeper m_lex_keeper; -}; // class sp_instr_set_case_expr : public sp_instr +}; // class sp_instr_set_case_expr : public sp_instr_opt_meta #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7bc5aac270b..c67ce383398 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3030,7 +3030,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (!revoke_grant) { - if (sp_exists_routine(thd, table_list, is_proc, no_error)<0) + if (sp_exist_routines(thd, table_list, is_proc, no_error)<0) DBUG_RETURN(TRUE); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1cbc616f63f..978cab704c0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4445,21 +4445,17 @@ end_with_restore_list: case SQLCOM_DROP_PROCEDURE: case SQLCOM_DROP_FUNCTION: { - sp_head *sp; int result; - char *db, *name; + int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ? + TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION); - if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, - &thd->sp_proc_cache, FALSE); - else - sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, - &thd->sp_func_cache, FALSE); + result= sp_routine_exists_in_table(thd, type, lex->spname); mysql_reset_errors(thd, 0); - if (sp) + if (result == SP_OK) { - db= thd->strdup(sp->m_db.str); - name= thd->strdup(sp->m_name.str); + char *db= lex->spname->m_db.str; + char *name= lex->spname->m_name.str; + if (check_routine_access(thd, ALTER_PROC_ACL, db, name, lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) goto error; @@ -4599,7 +4595,7 @@ end_with_restore_list: else sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, &thd->sp_func_cache, FALSE); - if (!sp || !sp->show_routine_code(thd)) + if (!sp || sp->show_routine_code(thd)) { /* We don't distinguish between errors for now */ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a1ede3c45fb..ebb97cde3e4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2018,17 +2018,18 @@ sp_proc_stmt: sp_head *sp= lex->sphead; sp_pcontext *parsing_ctx= lex->spcont; int case_expr_id= parsing_ctx->register_case_expr(); + sp_instr_set_case_expr *i; if (parsing_ctx->push_case_expr_id(case_expr_id)) YYABORT; - - sp->add_instr( - new sp_instr_set_case_expr(sp->instructions(), - parsing_ctx, - case_expr_id, - $3, - lex)); - + + i= new sp_instr_set_case_expr(sp->instructions(), + parsing_ctx, + case_expr_id, + $3, + lex); + sp->add_cont_backpatch(i); + sp->add_instr(i); sp->m_flags|= sp_head::IN_SIMPLE_CASE; sp->restore_lex(YYTHD); } |