mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
WL#1366: Use the schema (db) associated with an SP.
Phase 1: Introduced sp_name class, for qualified name support.
This commit is contained in:
@ -3088,6 +3088,25 @@ longlong Item_func_is_used_lock::val_int()
|
|||||||
return ull->thread_id;
|
return ull->thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item_func_sp::Item_func_sp(sp_name *name)
|
||||||
|
:Item_func(), m_name(name), m_sp(NULL)
|
||||||
|
{
|
||||||
|
m_name->init_qname(current_thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
|
||||||
|
:Item_func(list), m_name(name), m_sp(NULL)
|
||||||
|
{
|
||||||
|
m_name->init_qname(current_thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
Item_func_sp::func_name() const
|
||||||
|
{
|
||||||
|
return m_name->m_name.str;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Item_func_sp::execute(Item **itp)
|
Item_func_sp::execute(Item **itp)
|
||||||
{
|
{
|
||||||
@ -3099,7 +3118,7 @@ Item_func_sp::execute(Item **itp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
m_sp= sp_find_function(thd, &m_name);
|
m_sp= sp_find_function(thd, m_name);
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
@ -3122,7 +3141,7 @@ Item_func_sp::field_type() const
|
|||||||
DBUG_ENTER("Item_func_sp::field_type");
|
DBUG_ENTER("Item_func_sp::field_type");
|
||||||
|
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
m_sp= sp_find_function(current_thd, const_cast<LEX_STRING*>(&m_name));
|
m_sp= sp_find_function(current_thd, m_name);
|
||||||
if (m_sp)
|
if (m_sp)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns));
|
DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns));
|
||||||
@ -3138,7 +3157,7 @@ Item_func_sp::result_type() const
|
|||||||
DBUG_PRINT("info", ("m_sp = %p", m_sp));
|
DBUG_PRINT("info", ("m_sp = %p", m_sp));
|
||||||
|
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
m_sp= sp_find_function(current_thd, const_cast<LEX_STRING*>(&m_name));
|
m_sp= sp_find_function(current_thd, m_name);
|
||||||
if (m_sp)
|
if (m_sp)
|
||||||
{
|
{
|
||||||
DBUG_RETURN(m_sp->result());
|
DBUG_RETURN(m_sp->result());
|
||||||
@ -3152,7 +3171,7 @@ Item_func_sp::fix_length_and_dec()
|
|||||||
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
|
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
|
||||||
|
|
||||||
if (! m_sp)
|
if (! m_sp)
|
||||||
m_sp= sp_find_function(current_thd, &m_name);
|
m_sp= sp_find_function(current_thd, m_name);
|
||||||
if (m_sp)
|
if (m_sp)
|
||||||
{
|
{
|
||||||
switch (m_sp->result()) {
|
switch (m_sp->result()) {
|
||||||
|
@ -1072,32 +1072,26 @@ enum Cast_target
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class sp_head;
|
class sp_head;
|
||||||
|
class sp_name;
|
||||||
|
|
||||||
class Item_func_sp :public Item_func
|
class Item_func_sp :public Item_func
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
LEX_STRING m_name;
|
sp_name *m_name;
|
||||||
mutable sp_head *m_sp;
|
mutable sp_head *m_sp;
|
||||||
|
|
||||||
int execute(Item **itp);
|
int execute(Item **itp);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Item_func_sp(LEX_STRING name)
|
Item_func_sp(sp_name *name);
|
||||||
:Item_func(), m_name(name), m_sp(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Item_func_sp(LEX_STRING name, List<Item> &list)
|
Item_func_sp(sp_name *name, List<Item> &list);
|
||||||
:Item_func(list), m_name(name), m_sp(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual ~Item_func_sp()
|
virtual ~Item_func_sp()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const char *func_name() const
|
const char *func_name() const;
|
||||||
{
|
|
||||||
return m_name.str;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum enum_field_types field_type() const;
|
enum enum_field_types field_type() const;
|
||||||
|
|
||||||
|
124
sql/sp.cc
124
sql/sp.cc
@ -58,21 +58,22 @@ enum
|
|||||||
|
|
||||||
/* *opened=true means we opened ourselves */
|
/* *opened=true means we opened ourselves */
|
||||||
static int
|
static int
|
||||||
db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
|
db_find_routine_aux(THD *thd, int type, sp_name *name,
|
||||||
enum thr_lock_type ltype, TABLE **tablep, bool *opened)
|
enum thr_lock_type ltype, TABLE **tablep, bool *opened)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
byte key[64+64+1]; // db, name, type
|
byte key[64+64+1]; // db, name, type
|
||||||
uint keylen;
|
uint keylen;
|
||||||
DBUG_ENTER("db_find_routine_aux");
|
DBUG_ENTER("db_find_routine_aux");
|
||||||
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
|
DBUG_PRINT("enter", ("type: %d name: %*s",
|
||||||
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
// Put the key used to read the row together
|
// Put the key used to read the row together
|
||||||
memset(key, (int)' ', 64); // QQ Empty db for now
|
memset(key, (int)' ', 64); // QQ Empty db for now
|
||||||
keylen= namelen;
|
keylen= name->m_name.length;
|
||||||
if (keylen > 64)
|
if (keylen > 64)
|
||||||
keylen= 64;
|
keylen= 64;
|
||||||
memcpy(key+64, name, keylen);
|
memcpy(key+64, name->m_name.str, keylen);
|
||||||
memset(key+64+keylen, (int)' ', 64-keylen); // Pad with space
|
memset(key+64+keylen, (int)' ', 64-keylen); // Pad with space
|
||||||
key[128]= type;
|
key[128]= type;
|
||||||
keylen= sizeof(key);
|
keylen= sizeof(key);
|
||||||
@ -112,7 +113,7 @@ db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
|
db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
||||||
{
|
{
|
||||||
extern int yyparse(void *thd);
|
extern int yyparse(void *thd);
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
@ -129,9 +130,10 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
|
|||||||
String str(buff, sizeof(buff), &my_charset_bin);
|
String str(buff, sizeof(buff), &my_charset_bin);
|
||||||
ulong sql_mode;
|
ulong sql_mode;
|
||||||
DBUG_ENTER("db_find_routine");
|
DBUG_ENTER("db_find_routine");
|
||||||
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
|
DBUG_PRINT("enter", ("type: %d name: %*s",
|
||||||
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
ret= db_find_routine_aux(thd, type, name, namelen, TL_READ, &table, &opened);
|
ret= db_find_routine_aux(thd, type, name, TL_READ, &table, &opened);
|
||||||
if (ret != SP_OK)
|
if (ret != SP_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -220,7 +222,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
|
|||||||
|
|
||||||
if (!(defstr= create_string(thd, &deflen,
|
if (!(defstr= create_string(thd, &deflen,
|
||||||
type,
|
type,
|
||||||
name, namelen,
|
name->m_name.str, name->m_name.length,
|
||||||
params, strlen(params),
|
params, strlen(params),
|
||||||
returns, strlen(returns),
|
returns, strlen(returns),
|
||||||
body, strlen(body),
|
body, strlen(body),
|
||||||
@ -289,6 +291,9 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
|||||||
ret= SP_GET_FIELD_FAILED;
|
ret= SP_GET_FIELD_FAILED;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
// QQ Not yet
|
||||||
|
// table->field[MYSQL_PROC_FIELD_DB]->
|
||||||
|
// store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
||||||
table->field[MYSQL_PROC_FIELD_NAME]->
|
table->field[MYSQL_PROC_FIELD_NAME]->
|
||||||
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
store(sp->m_name.str, sp->m_name.length, system_charset_info);
|
||||||
table->field[MYSQL_PROC_FIELD_TYPE]->
|
table->field[MYSQL_PROC_FIELD_TYPE]->
|
||||||
@ -329,15 +334,16 @@ done:
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
db_drop_routine(THD *thd, int type, char *name, uint namelen)
|
db_drop_routine(THD *thd, int type, sp_name *name)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
int ret;
|
int ret;
|
||||||
bool opened;
|
bool opened;
|
||||||
DBUG_ENTER("db_drop_routine");
|
DBUG_ENTER("db_drop_routine");
|
||||||
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
|
DBUG_PRINT("enter", ("type: %d name: %*s",
|
||||||
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened);
|
ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened);
|
||||||
if (ret == SP_OK)
|
if (ret == SP_OK)
|
||||||
{
|
{
|
||||||
if (table->file->delete_row(table->record[0]))
|
if (table->file->delete_row(table->record[0]))
|
||||||
@ -351,7 +357,7 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
db_update_routine(THD *thd, int type, char *name, uint namelen,
|
db_update_routine(THD *thd, int type, sp_name *name,
|
||||||
char *newname, uint newnamelen,
|
char *newname, uint newnamelen,
|
||||||
st_sp_chistics *chistics)
|
st_sp_chistics *chistics)
|
||||||
{
|
{
|
||||||
@ -359,9 +365,10 @@ db_update_routine(THD *thd, int type, char *name, uint namelen,
|
|||||||
int ret;
|
int ret;
|
||||||
bool opened;
|
bool opened;
|
||||||
DBUG_ENTER("db_update_routine");
|
DBUG_ENTER("db_update_routine");
|
||||||
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
|
DBUG_PRINT("enter", ("type: %d name: %*s",
|
||||||
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened);
|
ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened);
|
||||||
if (ret == SP_OK)
|
if (ret == SP_OK)
|
||||||
{
|
{
|
||||||
store_record(table,record[1]);
|
store_record(table,record[1]);
|
||||||
@ -395,6 +402,8 @@ struct st_used_field
|
|||||||
|
|
||||||
static struct st_used_field init_fields[]=
|
static struct st_used_field init_fields[]=
|
||||||
{
|
{
|
||||||
|
// QQ Not yet
|
||||||
|
// { "Db", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
||||||
{ "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
{ "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
|
||||||
{ "Type", 9, MYSQL_TYPE_STRING, 0},
|
{ "Type", 9, MYSQL_TYPE_STRING, 0},
|
||||||
{ "Definer", 77, MYSQL_TYPE_STRING, 0},
|
{ "Definer", 77, MYSQL_TYPE_STRING, 0},
|
||||||
@ -550,16 +559,17 @@ done:
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_find_procedure(THD *thd, LEX_STRING *name)
|
sp_find_procedure(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
DBUG_ENTER("sp_find_procedure");
|
DBUG_ENTER("sp_find_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
|
DBUG_PRINT("enter", ("name: %*s.%*s",
|
||||||
|
name->m_db.length, name->m_db.str,
|
||||||
|
name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name->str, name->length)))
|
if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)))
|
||||||
{
|
{
|
||||||
if (db_find_routine(thd, TYPE_ENUM_PROCEDURE,
|
if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK)
|
||||||
name->str, name->length, &sp) == SP_OK)
|
|
||||||
sp_cache_insert(&thd->sp_proc_cache, sp);
|
sp_cache_insert(&thd->sp_proc_cache, sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,40 +590,40 @@ sp_create_procedure(THD *thd, sp_head *sp)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_drop_procedure(THD *thd, char *name, uint namelen)
|
sp_drop_procedure(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("sp_drop_procedure");
|
DBUG_ENTER("sp_drop_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", namelen, name));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
sp_cache_remove(&thd->sp_proc_cache, name, namelen);
|
sp_cache_remove(&thd->sp_proc_cache, name);
|
||||||
ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen);
|
ret= db_drop_routine(thd, TYPE_ENUM_PROCEDURE, name);
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_update_procedure(THD *thd, char *name, uint namelen,
|
sp_update_procedure(THD *thd, sp_name *name,
|
||||||
char *newname, uint newnamelen,
|
char *newname, uint newnamelen,
|
||||||
st_sp_chistics *chistics)
|
st_sp_chistics *chistics)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("sp_update_procedure");
|
DBUG_ENTER("sp_update_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", namelen, name));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
sp_cache_remove(&thd->sp_proc_cache, name, namelen);
|
sp_cache_remove(&thd->sp_proc_cache, name);
|
||||||
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen,
|
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name,
|
||||||
newname, newnamelen, chistics);
|
newname, newnamelen, chistics);
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_show_create_procedure(THD *thd, LEX_STRING *name)
|
sp_show_create_procedure(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
DBUG_ENTER("sp_show_create_procedure");
|
DBUG_ENTER("sp_show_create_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
if ((sp= sp_find_procedure(thd, name)))
|
if ((sp= sp_find_procedure(thd, name)))
|
||||||
{
|
{
|
||||||
@ -642,16 +652,15 @@ sp_show_status_procedure(THD *thd, const char *wild)
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_find_function(THD *thd, LEX_STRING *name)
|
sp_find_function(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
DBUG_ENTER("sp_find_function");
|
DBUG_ENTER("sp_find_function");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name->str, name->length)))
|
if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)))
|
||||||
{
|
{
|
||||||
if (db_find_routine(thd, TYPE_ENUM_FUNCTION,
|
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) != SP_OK)
|
||||||
name->str, name->length, &sp) != SP_OK)
|
|
||||||
sp= NULL;
|
sp= NULL;
|
||||||
else
|
else
|
||||||
sp_cache_insert(&thd->sp_func_cache, sp);
|
sp_cache_insert(&thd->sp_func_cache, sp);
|
||||||
@ -673,40 +682,40 @@ sp_create_function(THD *thd, sp_head *sp)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_drop_function(THD *thd, char *name, uint namelen)
|
sp_drop_function(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("sp_drop_function");
|
DBUG_ENTER("sp_drop_function");
|
||||||
DBUG_PRINT("enter", ("name: %*s", namelen, name));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
sp_cache_remove(&thd->sp_func_cache, name, namelen);
|
sp_cache_remove(&thd->sp_func_cache, name);
|
||||||
ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name, namelen);
|
ret= db_drop_routine(thd, TYPE_ENUM_FUNCTION, name);
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_update_function(THD *thd, char *name, uint namelen,
|
sp_update_function(THD *thd, sp_name *name,
|
||||||
char *newname, uint newnamelen,
|
char *newname, uint newnamelen,
|
||||||
st_sp_chistics *chistics)
|
st_sp_chistics *chistics)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("sp_update_procedure");
|
DBUG_ENTER("sp_update_procedure");
|
||||||
DBUG_PRINT("enter", ("name: %*s", namelen, name));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
sp_cache_remove(&thd->sp_func_cache, name, namelen);
|
sp_cache_remove(&thd->sp_func_cache, name);
|
||||||
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen,
|
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name,
|
||||||
newname, newnamelen, chistics);
|
newname, newnamelen, chistics);
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_show_create_function(THD *thd, LEX_STRING *name)
|
sp_show_create_function(THD *thd, sp_name *name)
|
||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
DBUG_ENTER("sp_show_create_function");
|
DBUG_ENTER("sp_show_create_function");
|
||||||
DBUG_PRINT("enter", ("name: %*s", name->length, name->str));
|
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
if ((sp= sp_find_function(thd, name)))
|
if ((sp= sp_find_function(thd, name)))
|
||||||
{
|
{
|
||||||
@ -728,18 +737,18 @@ sp_show_status_function(THD *thd, const char *wild)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// QQ Temporary until the function call detection in sql_lex has been reworked.
|
|
||||||
bool
|
bool
|
||||||
sp_function_exists(THD *thd, LEX_STRING *name)
|
sp_function_exists(THD *thd, LEX_STRING *name)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
bool ret= FALSE;
|
bool ret= FALSE;
|
||||||
bool opened= FALSE;
|
bool opened= FALSE;
|
||||||
|
sp_name n(*name);
|
||||||
DBUG_ENTER("sp_function_exists");
|
DBUG_ENTER("sp_function_exists");
|
||||||
|
|
||||||
if (sp_cache_lookup(&thd->sp_func_cache, name->str, name->length) ||
|
if (sp_cache_lookup(&thd->sp_func_cache, &n) ||
|
||||||
db_find_routine_aux(thd, TYPE_ENUM_FUNCTION,
|
db_find_routine_aux(thd, TYPE_ENUM_FUNCTION,
|
||||||
name->str, name->length, TL_READ,
|
&n, TL_READ,
|
||||||
&table, &opened) == SP_OK)
|
&table, &opened) == SP_OK)
|
||||||
ret= TRUE;
|
ret= TRUE;
|
||||||
if (opened)
|
if (opened)
|
||||||
@ -758,13 +767,14 @@ sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_add_fun_to_lex(LEX *lex, LEX_STRING fun)
|
sp_add_fun_to_lex(LEX *lex, sp_name *fun)
|
||||||
{
|
{
|
||||||
if (! hash_search(&lex->spfuns, (byte *)fun.str, fun.length))
|
if (! hash_search(&lex->spfuns,
|
||||||
|
(byte *)fun->m_name.str, fun->m_name.length))
|
||||||
{
|
{
|
||||||
LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING));
|
LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING));
|
||||||
ls->str= sql_strmake(fun.str, fun.length);
|
ls->str= sql_strmake(fun->m_name.str, fun->m_name.length);
|
||||||
ls->length= fun.length;
|
ls->length= fun->m_name.length;
|
||||||
|
|
||||||
my_hash_insert(&lex->spfuns, (byte *)ls);
|
my_hash_insert(&lex->spfuns, (byte *)ls);
|
||||||
}
|
}
|
||||||
@ -793,15 +803,17 @@ sp_cache_functions(THD *thd, LEX *lex)
|
|||||||
for (uint i=0 ; i < h->records ; i++)
|
for (uint i=0 ; i < h->records ; i++)
|
||||||
{
|
{
|
||||||
LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
|
LEX_STRING *ls= (LEX_STRING *)hash_element(h, i);
|
||||||
|
sp_name name(*ls);
|
||||||
|
|
||||||
if (! sp_cache_lookup(&thd->sp_func_cache, ls->str, ls->length))
|
if (! sp_cache_lookup(&thd->sp_func_cache, &name))
|
||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
LEX *oldlex= thd->lex;
|
LEX *oldlex= thd->lex;
|
||||||
LEX *newlex= new st_lex;
|
LEX *newlex= new st_lex;
|
||||||
|
|
||||||
thd->lex= newlex;
|
thd->lex= newlex;
|
||||||
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, ls->str, ls->length, &sp) == SP_OK)
|
if (db_find_routine(thd, TYPE_ENUM_FUNCTION, &name, &sp)
|
||||||
|
== SP_OK)
|
||||||
{
|
{
|
||||||
ret= sp_cache_functions(thd, newlex);
|
ret= sp_cache_functions(thd, newlex);
|
||||||
delete newlex;
|
delete newlex;
|
||||||
@ -836,11 +848,13 @@ create_string(THD *thd, ulong *lenp,
|
|||||||
char *buf, *ptr;
|
char *buf, *ptr;
|
||||||
ulong buflen;
|
ulong buflen;
|
||||||
|
|
||||||
buflen= 100 + namelen + paramslen + returnslen + bodylen + chistics->comment.length;
|
buflen= 100 + namelen + paramslen + returnslen + bodylen +
|
||||||
|
chistics->comment.length;
|
||||||
if (!(buf= thd->alloc(buflen)))
|
if (!(buf= thd->alloc(buflen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ptr= strxmov(buf, "CREATE ", (type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
|
ptr= strxmov(buf, "CREATE ",
|
||||||
|
(type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
|
||||||
" `", name, "`(", params, ")", NullS);
|
" `", name, "`(", params, ")", NullS);
|
||||||
|
|
||||||
if (type == TYPE_ENUM_FUNCTION)
|
if (type == TYPE_ENUM_FUNCTION)
|
||||||
|
19
sql/sp.h
19
sql/sp.h
@ -29,47 +29,46 @@
|
|||||||
#define SP_INTERNAL_ERROR -7
|
#define SP_INTERNAL_ERROR -7
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_find_procedure(THD *thd, LEX_STRING *name);
|
sp_find_procedure(THD *thd, sp_name *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_create_procedure(THD *thd, sp_head *sp);
|
sp_create_procedure(THD *thd, sp_head *sp);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_drop_procedure(THD *thd, char *name, uint namelen);
|
sp_drop_procedure(THD *thd, sp_name *name);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_update_procedure(THD *thd, char *name, uint namelen,
|
sp_update_procedure(THD *thd, sp_name *name,
|
||||||
char *newname, uint newnamelen,
|
char *newname, uint newnamelen,
|
||||||
st_sp_chistics *chistics);
|
st_sp_chistics *chistics);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_show_create_procedure(THD *thd, LEX_STRING *name);
|
sp_show_create_procedure(THD *thd, sp_name *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_show_status_procedure(THD *thd, const char *wild);
|
sp_show_status_procedure(THD *thd, const char *wild);
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_find_function(THD *thd, LEX_STRING *name);
|
sp_find_function(THD *thd, sp_name *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_create_function(THD *thd, sp_head *sp);
|
sp_create_function(THD *thd, sp_head *sp);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_drop_function(THD *thd, char *name, uint namelen);
|
sp_drop_function(THD *thd, sp_name *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_update_function(THD *thd, char *name, uint namelen,
|
sp_update_function(THD *thd, sp_name *name,
|
||||||
char *newname, uint newnamelen,
|
char *newname, uint newnamelen,
|
||||||
st_sp_chistics *chistics);
|
st_sp_chistics *chistics);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_show_create_function(THD *thd, LEX_STRING *name);
|
sp_show_create_function(THD *thd, sp_name *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_show_status_function(THD *thd, const char *wild);
|
sp_show_status_function(THD *thd, const char *wild);
|
||||||
|
|
||||||
// QQ Temporary until the function call detection in sql_lex has been reworked.
|
|
||||||
bool
|
bool
|
||||||
sp_function_exists(THD *thd, LEX_STRING *name);
|
sp_function_exists(THD *thd, LEX_STRING *name);
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ sp_function_exists(THD *thd, LEX_STRING *name);
|
|||||||
// This is needed since we have to read the functions before we
|
// This is needed since we have to read the functions before we
|
||||||
// do anything else.
|
// do anything else.
|
||||||
void
|
void
|
||||||
sp_add_fun_to_lex(LEX *lex, LEX_STRING fun);
|
sp_add_fun_to_lex(LEX *lex, sp_name *fun);
|
||||||
void
|
void
|
||||||
sp_merge_funs(LEX *dst, LEX *src);
|
sp_merge_funs(LEX *dst, LEX *src);
|
||||||
int
|
int
|
||||||
|
@ -71,7 +71,7 @@ sp_cache_insert(sp_cache **cp, sp_head *sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_cache_lookup(sp_cache **cp, char *name, uint namelen)
|
sp_cache_lookup(sp_cache **cp, sp_name *name)
|
||||||
{
|
{
|
||||||
ulong v;
|
ulong v;
|
||||||
sp_cache *c= *cp;
|
sp_cache *c= *cp;
|
||||||
@ -89,11 +89,11 @@ sp_cache_lookup(sp_cache **cp, char *name, uint namelen)
|
|||||||
c->version= v;
|
c->version= v;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return c->lookup(name, namelen);
|
return c->lookup(name->m_name.str, name->m_name.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sp_cache_remove(sp_cache **cp, char *name, uint namelen)
|
sp_cache_remove(sp_cache **cp, sp_name *name)
|
||||||
{
|
{
|
||||||
sp_cache *c= *cp;
|
sp_cache *c= *cp;
|
||||||
bool found= FALSE;
|
bool found= FALSE;
|
||||||
@ -109,7 +109,7 @@ sp_cache_remove(sp_cache **cp, char *name, uint namelen)
|
|||||||
if (c->version < v)
|
if (c->version < v)
|
||||||
c->remove_all();
|
c->remove_all();
|
||||||
else
|
else
|
||||||
found= c->remove(name, namelen);
|
found= c->remove(name->m_name.str, name->m_name.length);
|
||||||
c->version= v+1;
|
c->version= v+1;
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
|
@ -35,10 +35,10 @@ void sp_cache_clear(sp_cache **cp);
|
|||||||
void sp_cache_insert(sp_cache **cp, sp_head *sp);
|
void sp_cache_insert(sp_cache **cp, sp_head *sp);
|
||||||
|
|
||||||
/* Lookup an SP in cache */
|
/* Lookup an SP in cache */
|
||||||
sp_head *sp_cache_lookup(sp_cache **cp, char *name, uint namelen);
|
sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
|
||||||
|
|
||||||
/* Remove an SP from cache. Returns true if something was removed */
|
/* Remove an SP from cache. Returns true if something was removed */
|
||||||
bool sp_cache_remove(sp_cache **cp, char *name, uint namelen);
|
bool sp_cache_remove(sp_cache **cp, sp_name *name);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -130,6 +130,32 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
|
|||||||
DBUG_RETURN(it);
|
DBUG_RETURN(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* sp_name
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
sp_name::init_qname(THD *thd)
|
||||||
|
{
|
||||||
|
m_qname.length= m_db.length+m_name.length+1;
|
||||||
|
m_qname.str= alloc_root(&thd->mem_root, m_qname.length+1);
|
||||||
|
sprintf(m_qname.str, "%*s.%*s",
|
||||||
|
m_db.length, (m_db.length ? m_db.str : ""),
|
||||||
|
m_name.length, m_name.str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* sp_head
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
void *
|
void *
|
||||||
sp_head::operator new(size_t size)
|
sp_head::operator new(size_t size)
|
||||||
{
|
{
|
||||||
@ -178,22 +204,42 @@ sp_head::init(LEX *lex)
|
|||||||
lex->spcont= m_pcont= new sp_pcontext();
|
lex->spcont= m_pcont= new sp_pcontext();
|
||||||
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
|
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
|
||||||
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
|
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
|
||||||
m_name.str= m_params.str= m_retstr.str= m_body.str= m_defstr.str= 0;
|
m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
|
||||||
m_name.length= m_params.length= m_retstr.length= m_body.length=
|
m_body.str= m_defstr.str= 0;
|
||||||
m_defstr.length= 0;
|
m_qname.length= m_db.length= m_name.length= m_params.length=
|
||||||
|
m_retstr.length= m_body.length= m_defstr.length= 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_head::init_strings(THD *thd, LEX *lex, LEX_STRING *name)
|
sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("sp_head::init_strings");
|
DBUG_ENTER("sp_head::init_strings");
|
||||||
/* During parsing, we must use thd->mem_root */
|
/* During parsing, we must use thd->mem_root */
|
||||||
MEM_ROOT *root= &thd->mem_root;
|
MEM_ROOT *root= &thd->mem_root;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("name: %*s", name->length, name->str));
|
DBUG_PRINT("info", ("name: %*.s%*s",
|
||||||
m_name.length= name->length;
|
name->m_db.length, name->m_db.str,
|
||||||
m_name.str= strmake_root(root, name->str, name->length);
|
name->m_name.length, name->m_name.str));
|
||||||
|
/* We have to copy strings to get them into the right memroot */
|
||||||
|
if (name->m_db.length == 0)
|
||||||
|
{
|
||||||
|
m_db.length= strlen(thd->db);
|
||||||
|
m_db.str= strmake_root(root, thd->db, m_db.length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_db.length= name->m_db.length;
|
||||||
|
m_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
|
||||||
|
}
|
||||||
|
m_name.length= name->m_name.length;
|
||||||
|
m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
|
||||||
|
|
||||||
|
if (name->m_qname.length == 0)
|
||||||
|
name->init_qname(thd);
|
||||||
|
m_qname.length= name->m_qname.length;
|
||||||
|
m_qname.str= strmake_root(root, name->m_qname.str, m_qname.length);
|
||||||
|
|
||||||
m_params.length= m_param_end- m_param_begin;
|
m_params.length= m_param_end- m_param_begin;
|
||||||
m_params.str= strmake_root(root,
|
m_params.str= strmake_root(root,
|
||||||
(char *)m_param_begin, m_params.length);
|
(char *)m_param_begin, m_params.length);
|
||||||
@ -1089,10 +1135,13 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
|
|||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Security context swapping
|
// Security context swapping
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
void
|
void
|
||||||
sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
|
sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp)
|
||||||
|
@ -37,6 +37,35 @@ class sp_instr;
|
|||||||
struct sp_cond_type;
|
struct sp_cond_type;
|
||||||
struct sp_pvar;
|
struct sp_pvar;
|
||||||
|
|
||||||
|
class sp_name : public Sql_alloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LEX_STRING m_db;
|
||||||
|
LEX_STRING m_name;
|
||||||
|
LEX_STRING m_qname;
|
||||||
|
|
||||||
|
sp_name(LEX_STRING name)
|
||||||
|
: m_name(name)
|
||||||
|
{
|
||||||
|
m_db.str= m_qname.str= 0;
|
||||||
|
m_db.length= m_qname.length= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_name(LEX_STRING db, LEX_STRING name)
|
||||||
|
: m_db(db), m_name(name)
|
||||||
|
{
|
||||||
|
m_qname.str= 0;
|
||||||
|
m_qname.length= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init. the qualified name from the db and name.
|
||||||
|
void init_qname(THD *thd); // thd for memroot allocation
|
||||||
|
|
||||||
|
~sp_name()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
class sp_head : public Sql_alloc
|
class sp_head : public Sql_alloc
|
||||||
{
|
{
|
||||||
sp_head(const sp_head &); /* Prevent use of these */
|
sp_head(const sp_head &); /* Prevent use of these */
|
||||||
@ -56,6 +85,8 @@ public:
|
|||||||
List<char *> m_calls; // Called procedures.
|
List<char *> m_calls; // Called procedures.
|
||||||
List<char *> m_tables; // Used tables.
|
List<char *> m_tables; // Used tables.
|
||||||
#endif
|
#endif
|
||||||
|
LEX_STRING m_qname; // db.name
|
||||||
|
LEX_STRING m_db;
|
||||||
LEX_STRING m_name;
|
LEX_STRING m_name;
|
||||||
LEX_STRING m_params;
|
LEX_STRING m_params;
|
||||||
LEX_STRING m_retstr; // For FUNCTIONs only
|
LEX_STRING m_retstr; // For FUNCTIONs only
|
||||||
@ -83,7 +114,7 @@ public:
|
|||||||
|
|
||||||
// Initialize strings after parsing header
|
// Initialize strings after parsing header
|
||||||
void
|
void
|
||||||
init_strings(THD *thd, LEX *lex, LEX_STRING *name);
|
init_strings(THD *thd, LEX *lex, sp_name *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
create(THD *thd);
|
create(THD *thd);
|
||||||
|
@ -22,6 +22,7 @@ class Table_ident;
|
|||||||
class sql_exchange;
|
class sql_exchange;
|
||||||
class LEX_COLUMN;
|
class LEX_COLUMN;
|
||||||
class sp_head;
|
class sp_head;
|
||||||
|
class sp_name;
|
||||||
class sp_instr;
|
class sp_instr;
|
||||||
class sp_pcontext;
|
class sp_pcontext;
|
||||||
|
|
||||||
@ -604,6 +605,7 @@ typedef struct st_lex
|
|||||||
bool derived_tables;
|
bool derived_tables;
|
||||||
bool safe_to_cache_query;
|
bool safe_to_cache_query;
|
||||||
sp_head *sphead;
|
sp_head *sphead;
|
||||||
|
sp_name *spname;
|
||||||
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
|
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
|
||||||
sp_pcontext *spcont;
|
sp_pcontext *spcont;
|
||||||
HASH spfuns; /* Called functions */
|
HASH spfuns; /* Called functions */
|
||||||
|
@ -3101,9 +3101,9 @@ mysql_execute_command(THD *thd)
|
|||||||
if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
|
if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
if ((sph= sp_find_function(thd, &lex->udf.name)))
|
if ((sph= sp_find_function(thd, lex->spname)))
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str);
|
net_printf(thd, ER_UDF_EXISTS, lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!(res = mysql_create_function(thd,&lex->udf)))
|
if (!(res = mysql_create_function(thd,&lex->udf)))
|
||||||
@ -3441,9 +3441,10 @@ mysql_execute_command(THD *thd)
|
|||||||
{
|
{
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
|
|
||||||
if (!(sp= sp_find_procedure(thd, &lex->udf.name)))
|
if (!(sp= sp_find_procedure(thd, lex->spname)))
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE", lex->udf.name);
|
net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE",
|
||||||
|
lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3521,10 +3522,10 @@ mysql_execute_command(THD *thd)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
|
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
|
||||||
res= sp_update_procedure(thd, lex->udf.name.str, lex->udf.name.length,
|
res= sp_update_procedure(thd, lex->spname,
|
||||||
lex->name, newname_len, &lex->sp_chistics);
|
lex->name, newname_len, &lex->sp_chistics);
|
||||||
else
|
else
|
||||||
res= sp_update_function(thd, lex->udf.name.str, lex->udf.name.length,
|
res= sp_update_function(thd, lex->spname,
|
||||||
lex->name, newname_len, &lex->sp_chistics);
|
lex->name, newname_len, &lex->sp_chistics);
|
||||||
switch (res)
|
switch (res)
|
||||||
{
|
{
|
||||||
@ -3532,10 +3533,12 @@ mysql_execute_command(THD *thd)
|
|||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
break;
|
break;
|
||||||
case SP_KEY_NOT_FOUND:
|
case SP_KEY_NOT_FOUND:
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),lex->udf.name);
|
net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
|
||||||
|
lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
default:
|
default:
|
||||||
net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex),lex->udf.name);
|
net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex),
|
||||||
|
lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3544,19 +3547,20 @@ mysql_execute_command(THD *thd)
|
|||||||
case SQLCOM_DROP_FUNCTION:
|
case SQLCOM_DROP_FUNCTION:
|
||||||
{
|
{
|
||||||
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
|
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
|
||||||
res= sp_drop_procedure(thd, lex->udf.name.str, lex->udf.name.length);
|
res= sp_drop_procedure(thd, lex->spname);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res= sp_drop_function(thd, lex->udf.name.str, lex->udf.name.length);
|
res= sp_drop_function(thd, lex->spname);
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
if (res == SP_KEY_NOT_FOUND)
|
if (res == SP_KEY_NOT_FOUND)
|
||||||
{
|
{
|
||||||
udf_func *udf = find_udf(lex->udf.name.str, lex->udf.name.length);
|
udf_func *udf = find_udf(lex->spname->m_name.str,
|
||||||
|
lex->spname->m_name.length);
|
||||||
if (udf)
|
if (udf)
|
||||||
{
|
{
|
||||||
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0))
|
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0))
|
||||||
goto error;
|
goto error;
|
||||||
if (!(res = mysql_drop_function(thd,&lex->udf.name)))
|
if (!(res = mysql_drop_function(thd,&lex->spname->m_name)))
|
||||||
{
|
{
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
break;
|
break;
|
||||||
@ -3575,17 +3579,17 @@ mysql_execute_command(THD *thd)
|
|||||||
{
|
{
|
||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
||||||
SP_COM_STRING(lex), lex->udf.name.str);
|
SP_COM_STRING(lex), lex->spname->m_name.str);
|
||||||
res= 0;
|
res= 0;
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
|
net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
|
||||||
lex->udf.name.str);
|
lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
default:
|
default:
|
||||||
net_printf(thd, ER_SP_DROP_FAILED, SP_COM_STRING(lex),
|
net_printf(thd, ER_SP_DROP_FAILED, SP_COM_STRING(lex),
|
||||||
lex->udf.name.str);
|
lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3593,16 +3597,16 @@ mysql_execute_command(THD *thd)
|
|||||||
case SQLCOM_SHOW_CREATE_PROC:
|
case SQLCOM_SHOW_CREATE_PROC:
|
||||||
{
|
{
|
||||||
res= -1;
|
res= -1;
|
||||||
if (lex->udf.name.length > NAME_LEN)
|
if (lex->spname->m_name.length > NAME_LEN)
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_TOO_LONG_IDENT, lex->udf.name.str);
|
net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
res= sp_show_create_procedure(thd, &lex->udf.name);
|
res= sp_show_create_procedure(thd, lex->spname);
|
||||||
if (res != SP_OK)
|
if (res != SP_OK)
|
||||||
{ /* We don't distinguish between errors for now */
|
{ /* We don't distinguish between errors for now */
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
||||||
SP_COM_STRING(lex), lex->udf.name.str);
|
SP_COM_STRING(lex), lex->spname->m_name.str);
|
||||||
res= 0;
|
res= 0;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -3610,16 +3614,16 @@ mysql_execute_command(THD *thd)
|
|||||||
}
|
}
|
||||||
case SQLCOM_SHOW_CREATE_FUNC:
|
case SQLCOM_SHOW_CREATE_FUNC:
|
||||||
{
|
{
|
||||||
if (lex->udf.name.length > NAME_LEN)
|
if (lex->spname->m_name.length > NAME_LEN)
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_TOO_LONG_IDENT, lex->udf.name.str);
|
net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
res= sp_show_create_function(thd, &lex->udf.name);
|
res= sp_show_create_function(thd, lex->spname);
|
||||||
if (res != SP_OK)
|
if (res != SP_OK)
|
||||||
{ /* We don't distinguish between errors for now */
|
{ /* We don't distinguish between errors for now */
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
||||||
SP_COM_STRING(lex), lex->udf.name.str);
|
SP_COM_STRING(lex), lex->spname->m_name.str);
|
||||||
res= 0;
|
res= 0;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
|
|||||||
chooser_compare_func_creator boolfunc2creator;
|
chooser_compare_func_creator boolfunc2creator;
|
||||||
struct sp_cond_type *spcondtype;
|
struct sp_cond_type *spcondtype;
|
||||||
struct { int vars, conds, hndlrs, curs; } spblock;
|
struct { int vars, conds, hndlrs, curs; } spblock;
|
||||||
|
sp_name *spname;
|
||||||
struct st_lex *lex;
|
struct st_lex *lex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,6 +772,7 @@ END_OF_INPUT
|
|||||||
%type <spcondtype> sp_cond sp_hcond
|
%type <spcondtype> sp_cond sp_hcond
|
||||||
%type <spblock> sp_decls sp_decl
|
%type <spblock> sp_decls sp_decl
|
||||||
%type <lex> sp_cursor_stmt
|
%type <lex> sp_cursor_stmt
|
||||||
|
%type <spname> sp_name
|
||||||
|
|
||||||
%type <NONE>
|
%type <NONE>
|
||||||
'-' '+' '*' '/' '%' '(' ')'
|
'-' '+' '*' '/' '%' '(' ')'
|
||||||
@ -1019,15 +1021,15 @@ create:
|
|||||||
lex->name=$4.str;
|
lex->name=$4.str;
|
||||||
lex->create_info.options=$3;
|
lex->create_info.options=$3;
|
||||||
}
|
}
|
||||||
| CREATE udf_func_type FUNCTION_SYM IDENT_sys
|
| CREATE udf_func_type FUNCTION_SYM sp_name
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->udf.name = $4;
|
lex->spname= $4;
|
||||||
lex->udf.type= $2;
|
lex->udf.type= $2;
|
||||||
}
|
}
|
||||||
create_function_tail
|
create_function_tail
|
||||||
{}
|
{}
|
||||||
| CREATE PROCEDURE ident
|
| CREATE PROCEDURE sp_name
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
@ -1078,7 +1080,7 @@ create:
|
|||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
|
||||||
lex->sphead->init_strings(YYTHD, lex, &$3);
|
lex->sphead->init_strings(YYTHD, lex, $3);
|
||||||
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||||
/* Restore flag if it was cleared above */
|
/* Restore flag if it was cleared above */
|
||||||
if (lex->sphead->m_old_cmq)
|
if (lex->sphead->m_old_cmq)
|
||||||
@ -1087,11 +1089,17 @@ create:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
sp_name:
|
||||||
|
IDENT_sys '.' IDENT_sys { $$= new sp_name($1, $3); }
|
||||||
|
| IDENT_sys { $$= new sp_name($1); }
|
||||||
|
;
|
||||||
|
|
||||||
create_function_tail:
|
create_function_tail:
|
||||||
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
|
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command = SQLCOM_CREATE_FUNCTION;
|
lex->sql_command = SQLCOM_CREATE_FUNCTION;
|
||||||
|
lex->udf.name = lex->spname->m_name;
|
||||||
lex->udf.returns=(Item_result) $2;
|
lex->udf.returns=(Item_result) $2;
|
||||||
lex->udf.dl=$4.str;
|
lex->udf.dl=$4.str;
|
||||||
}
|
}
|
||||||
@ -1153,7 +1161,7 @@ create_function_tail:
|
|||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
||||||
sp->init_strings(YYTHD, lex, &lex->udf.name);
|
sp->init_strings(YYTHD, lex, lex->spname);
|
||||||
/* Restore flag if it was cleared above */
|
/* Restore flag if it was cleared above */
|
||||||
if (sp->m_old_cmq)
|
if (sp->m_old_cmq)
|
||||||
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
||||||
@ -1203,12 +1211,12 @@ sp_suid:
|
|||||||
;
|
;
|
||||||
|
|
||||||
call:
|
call:
|
||||||
CALL_SYM IDENT_sys
|
CALL_SYM sp_name
|
||||||
{
|
{
|
||||||
LEX *lex = Lex;
|
LEX *lex = Lex;
|
||||||
|
|
||||||
lex->sql_command= SQLCOM_CALL;
|
lex->sql_command= SQLCOM_CALL;
|
||||||
lex->udf.name= $2;
|
lex->spname= $2;
|
||||||
lex->value_list.empty();
|
lex->value_list.empty();
|
||||||
}
|
}
|
||||||
'(' sp_cparam_list ')' {}
|
'(' sp_cparam_list ')' {}
|
||||||
@ -2723,7 +2731,7 @@ alter:
|
|||||||
lex->sql_command=SQLCOM_ALTER_DB;
|
lex->sql_command=SQLCOM_ALTER_DB;
|
||||||
lex->name=$3.str;
|
lex->name=$3.str;
|
||||||
}
|
}
|
||||||
| ALTER PROCEDURE ident
|
| ALTER PROCEDURE sp_name
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
|
||||||
@ -2736,9 +2744,9 @@ alter:
|
|||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
|
||||||
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
|
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
|
||||||
lex->udf.name= $3;
|
lex->spname= $3;
|
||||||
}
|
}
|
||||||
| ALTER FUNCTION_SYM ident
|
| ALTER FUNCTION_SYM sp_name
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
|
||||||
@ -2751,7 +2759,7 @@ alter:
|
|||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
|
||||||
lex->sql_command= SQLCOM_ALTER_FUNCTION;
|
lex->sql_command= SQLCOM_ALTER_FUNCTION;
|
||||||
lex->udf.name= $3;
|
lex->spname= $3;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -3908,12 +3916,13 @@ simple_expr:
|
|||||||
if (sp_function_exists(YYTHD, &$1))
|
if (sp_function_exists(YYTHD, &$1))
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
sp_name *name= new sp_name($1);
|
||||||
|
|
||||||
sp_add_fun_to_lex(lex, $1);
|
sp_add_fun_to_lex(lex, name);
|
||||||
if ($3)
|
if ($3)
|
||||||
$$= new Item_func_sp($1, *$3);
|
$$= new Item_func_sp(name, *$3);
|
||||||
else
|
else
|
||||||
$$= new Item_func_sp($1);
|
$$= new Item_func_sp(name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4830,19 +4839,19 @@ drop:
|
|||||||
lex->drop_if_exists=$3;
|
lex->drop_if_exists=$3;
|
||||||
lex->name=$4.str;
|
lex->name=$4.str;
|
||||||
}
|
}
|
||||||
| DROP FUNCTION_SYM if_exists IDENT_sys opt_restrict
|
| DROP FUNCTION_SYM if_exists sp_name opt_restrict
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command = SQLCOM_DROP_FUNCTION;
|
lex->sql_command = SQLCOM_DROP_FUNCTION;
|
||||||
lex->drop_if_exists= $3;
|
lex->drop_if_exists= $3;
|
||||||
lex->udf.name= $4;
|
lex->spname= $4;
|
||||||
}
|
}
|
||||||
| DROP PROCEDURE if_exists IDENT_sys opt_restrict
|
| DROP PROCEDURE if_exists sp_name opt_restrict
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command = SQLCOM_DROP_PROCEDURE;
|
lex->sql_command = SQLCOM_DROP_PROCEDURE;
|
||||||
lex->drop_if_exists= $3;
|
lex->drop_if_exists= $3;
|
||||||
lex->udf.name= $4;
|
lex->spname= $4;
|
||||||
}
|
}
|
||||||
| DROP USER
|
| DROP USER
|
||||||
{
|
{
|
||||||
@ -5321,15 +5330,19 @@ show_param:
|
|||||||
{
|
{
|
||||||
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
|
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
|
||||||
}
|
}
|
||||||
| CREATE PROCEDURE ident
|
| CREATE PROCEDURE sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
|
LEX *lex= Lex;
|
||||||
Lex->udf.name= $3;
|
|
||||||
|
lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
|
||||||
|
lex->spname= $3;
|
||||||
}
|
}
|
||||||
| CREATE FUNCTION_SYM ident
|
| CREATE FUNCTION_SYM sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
|
LEX *lex= Lex;
|
||||||
Lex->udf.name= $3;
|
|
||||||
|
lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
|
||||||
|
lex->spname= $3;
|
||||||
}
|
}
|
||||||
| PROCEDURE STATUS_SYM wild
|
| PROCEDURE STATUS_SYM wild
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user