mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge mysql.com:/home/psergey/mysql-5.0-bug12228-r4
into mysql.com:/home/psergey/mysql-5.0-bug12228-r5 mysql-test/r/type_bit.result: Auto merged mysql-test/t/sp-threads.test: Auto merged mysql-test/t/type_bit.test: Auto merged sql/sp.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged
This commit is contained in:
@ -37,6 +37,7 @@ Id User Host db Command Time State Info
|
|||||||
# root localhost test Sleep # NULL
|
# root localhost test Sleep # NULL
|
||||||
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
|
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
|
||||||
# root localhost test Query # NULL show processlist
|
# root localhost test Query # NULL show processlist
|
||||||
|
# root localhost test Sleep # NULL
|
||||||
unlock tables;
|
unlock tables;
|
||||||
drop procedure bug9486;
|
drop procedure bug9486;
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
@ -64,3 +65,27 @@ insert into t1 (select f from v1);
|
|||||||
drop function bug11554;
|
drop function bug11554;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
|
drop procedure if exists p1;
|
||||||
|
drop procedure if exists p2;
|
||||||
|
create table t1 (s1 int)|
|
||||||
|
create procedure p1() select * from t1|
|
||||||
|
create procedure p2()
|
||||||
|
begin
|
||||||
|
insert into t1 values (1);
|
||||||
|
call p1();
|
||||||
|
select * from t1;
|
||||||
|
end|
|
||||||
|
use test;
|
||||||
|
lock table t1 write;
|
||||||
|
call p2();
|
||||||
|
use test;
|
||||||
|
drop procedure p1;
|
||||||
|
create procedure p1() select * from t1;
|
||||||
|
unlock tables;
|
||||||
|
s1
|
||||||
|
1
|
||||||
|
s1
|
||||||
|
1
|
||||||
|
drop procedure p1;
|
||||||
|
drop procedure p2;
|
||||||
|
drop table t1;
|
||||||
|
@ -34,7 +34,7 @@ select 0 + b'1111111111111111';
|
|||||||
select 0 + b'1000000000000001';
|
select 0 + b'1000000000000001';
|
||||||
0 + b'1000000000000001'
|
0 + b'1000000000000001'
|
||||||
32769
|
32769
|
||||||
drop table if exists t1;
|
drop table if exists t1,t2;
|
||||||
create table t1 (a bit(65));
|
create table t1 (a bit(65));
|
||||||
ERROR 42000: Display width out of range for column 'a' (max = 64)
|
ERROR 42000: Display width out of range for column 'a' (max = 64)
|
||||||
create table t1 (a bit(0));
|
create table t1 (a bit(0));
|
||||||
|
@ -1880,6 +1880,8 @@ test.v5 check error View 'test.v5' references invalid table(s) or column(s) or f
|
|||||||
test.v6 check status OK
|
test.v6 check status OK
|
||||||
drop view v1, v2, v3, v4, v5, v6;
|
drop view v1, v2, v3, v4, v5, v6;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
drop function if exists f1;
|
||||||
|
drop function if exists f2;
|
||||||
CREATE TABLE t1 (col1 time);
|
CREATE TABLE t1 (col1 time);
|
||||||
CREATE TABLE t2 (col1 time);
|
CREATE TABLE t2 (col1 time);
|
||||||
CREATE TABLE t3 (col1 time);
|
CREATE TABLE t3 (col1 time);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
connect (con1root,localhost,root,,);
|
connect (con1root,localhost,root,,);
|
||||||
connect (con2root,localhost,root,,);
|
connect (con2root,localhost,root,,);
|
||||||
|
connect (con3root,localhost,root,,);
|
||||||
|
|
||||||
connection con1root;
|
connection con1root;
|
||||||
use test;
|
use test;
|
||||||
@ -130,6 +131,48 @@ drop function bug11554;
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
|
|
||||||
|
|
||||||
|
# BUG#12228
|
||||||
|
--disable_warnings
|
||||||
|
drop procedure if exists p1;
|
||||||
|
drop procedure if exists p2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
connection con1root;
|
||||||
|
delimiter |;
|
||||||
|
create table t1 (s1 int)|
|
||||||
|
create procedure p1() select * from t1|
|
||||||
|
create procedure p2()
|
||||||
|
begin
|
||||||
|
insert into t1 values (1);
|
||||||
|
call p1();
|
||||||
|
select * from t1;
|
||||||
|
end|
|
||||||
|
delimiter ;|
|
||||||
|
|
||||||
|
connection con2root;
|
||||||
|
use test;
|
||||||
|
lock table t1 write;
|
||||||
|
|
||||||
|
connection con1root;
|
||||||
|
send call p2();
|
||||||
|
|
||||||
|
connection con3root;
|
||||||
|
use test;
|
||||||
|
drop procedure p1;
|
||||||
|
create procedure p1() select * from t1;
|
||||||
|
|
||||||
|
connection con2root;
|
||||||
|
unlock tables;
|
||||||
|
|
||||||
|
connection con1root;
|
||||||
|
# Crash will be here if we hit BUG#12228
|
||||||
|
reap;
|
||||||
|
|
||||||
|
drop procedure p1;
|
||||||
|
drop procedure p2;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
#
|
#
|
||||||
|
@ -16,7 +16,7 @@ select 0 + b'1111111111111111';
|
|||||||
select 0 + b'1000000000000001';
|
select 0 + b'1000000000000001';
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1,t2;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
--error 1439
|
--error 1439
|
||||||
|
@ -1711,6 +1711,10 @@ CHECK TABLE v1, v2, v3, v4, v5, v6;
|
|||||||
drop view v1, v2, v3, v4, v5, v6;
|
drop view v1, v2, v3, v4, v5, v6;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop function if exists f1;
|
||||||
|
drop function if exists f2;
|
||||||
|
--enable_warnings
|
||||||
CREATE TABLE t1 (col1 time);
|
CREATE TABLE t1 (col1 time);
|
||||||
CREATE TABLE t2 (col1 time);
|
CREATE TABLE t2 (col1 time);
|
||||||
CREATE TABLE t3 (col1 time);
|
CREATE TABLE t3 (col1 time);
|
||||||
|
16
sql/sp.cc
16
sql/sp.cc
@ -989,13 +989,11 @@ int
|
|||||||
sp_drop_procedure(THD *thd, sp_name *name)
|
sp_drop_procedure(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
bool found;
|
|
||||||
DBUG_ENTER("sp_drop_procedure");
|
DBUG_ENTER("sp_drop_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
found= sp_cache_remove(&thd->sp_proc_cache, name);
|
|
||||||
ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name);
|
ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name);
|
||||||
if (!found && !ret)
|
if (!ret)
|
||||||
sp_cache_invalidate();
|
sp_cache_invalidate();
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
@ -1005,13 +1003,11 @@ int
|
|||||||
sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics)
|
sp_update_procedure(THD *thd, sp_name *name, st_sp_chistics *chistics)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
bool found;
|
|
||||||
DBUG_ENTER("sp_update_procedure");
|
DBUG_ENTER("sp_update_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
found= sp_cache_remove(&thd->sp_proc_cache, name);
|
|
||||||
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics);
|
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, chistics);
|
||||||
if (!found && !ret)
|
if (!ret)
|
||||||
sp_cache_invalidate();
|
sp_cache_invalidate();
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
@ -1102,13 +1098,11 @@ int
|
|||||||
sp_drop_function(THD *thd, sp_name *name)
|
sp_drop_function(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
bool found;
|
|
||||||
DBUG_ENTER("sp_drop_function");
|
DBUG_ENTER("sp_drop_function");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
found= sp_cache_remove(&thd->sp_func_cache, name);
|
|
||||||
ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name);
|
ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name);
|
||||||
if (!found && !ret)
|
if (!ret)
|
||||||
sp_cache_invalidate();
|
sp_cache_invalidate();
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
@ -1118,13 +1112,11 @@ int
|
|||||||
sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics)
|
sp_update_function(THD *thd, sp_name *name, st_sp_chistics *chistics)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
bool found;
|
|
||||||
DBUG_ENTER("sp_update_procedure");
|
DBUG_ENTER("sp_update_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
found= sp_cache_remove(&thd->sp_func_cache, name);
|
|
||||||
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics);
|
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, chistics);
|
||||||
if (!found && !ret)
|
if (!ret)
|
||||||
sp_cache_invalidate();
|
sp_cache_invalidate();
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
222
sql/sp_cache.cc
222
sql/sp_cache.cc
@ -24,17 +24,78 @@
|
|||||||
static pthread_mutex_t Cversion_lock;
|
static pthread_mutex_t Cversion_lock;
|
||||||
static ulong Cversion = 0;
|
static ulong Cversion = 0;
|
||||||
|
|
||||||
void
|
|
||||||
sp_cache_init()
|
/*
|
||||||
|
Cache of stored routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class sp_cache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ulong version;
|
||||||
|
|
||||||
|
sp_cache();
|
||||||
|
~sp_cache();
|
||||||
|
|
||||||
|
inline void insert(sp_head *sp)
|
||||||
|
{
|
||||||
|
/* TODO: why don't we check return value? */
|
||||||
|
my_hash_insert(&m_hashtable, (const byte *)sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sp_head *lookup(char *name, uint namelen)
|
||||||
|
{
|
||||||
|
return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NOT_USED
|
||||||
|
inline bool remove(char *name, uint namelen)
|
||||||
|
{
|
||||||
|
sp_head *sp= lookup(name, namelen);
|
||||||
|
if (sp)
|
||||||
|
{
|
||||||
|
hash_delete(&m_hashtable, (byte *)sp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void remove_all()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
/* All routines in this cache */
|
||||||
|
HASH m_hashtable;
|
||||||
|
}; // class sp_cache
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize the SP caching once at startup */
|
||||||
|
|
||||||
|
void sp_cache_init()
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&Cversion_lock, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&Cversion_lock, MY_MUTEX_INIT_FAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
sp_cache_clear(sp_cache **cp)
|
/*
|
||||||
|
Clear the cache *cp and set *cp to NULL.
|
||||||
|
SYNOPSIS
|
||||||
|
sp_cache_clear()
|
||||||
|
cp Pointer to cache to clear
|
||||||
|
NOTE
|
||||||
|
This function doesn't invalidate other caches.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sp_cache_clear(sp_cache **cp)
|
||||||
{
|
{
|
||||||
sp_cache *c= *cp;
|
sp_cache *c= *cp;
|
||||||
|
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
delete c;
|
delete c;
|
||||||
@ -42,86 +103,122 @@ sp_cache_clear(sp_cache **cp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
sp_cache_insert(sp_cache **cp, sp_head *sp)
|
/*
|
||||||
|
Insert a routine into the cache.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
sp_cache_insert()
|
||||||
|
cp The cache to put routine into
|
||||||
|
sp Routine to insert.
|
||||||
|
|
||||||
|
TODO: Perhaps it will be more straightforward if in case we returned an
|
||||||
|
error from this function when we couldn't allocate sp_cache. (right
|
||||||
|
now failure to put routine into cache will cause a 'SP not found'
|
||||||
|
error to be reported at some later time)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sp_cache_insert(sp_cache **cp, sp_head *sp)
|
||||||
{
|
{
|
||||||
sp_cache *c= *cp;
|
sp_cache *c= *cp;
|
||||||
|
|
||||||
if (! c)
|
if (!c && (c= new sp_cache()))
|
||||||
c= new sp_cache();
|
{
|
||||||
|
pthread_mutex_lock(&Cversion_lock); // LOCK
|
||||||
|
c->version= Cversion;
|
||||||
|
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
||||||
|
}
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
ulong v;
|
DBUG_PRINT("info",("sp_cache: inserting: %*s", sp->m_qname.length,
|
||||||
|
sp->m_qname.str));
|
||||||
pthread_mutex_lock(&Cversion_lock); // LOCK
|
|
||||||
v= Cversion;
|
|
||||||
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
|
||||||
|
|
||||||
if (c->version < v)
|
|
||||||
{
|
|
||||||
if (*cp)
|
|
||||||
c->remove_all();
|
|
||||||
c->version= v;
|
|
||||||
}
|
|
||||||
c->insert(sp);
|
c->insert(sp);
|
||||||
if (*cp == NULL)
|
if (*cp == NULL)
|
||||||
*cp= c;
|
*cp= c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sp_head *
|
|
||||||
sp_cache_lookup(sp_cache **cp, sp_name *name)
|
/*
|
||||||
|
Look up a routine in the cache.
|
||||||
|
SYNOPSIS
|
||||||
|
sp_cache_lookup()
|
||||||
|
cp Cache to look into
|
||||||
|
name Name of rutine to find
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
An obsolete (but not more obsolete then since last
|
||||||
|
sp_cache_flush_obsolete call) routine may be returned.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
The routine or
|
||||||
|
NULL if the routine not found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name)
|
||||||
{
|
{
|
||||||
ulong v;
|
|
||||||
sp_cache *c= *cp;
|
sp_cache *c= *cp;
|
||||||
|
if (!c)
|
||||||
if (! c)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pthread_mutex_lock(&Cversion_lock); // LOCK
|
|
||||||
v= Cversion;
|
|
||||||
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
|
||||||
|
|
||||||
if (c->version < v)
|
|
||||||
{
|
|
||||||
c->remove_all();
|
|
||||||
c->version= v;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return c->lookup(name->m_qname.str, name->m_qname.length);
|
return c->lookup(name->m_qname.str, name->m_qname.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
sp_cache_remove(sp_cache **cp, sp_name *name)
|
/*
|
||||||
{
|
Invalidate all routines in all caches.
|
||||||
sp_cache *c= *cp;
|
|
||||||
bool found= FALSE;
|
SYNOPSIS
|
||||||
|
sp_cache_invalidate()
|
||||||
if (c)
|
|
||||||
{
|
NOTE
|
||||||
ulong v;
|
This is called when a VIEW definition is modifed. We can't destroy sp_head
|
||||||
|
objects here as one may modify VIEW definitions from prelocking-free SPs.
|
||||||
pthread_mutex_lock(&Cversion_lock); // LOCK
|
*/
|
||||||
v= Cversion++;
|
|
||||||
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
void sp_cache_invalidate()
|
||||||
|
|
||||||
if (c->version < v)
|
|
||||||
c->remove_all();
|
|
||||||
else
|
|
||||||
found= c->remove(name->m_qname.str, name->m_qname.length);
|
|
||||||
c->version= v+1;
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sp_cache_invalidate()
|
|
||||||
{
|
{
|
||||||
|
DBUG_PRINT("info",("sp_cache: invalidating"));
|
||||||
pthread_mutex_lock(&Cversion_lock); // LOCK
|
pthread_mutex_lock(&Cversion_lock); // LOCK
|
||||||
Cversion++;
|
Cversion++;
|
||||||
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove out-of-date SPs from the cache.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
sp_cache_flush_obsolete()
|
||||||
|
cp Cache to flush
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
This invalidates pointers to sp_head objects this thread uses.
|
||||||
|
In practice that means 'dont call this function when inside SP'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sp_cache_flush_obsolete(sp_cache **cp)
|
||||||
|
{
|
||||||
|
sp_cache *c= *cp;
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
pthread_mutex_lock(&Cversion_lock); // LOCK
|
||||||
|
v= Cversion;
|
||||||
|
pthread_mutex_unlock(&Cversion_lock); // UNLOCK
|
||||||
|
if (c->version < v)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info",("sp_cache: deleting all functions"));
|
||||||
|
/* We need to delete all elements. */
|
||||||
|
c->remove_all();
|
||||||
|
c->version= v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Internal functions
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
static byte *
|
static byte *
|
||||||
hash_get_key_for_sp_head(const byte *ptr, uint *plen,
|
hash_get_key_for_sp_head(const byte *ptr, uint *plen,
|
||||||
my_bool first)
|
my_bool first)
|
||||||
@ -136,7 +233,6 @@ static void
|
|||||||
hash_free_sp_head(void *p)
|
hash_free_sp_head(void *p)
|
||||||
{
|
{
|
||||||
sp_head *sp= (sp_head *)p;
|
sp_head *sp= (sp_head *)p;
|
||||||
|
|
||||||
delete sp;
|
delete sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
sql/sp_cache.h
105
sql/sp_cache.h
@ -25,94 +25,39 @@
|
|||||||
/*
|
/*
|
||||||
Stored procedures/functions cache. This is used as follows:
|
Stored procedures/functions cache. This is used as follows:
|
||||||
* Each thread has its own cache.
|
* Each thread has its own cache.
|
||||||
* Each sp_head object is put into its thread cache before it is used, and
|
* Each sp_head object is put into its thread cache before it is used, and
|
||||||
then remains in the cache until deleted.
|
then remains in the cache until deleted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class sp_head;
|
class sp_head;
|
||||||
class sp_cache;
|
class sp_cache;
|
||||||
|
|
||||||
/* Initialize the SP caching once at startup */
|
|
||||||
void sp_cache_init();
|
|
||||||
|
|
||||||
/* Clear the cache *cp and set *cp to NULL */
|
|
||||||
void sp_cache_clear(sp_cache **cp);
|
|
||||||
|
|
||||||
/* Insert an SP into cache. If 'cp' points to NULL, it's set to a new cache */
|
|
||||||
void sp_cache_insert(sp_cache **cp, sp_head *sp);
|
|
||||||
|
|
||||||
/* Lookup an SP in cache */
|
|
||||||
sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove an SP from cache, and also bump the Cversion number so all other
|
|
||||||
caches are invalidated.
|
|
||||||
Returns true if something was removed.
|
|
||||||
*/
|
|
||||||
bool sp_cache_remove(sp_cache **cp, sp_name *name);
|
|
||||||
|
|
||||||
/* Invalidate all existing SP caches by bumping Cversion number. */
|
|
||||||
void sp_cache_invalidate();
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
Cache usage scenarios:
|
||||||
* The cache class. Don't use this directly, use the C API above
|
1. Application-wide init:
|
||||||
*
|
sp_cache_init();
|
||||||
*/
|
|
||||||
|
|
||||||
class sp_cache
|
2. SP execution in thread:
|
||||||
{
|
2.1 While holding sp_head* pointers:
|
||||||
public:
|
|
||||||
|
// look up a routine in the cache (no checks if it is up to date or not)
|
||||||
|
sp_cache_lookup();
|
||||||
|
|
||||||
|
sp_cache_insert();
|
||||||
|
sp_cache_invalidate();
|
||||||
|
|
||||||
|
2.2 When not holding any sp_head* pointers:
|
||||||
|
sp_cache_flush_obsolete();
|
||||||
|
|
||||||
|
3. Before thread exit:
|
||||||
|
sp_cache_clear();
|
||||||
|
*/
|
||||||
|
|
||||||
ulong version;
|
void sp_cache_init();
|
||||||
|
void sp_cache_clear(sp_cache **cp);
|
||||||
sp_cache();
|
void sp_cache_insert(sp_cache **cp, sp_head *sp);
|
||||||
|
sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
|
||||||
~sp_cache();
|
void sp_cache_invalidate();
|
||||||
|
void sp_cache_flush_obsolete(sp_cache **cp);
|
||||||
void
|
|
||||||
init();
|
|
||||||
|
|
||||||
void
|
|
||||||
cleanup();
|
|
||||||
|
|
||||||
inline void
|
|
||||||
insert(sp_head *sp)
|
|
||||||
{
|
|
||||||
my_hash_insert(&m_hashtable, (const byte *)sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline sp_head *
|
|
||||||
lookup(char *name, uint namelen)
|
|
||||||
{
|
|
||||||
return (sp_head *)hash_search(&m_hashtable, (const byte *)name, namelen);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
remove(char *name, uint namelen)
|
|
||||||
{
|
|
||||||
sp_head *sp= lookup(name, namelen);
|
|
||||||
|
|
||||||
if (sp)
|
|
||||||
{
|
|
||||||
hash_delete(&m_hashtable, (byte *)sp);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
remove_all()
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
HASH m_hashtable;
|
|
||||||
|
|
||||||
}; // class sp_cache
|
|
||||||
|
|
||||||
#endif /* _SP_CACHE_H_ */
|
#endif /* _SP_CACHE_H_ */
|
||||||
|
@ -5340,11 +5340,12 @@ void mysql_init_multi_delete(LEX *lex)
|
|||||||
void mysql_parse(THD *thd, char *inBuf, uint length)
|
void mysql_parse(THD *thd, char *inBuf, uint length)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_parse");
|
DBUG_ENTER("mysql_parse");
|
||||||
|
|
||||||
mysql_init_query(thd, (uchar*) inBuf, length);
|
mysql_init_query(thd, (uchar*) inBuf, length);
|
||||||
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
|
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
|
sp_cache_flush_obsolete(&thd->sp_proc_cache);
|
||||||
|
sp_cache_flush_obsolete(&thd->sp_func_cache);
|
||||||
if (!yyparse((void *)thd) && ! thd->is_fatal_error)
|
if (!yyparse((void *)thd) && ! thd->is_fatal_error)
|
||||||
{
|
{
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
@ -73,6 +73,7 @@ Long data handling:
|
|||||||
#include <m_ctype.h> // for isspace()
|
#include <m_ctype.h> // for isspace()
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
#include "sp.h"
|
#include "sp.h"
|
||||||
|
#include "sp_cache.h"
|
||||||
#ifdef EMBEDDED_LIBRARY
|
#ifdef EMBEDDED_LIBRARY
|
||||||
/* include MYSQL_BIND headers */
|
/* include MYSQL_BIND headers */
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
@ -1783,6 +1784,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
|||||||
lex= thd->lex;
|
lex= thd->lex;
|
||||||
lex->safe_to_cache_query= 0;
|
lex->safe_to_cache_query= 0;
|
||||||
|
|
||||||
|
sp_cache_flush_obsolete(&thd->sp_proc_cache);
|
||||||
|
sp_cache_flush_obsolete(&thd->sp_func_cache);
|
||||||
|
|
||||||
error= yyparse((void *)thd) || thd->is_fatal_error ||
|
error= yyparse((void *)thd) || thd->is_fatal_error ||
|
||||||
thd->net.report_error || init_param_array(stmt);
|
thd->net.report_error || init_param_array(stmt);
|
||||||
/*
|
/*
|
||||||
@ -2060,6 +2064,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
|
|||||||
thd->protocol= stmt->protocol; // Switch to binary protocol
|
thd->protocol= stmt->protocol; // Switch to binary protocol
|
||||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
|
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
|
||||||
|
sp_cache_flush_obsolete(&thd->sp_proc_cache);
|
||||||
|
sp_cache_flush_obsolete(&thd->sp_func_cache);
|
||||||
mysql_execute_command(thd);
|
mysql_execute_command(thd);
|
||||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
|
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
|
||||||
|
Reference in New Issue
Block a user