Fixed BUG#3583: query cache doesn't work for stored procedures.
This commit is contained in:
parent
ef31095c5c
commit
5b10e3e5b5
@ -1719,10 +1719,10 @@ show processlist;
|
||||
end|
|
||||
call bug4902_2()|
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query # NULL call bug4902_2()
|
||||
# root localhost test Query # NULL show processlist
|
||||
call bug4902_2()|
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query # NULL call bug4902_2()
|
||||
# root localhost test Query # NULL show processlist
|
||||
drop procedure bug4902_2|
|
||||
drop table if exists t3|
|
||||
create procedure bug4904()
|
||||
@ -1849,6 +1849,51 @@ select @x|
|
||||
NULL
|
||||
delete from t1|
|
||||
drop procedure bug4941|
|
||||
drop procedure if exists bug3583|
|
||||
create procedure bug3583()
|
||||
begin
|
||||
declare c int;
|
||||
select * from t1;
|
||||
select count(*) into c from t1;
|
||||
select c;
|
||||
end|
|
||||
insert into t1 values ("x", 3), ("y", 5)|
|
||||
set @x = @@query_cache_size|
|
||||
set global query_cache_size = 10*1024*1024|
|
||||
flush status|
|
||||
flush query cache|
|
||||
show status like 'Qcache_hits'|
|
||||
Variable_name Value
|
||||
Qcache_hits 0
|
||||
call bug3583()|
|
||||
id data
|
||||
x 3
|
||||
y 5
|
||||
c
|
||||
2
|
||||
show status like 'Qcache_hits'|
|
||||
Variable_name Value
|
||||
Qcache_hits 0
|
||||
call bug3583()|
|
||||
id data
|
||||
x 3
|
||||
y 5
|
||||
c
|
||||
2
|
||||
call bug3583()|
|
||||
id data
|
||||
x 3
|
||||
y 5
|
||||
c
|
||||
2
|
||||
show status like 'Qcache_hits'|
|
||||
Variable_name Value
|
||||
Qcache_hits 2
|
||||
set global query_cache_size = @x|
|
||||
flush status|
|
||||
flush query cache|
|
||||
delete from t1|
|
||||
drop procedure bug3583|
|
||||
drop table if exists fac|
|
||||
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
||||
create procedure ifac(n int unsigned)
|
||||
|
@ -2022,6 +2022,41 @@ delete from t1|
|
||||
drop procedure bug4941|
|
||||
|
||||
|
||||
#
|
||||
# BUG#3583: query cache doesn't work for stored procedures
|
||||
#
|
||||
--disable_warnings
|
||||
drop procedure if exists bug3583|
|
||||
--enable_warnings
|
||||
create procedure bug3583()
|
||||
begin
|
||||
declare c int;
|
||||
|
||||
select * from t1;
|
||||
select count(*) into c from t1;
|
||||
select c;
|
||||
end|
|
||||
|
||||
insert into t1 values ("x", 3), ("y", 5)|
|
||||
set @x = @@query_cache_size|
|
||||
set global query_cache_size = 10*1024*1024|
|
||||
|
||||
flush status|
|
||||
flush query cache|
|
||||
show status like 'Qcache_hits'|
|
||||
call bug3583()|
|
||||
show status like 'Qcache_hits'|
|
||||
call bug3583()|
|
||||
call bug3583()|
|
||||
show status like 'Qcache_hits'|
|
||||
|
||||
set global query_cache_size = @x|
|
||||
flush status|
|
||||
flush query cache|
|
||||
delete from t1|
|
||||
drop procedure bug3583|
|
||||
|
||||
|
||||
#
|
||||
# Some "real" examples
|
||||
#
|
||||
|
@ -1153,9 +1153,25 @@ sp_instr_stmt::~sp_instr_stmt()
|
||||
int
|
||||
sp_instr_stmt::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
char *query;
|
||||
uint32 query_length;
|
||||
DBUG_ENTER("sp_instr_stmt::execute");
|
||||
DBUG_PRINT("info", ("command: %d", m_lex->sql_command));
|
||||
int res= exec_stmt(thd, m_lex);
|
||||
int res;
|
||||
|
||||
query= thd->query;
|
||||
query_length= thd->query_length;
|
||||
if (!(res= alloc_query(thd, m_query.str, m_query.length+1)))
|
||||
{
|
||||
if (query_cache_send_result_to_client(thd,
|
||||
thd->query, thd->query_length) <= 0)
|
||||
{
|
||||
res= exec_stmt(thd, m_lex);
|
||||
query_cache_end_of_result(thd);
|
||||
}
|
||||
thd->query= query;
|
||||
thd->query_length= query_length;
|
||||
}
|
||||
*nextp = m_ip+1;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
|
||||
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
|
||||
my_bool m_in_handler; // TRUE if parser in a handler body
|
||||
uchar *m_tmp_query; // Temporary pointer to sub query string
|
||||
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
|
||||
st_sp_chistics *m_chistics;
|
||||
ulong m_sql_mode; // For SHOW CREATE
|
||||
@ -314,9 +315,14 @@ class sp_instr_stmt : public sp_instr
|
||||
|
||||
public:
|
||||
|
||||
LEX_STRING m_query; // For thd->query
|
||||
|
||||
sp_instr_stmt(uint ip, sp_pcontext *ctx)
|
||||
: sp_instr(ip, ctx), m_lex(NULL)
|
||||
{}
|
||||
{
|
||||
m_query.str= 0;
|
||||
m_query.length= 0;
|
||||
}
|
||||
|
||||
virtual ~sp_instr_stmt();
|
||||
|
||||
|
@ -611,6 +611,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
header->result(result);
|
||||
header->last_pkt_nr= net->pkt_nr;
|
||||
BLOCK_UNLOCK_WR(query_block);
|
||||
}
|
||||
else
|
||||
@ -1085,6 +1086,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
||||
ALIGN_SIZE(sizeof(Query_cache_result))))
|
||||
break; // Client aborted
|
||||
result_block = result_block->next;
|
||||
thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated
|
||||
} while (result_block != first_result_block);
|
||||
#else
|
||||
{
|
||||
|
@ -116,6 +116,7 @@ struct Query_cache_query
|
||||
NET *wri;
|
||||
ulong len;
|
||||
uint8 tbls_type;
|
||||
unsigned int last_pkt_nr;
|
||||
|
||||
inline void init_n_lock();
|
||||
void unlock_n_destroy();
|
||||
|
@ -1788,17 +1788,21 @@ sp_opt_default:
|
||||
|
||||
sp_proc_stmt:
|
||||
{
|
||||
Lex->sphead->reset_lex(YYTHD);
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->reset_lex(YYTHD);
|
||||
lex->sphead->m_tmp_query= lex->tok_start;
|
||||
}
|
||||
statement
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
if ((lex->sql_command == SQLCOM_SELECT && !lex->result) ||
|
||||
sp_multi_results_command(lex->sql_command))
|
||||
{
|
||||
/* We maybe have one or more SELECT without INTO */
|
||||
lex->sphead->m_multi_results= TRUE;
|
||||
sp->m_multi_results= TRUE;
|
||||
}
|
||||
if (lex->sql_command == SQLCOM_CHANGE_DB)
|
||||
{ /* "USE db" doesn't work in a procedure */
|
||||
@ -1819,22 +1823,31 @@ sp_proc_stmt:
|
||||
especially triggers a tremendously, but it's nothing we
|
||||
can do about this at the moment.
|
||||
*/
|
||||
if (lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
|
||||
if (sp->m_type != TYPE_ENUM_PROCEDURE)
|
||||
{
|
||||
send_error(YYTHD, ER_SP_BADSTATEMENT);
|
||||
YYABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions(),
|
||||
sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(),
|
||||
lex->spcont);
|
||||
|
||||
/* Extract the query statement from the tokenizer:
|
||||
The end is either lex->tok_end or tok->ptr. */
|
||||
if (lex->ptr - lex->tok_end > 1)
|
||||
i->m_query.length= lex->ptr - sp->m_tmp_query;
|
||||
else
|
||||
i->m_query.length= lex->tok_end - sp->m_tmp_query;
|
||||
i->m_query.str= strmake_root(&YYTHD->mem_root,
|
||||
(char *)sp->m_tmp_query,
|
||||
i->m_query.length);
|
||||
i->set_lex(lex);
|
||||
lex->sphead->add_instr(i);
|
||||
sp->add_instr(i);
|
||||
lex->sp_lex_in_use= TRUE;
|
||||
}
|
||||
}
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
sp->restore_lex(YYTHD);
|
||||
}
|
||||
| RETURN_SYM expr
|
||||
{
|
||||
@ -6482,6 +6495,7 @@ simple_ident:
|
||||
}
|
||||
$$ = (Item*) new Item_splocal($1, spv->offset);
|
||||
lex->variables_used= 1;
|
||||
lex->safe_to_cache_query=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user