summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <ramil@mysql.com>2006-02-07 12:06:06 +0400
committerunknown <ramil@mysql.com>2006-02-07 12:06:06 +0400
commit79112423afaed3c4ead9542fe53e1650aacaa15b (patch)
tree747099b88908fa6cd29fc55c930fa13a07cc00c4
parente071d7aa8793cadd6c455bc2a002de8820f586e8 (diff)
parent2ba25676d7d835d53f591b8d8eb4cde84445b313 (diff)
downloadmariadb-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.result27
-rw-r--r--mysql-test/r/sp-code.result2
-rw-r--r--mysql-test/r/sp-destruct.result8
-rw-r--r--mysql-test/r/sp.result7
-rw-r--r--mysql-test/t/group_min_max.test21
-rw-r--r--mysql-test/t/sp-destruct.test11
-rw-r--r--mysql-test/t/sp.test5
-rw-r--r--sql/opt_range.cc1
-rw-r--r--sql/sp.cc53
-rw-r--r--sql/sp.h5
-rw-r--r--sql/sp_head.cc85
-rw-r--r--sql/sp_head.h96
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_parse.cc20
-rw-r--r--sql/sql_yacc.yy17
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)
{
diff --git a/sql/sp.h b/sql/sp.h
index 53343e0fb25..2587a9b115a 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -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);
}