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|
|
end|
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
Id User Host db Command Time State Info
|
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()|
|
call bug4902_2()|
|
||||||
Id User Host db Command Time State Info
|
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 procedure bug4902_2|
|
||||||
drop table if exists t3|
|
drop table if exists t3|
|
||||||
create procedure bug4904()
|
create procedure bug4904()
|
||||||
@ -1849,6 +1849,51 @@ select @x|
|
|||||||
NULL
|
NULL
|
||||||
delete from t1|
|
delete from t1|
|
||||||
drop procedure bug4941|
|
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|
|
drop table if exists fac|
|
||||||
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
||||||
create procedure ifac(n int unsigned)
|
create procedure ifac(n int unsigned)
|
||||||
|
@ -2022,6 +2022,41 @@ delete from t1|
|
|||||||
drop procedure bug4941|
|
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
|
# Some "real" examples
|
||||||
#
|
#
|
||||||
|
@ -1153,9 +1153,25 @@ sp_instr_stmt::~sp_instr_stmt()
|
|||||||
int
|
int
|
||||||
sp_instr_stmt::execute(THD *thd, uint *nextp)
|
sp_instr_stmt::execute(THD *thd, uint *nextp)
|
||||||
{
|
{
|
||||||
|
char *query;
|
||||||
|
uint32 query_length;
|
||||||
DBUG_ENTER("sp_instr_stmt::execute");
|
DBUG_ENTER("sp_instr_stmt::execute");
|
||||||
DBUG_PRINT("info", ("command: %d", m_lex->sql_command));
|
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;
|
*nextp = m_ip+1;
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,7 @@ public:
|
|||||||
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
|
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_multi_results; // TRUE if a procedure with SELECT(s)
|
||||||
my_bool m_in_handler; // TRUE if parser in a handler body
|
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
|
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
|
||||||
st_sp_chistics *m_chistics;
|
st_sp_chistics *m_chistics;
|
||||||
ulong m_sql_mode; // For SHOW CREATE
|
ulong m_sql_mode; // For SHOW CREATE
|
||||||
@ -314,9 +315,14 @@ class sp_instr_stmt : public sp_instr
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
LEX_STRING m_query; // For thd->query
|
||||||
|
|
||||||
sp_instr_stmt(uint ip, sp_pcontext *ctx)
|
sp_instr_stmt(uint ip, sp_pcontext *ctx)
|
||||||
: sp_instr(ip, ctx), m_lex(NULL)
|
: sp_instr(ip, ctx), m_lex(NULL)
|
||||||
{}
|
{
|
||||||
|
m_query.str= 0;
|
||||||
|
m_query.length= 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~sp_instr_stmt();
|
virtual ~sp_instr_stmt();
|
||||||
|
|
||||||
|
@ -611,6 +611,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
header->result(result);
|
header->result(result);
|
||||||
|
header->last_pkt_nr= net->pkt_nr;
|
||||||
BLOCK_UNLOCK_WR(query_block);
|
BLOCK_UNLOCK_WR(query_block);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1085,6 +1086,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
ALIGN_SIZE(sizeof(Query_cache_result))))
|
ALIGN_SIZE(sizeof(Query_cache_result))))
|
||||||
break; // Client aborted
|
break; // Client aborted
|
||||||
result_block = result_block->next;
|
result_block = result_block->next;
|
||||||
|
thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated
|
||||||
} while (result_block != first_result_block);
|
} while (result_block != first_result_block);
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
@ -116,6 +116,7 @@ struct Query_cache_query
|
|||||||
NET *wri;
|
NET *wri;
|
||||||
ulong len;
|
ulong len;
|
||||||
uint8 tbls_type;
|
uint8 tbls_type;
|
||||||
|
unsigned int last_pkt_nr;
|
||||||
|
|
||||||
inline void init_n_lock();
|
inline void init_n_lock();
|
||||||
void unlock_n_destroy();
|
void unlock_n_destroy();
|
||||||
|
@ -1788,17 +1788,21 @@ sp_opt_default:
|
|||||||
|
|
||||||
sp_proc_stmt:
|
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
|
statement
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
if ((lex->sql_command == SQLCOM_SELECT && !lex->result) ||
|
if ((lex->sql_command == SQLCOM_SELECT && !lex->result) ||
|
||||||
sp_multi_results_command(lex->sql_command))
|
sp_multi_results_command(lex->sql_command))
|
||||||
{
|
{
|
||||||
/* We maybe have one or more SELECT without INTO */
|
/* 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)
|
if (lex->sql_command == SQLCOM_CHANGE_DB)
|
||||||
{ /* "USE db" doesn't work in a procedure */
|
{ /* "USE db" doesn't work in a procedure */
|
||||||
@ -1819,22 +1823,31 @@ sp_proc_stmt:
|
|||||||
especially triggers a tremendously, but it's nothing we
|
especially triggers a tremendously, but it's nothing we
|
||||||
can do about this at the moment.
|
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);
|
send_error(YYTHD, ER_SP_BADSTATEMENT);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions(),
|
sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(),
|
||||||
lex->spcont);
|
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);
|
i->set_lex(lex);
|
||||||
lex->sphead->add_instr(i);
|
sp->add_instr(i);
|
||||||
lex->sp_lex_in_use= TRUE;
|
lex->sp_lex_in_use= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lex->sphead->restore_lex(YYTHD);
|
sp->restore_lex(YYTHD);
|
||||||
}
|
}
|
||||||
| RETURN_SYM expr
|
| RETURN_SYM expr
|
||||||
{
|
{
|
||||||
@ -6482,6 +6495,7 @@ simple_ident:
|
|||||||
}
|
}
|
||||||
$$ = (Item*) new Item_splocal($1, spv->offset);
|
$$ = (Item*) new Item_splocal($1, spv->offset);
|
||||||
lex->variables_used= 1;
|
lex->variables_used= 1;
|
||||||
|
lex->safe_to_cache_query=0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user