mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge 10.4 to 10.5
This commit is contained in:
150
sql/sql_udf.cc
150
sql/sql_udf.cc
@ -58,6 +58,8 @@ static udf_func *add_udf(LEX_CSTRING *name, Item_result ret,
|
||||
const char *dl, Item_udftype typ);
|
||||
static void del_udf(udf_func *udf);
|
||||
static void *find_udf_dl(const char *dl);
|
||||
static bool find_udf_everywhere(THD* thd, const LEX_CSTRING &name,
|
||||
TABLE *table);
|
||||
|
||||
static const char *init_syms(udf_func *tmp, char *nm)
|
||||
{
|
||||
@ -430,6 +432,41 @@ static udf_func *add_udf(LEX_CSTRING *name, Item_result ret, const char *dl,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
Find record with the udf in the udf func table
|
||||
|
||||
@param exact_name udf name
|
||||
@param table table of mysql.func
|
||||
|
||||
@retval TRUE found
|
||||
@retral FALSE not found
|
||||
*/
|
||||
|
||||
static bool find_udf_in_table(const LEX_CSTRING &exact_name, TABLE *table)
|
||||
{
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(exact_name.str, exact_name.length, &my_charset_bin);
|
||||
return (!table->file->ha_index_read_idx_map(table->record[0], 0,
|
||||
(uchar*) table->field[0]->ptr,
|
||||
HA_WHOLE_KEY,
|
||||
HA_READ_KEY_EXACT));
|
||||
}
|
||||
|
||||
static bool remove_udf_in_table(const LEX_CSTRING &exact_name, TABLE *table)
|
||||
{
|
||||
if (find_udf_in_table(exact_name, table))
|
||||
{
|
||||
int error;
|
||||
if ((error= table->file->ha_delete_row(table->record[0])))
|
||||
{
|
||||
table->file->print_error(error, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Drop user defined function.
|
||||
|
||||
@ -446,8 +483,7 @@ static int mysql_drop_function_internal(THD *thd, udf_func *udf, TABLE *table)
|
||||
{
|
||||
DBUG_ENTER("mysql_drop_function_internal");
|
||||
|
||||
const char *exact_name_str= udf->name.str;
|
||||
size_t exact_name_len= udf->name.length;
|
||||
const LEX_CSTRING exact_name= udf->name;
|
||||
|
||||
del_udf(udf);
|
||||
/*
|
||||
@ -460,18 +496,17 @@ static int mysql_drop_function_internal(THD *thd, udf_func *udf, TABLE *table)
|
||||
if (!table)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin);
|
||||
if (!table->file->ha_index_read_idx_map(table->record[0], 0,
|
||||
(uchar*) table->field[0]->ptr,
|
||||
HA_WHOLE_KEY,
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
int error;
|
||||
if (unlikely((error= table->file->ha_delete_row(table->record[0]))))
|
||||
table->file->print_error(error, MYF(0));
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
bool ret= remove_udf_in_table(exact_name, table);
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
static TABLE *open_udf_func_table(THD *thd)
|
||||
{
|
||||
TABLE_LIST tables;
|
||||
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_FUNC_NAME,
|
||||
&MYSQL_FUNC_NAME, TL_WRITE);
|
||||
return open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
@ -518,8 +553,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
||||
if (check_ident_length(&udf->name))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_FUNC_NAME, 0, TL_WRITE);
|
||||
table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
|
||||
table= open_udf_func_table(thd);
|
||||
|
||||
mysql_rwlock_wrlock(&THR_LOCK_udf);
|
||||
DEBUG_SYNC(current_thd, "mysql_create_function_after_lock");
|
||||
@ -620,42 +654,65 @@ err:
|
||||
}
|
||||
|
||||
|
||||
int mysql_drop_function(THD *thd, const LEX_CSTRING *udf_name)
|
||||
enum drop_udf_result mysql_drop_function(THD *thd, const LEX_CSTRING *udf_name)
|
||||
{
|
||||
TABLE *table;
|
||||
TABLE_LIST tables;
|
||||
udf_func *udf;
|
||||
DBUG_ENTER("mysql_drop_function");
|
||||
|
||||
if (!initialized)
|
||||
if (thd->locked_tables_mode)
|
||||
{
|
||||
if (opt_noacl)
|
||||
my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
|
||||
else
|
||||
my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES),
|
||||
MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ERROR);
|
||||
}
|
||||
|
||||
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_FUNC_NAME, 0, TL_WRITE);
|
||||
table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
|
||||
if (!(table= open_udf_func_table(thd)))
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ERROR);
|
||||
|
||||
// Fast pre-check
|
||||
if (!mysql_rwlock_tryrdlock(&THR_LOCK_udf))
|
||||
{
|
||||
bool found= find_udf_everywhere(thd, *udf_name, table);
|
||||
mysql_rwlock_unlock(&THR_LOCK_udf);
|
||||
if (!found)
|
||||
{
|
||||
close_mysql_tables(thd);
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ABSENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
close_mysql_tables(thd);
|
||||
if (opt_noacl)
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ABSENT); // SP should be checked
|
||||
|
||||
my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES), MYF(0));
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ERROR);
|
||||
}
|
||||
|
||||
mysql_rwlock_wrlock(&THR_LOCK_udf);
|
||||
|
||||
// re-check under protection
|
||||
if (!find_udf_everywhere(thd, *udf_name, table))
|
||||
{
|
||||
close_mysql_tables(thd);
|
||||
mysql_rwlock_unlock(&THR_LOCK_udf);
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ABSENT);
|
||||
}
|
||||
|
||||
if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 0))
|
||||
goto err;
|
||||
|
||||
|
||||
DEBUG_SYNC(current_thd, "mysql_drop_function_after_lock");
|
||||
|
||||
if (!(udf= (udf_func*) my_hash_search(&udf_hash, (uchar*) udf_name->str,
|
||||
(uint) udf_name->length)) )
|
||||
{
|
||||
if (thd->lex->check_exists)
|
||||
{
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_FUNCTION_NOT_DEFINED,
|
||||
ER_THD(thd, ER_FUNCTION_NOT_DEFINED),
|
||||
udf_name->str);
|
||||
goto done;
|
||||
}
|
||||
|
||||
my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
|
||||
goto err;
|
||||
if (remove_udf_in_table(*udf_name, table))
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (mysql_drop_function_internal(thd, udf, table))
|
||||
@ -669,13 +726,24 @@ done:
|
||||
while binlogging, to avoid binlog inconsistency.
|
||||
*/
|
||||
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ERROR);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
close_mysql_tables(thd);
|
||||
DBUG_RETURN(UDF_DEL_RESULT_DELETED);
|
||||
|
||||
err:
|
||||
close_mysql_tables(thd);
|
||||
mysql_rwlock_unlock(&THR_LOCK_udf);
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(UDF_DEL_RESULT_ERROR);
|
||||
}
|
||||
|
||||
static bool find_udf_everywhere(THD* thd, const LEX_CSTRING &name,
|
||||
TABLE *table)
|
||||
{
|
||||
if (initialized && my_hash_search(&udf_hash, (uchar*) name.str, name.length))
|
||||
return true;
|
||||
|
||||
return find_udf_in_table(name, table);
|
||||
}
|
||||
|
||||
#endif /* HAVE_DLOPEN */
|
||||
|
Reference in New Issue
Block a user