mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 21:42:35 +01:00
Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/usr/home/ram/work/5.0.b16511
This commit is contained in:
commit
221b35783d
15 changed files with 273 additions and 87 deletions
|
@ -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;
|
||||
|
|
|
@ -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 ..."
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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)
|
||||
|
|
53
sql/sp.cc
53
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)
|
||||
{
|
||||
|
|
5
sql/sp.h
5
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue