summaryrefslogtreecommitdiff
path: root/sql/sql_udf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_udf.cc')
-rw-r--r--sql/sql_udf.cc152
1 files changed, 103 insertions, 49 deletions
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 456a6bd4058..4ccd4948b58 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -90,10 +90,11 @@ static char *init_syms(udf_func *tmp, char *nm)
*/
if (!tmp->func_init && !tmp->func_deinit && tmp->type != UDFTYPE_AGGREGATE)
{
+ THD *thd= current_thd;
if (!opt_allow_suspicious_udfs)
return nm;
- if (current_thd->variables.log_warnings)
- sql_print_warning(ER(ER_CANT_FIND_DL_ENTRY), nm);
+ if (thd->variables.log_warnings)
+ sql_print_warning(ER_THD(thd, ER_CANT_FIND_DL_ENTRY), nm);
}
return 0;
}
@@ -207,7 +208,7 @@ void udf_init()
On windows we must check both FN_LIBCHAR and '/'.
*/
if (check_valid_path(dl_name, strlen(dl_name)) ||
- check_string_char_length(&name, "", NAME_CHAR_LEN,
+ check_string_char_length(&name, 0, NAME_CHAR_LEN,
system_charset_info, 1))
{
sql_print_error("Invalid row in mysql.func table for function '%.64s'",
@@ -226,13 +227,13 @@ void udf_init()
if (dl == NULL)
{
char dlpath[FN_REFLEN];
- strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl,
- NullS);
+ strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl, NullS);
(void) unpack_filename(dlpath, dlpath);
if (!(dl= dlopen(dlpath, RTLD_NOW)))
{
/* Print warning to log */
- sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl, errno, dlerror());
+ sql_print_error(ER_THD(new_thd, ER_CANT_OPEN_LIBRARY),
+ tmp->dl, errno, my_dlerror(dlpath));
/* Keep the udf in the hash so that we can remove it later */
continue;
}
@@ -243,7 +244,7 @@ void udf_init()
char buf[SAFE_NAME_LEN+16], *missing;
if ((missing= init_syms(tmp, buf)))
{
- sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), missing);
+ sql_print_error(ER_THD(new_thd, ER_CANT_FIND_DL_ENTRY), missing);
del_udf(tmp);
if (new_dl)
dlclose(dl);
@@ -413,6 +414,50 @@ static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
return tmp;
}
+/*
+ Drop user defined function.
+
+ @param thd Thread handler.
+ @param udf Existing udf_func pointer which is to be deleted.
+ @param table mysql.func table reference (opened and locked)
+
+ Assumption
+
+ - udf is not null.
+ - table is already opened and locked
+*/
+static int mysql_drop_function_internal(THD *thd, udf_func *udf, TABLE *table)
+{
+ DBUG_ENTER("mysql_drop_function_internal");
+
+ char *exact_name_str= udf->name.str;
+ uint exact_name_len= udf->name.length;
+
+ del_udf(udf);
+ /*
+ Close the handle if this was function that was found during boot or
+ CREATE FUNCTION and it's not in use by any other udf function
+ */
+ if (udf->dlhandle && !find_udf_dl(udf->dl))
+ dlclose(udf->dlhandle);
+
+ 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 ((error= table->file->ha_delete_row(table->record[0])))
+ table->file->print_error(error, MYF(0));
+ }
+ DBUG_RETURN(0);
+}
+
/**
Create a user defined function.
@@ -439,7 +484,8 @@ int mysql_create_function(THD *thd,udf_func *udf)
udf->name.str,
"UDFs are unavailable with the --skip-grant-tables option");
else
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES),
+ MYF(0));
DBUG_RETURN(1);
}
@@ -450,7 +496,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
*/
if (check_valid_path(udf->dl, strlen(udf->dl)))
{
- my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0));
+ my_message(ER_UDF_NO_PATHS, ER_THD(thd, ER_UDF_NO_PATHS), MYF(0));
DBUG_RETURN(1);
}
if (check_ident_length(&udf->name))
@@ -462,10 +508,26 @@ int mysql_create_function(THD *thd,udf_func *udf)
mysql_rwlock_wrlock(&THR_LOCK_udf);
DEBUG_SYNC(current_thd, "mysql_create_function_after_lock");
- if ((my_hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length)))
+ if ((u_d= (udf_func*) my_hash_search(&udf_hash, (uchar*) udf->name.str,
+ udf->name.length)))
{
- my_error(ER_UDF_EXISTS, MYF(0), udf->name.str);
- goto err;
+ if (thd->lex->create_info.or_replace())
+ {
+ if ((error= mysql_drop_function_internal(thd, u_d, table)))
+ goto err;
+ }
+ else if (thd->lex->create_info.if_not_exists())
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UDF_EXISTS,
+ ER_THD(thd, ER_UDF_EXISTS), udf->name.str);
+
+ goto done;
+ }
+ else
+ {
+ my_error(ER_UDF_EXISTS, MYF(0), udf->name.str);
+ goto err;
+ }
}
if (!(dl = find_udf_dl(udf->dl)))
{
@@ -475,10 +537,10 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (!(dl = dlopen(dlpath, RTLD_NOW)))
{
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0),
+ udf->dl, errno, my_dlerror(dlpath));
DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)",
udf->dl, errno, dlerror()));
- my_error(ER_CANT_OPEN_LIBRARY, MYF(0),
- udf->dl, errno, dlerror());
goto err;
}
new_dl=1;
@@ -492,16 +554,16 @@ int mysql_create_function(THD *thd,udf_func *udf)
goto err;
}
}
- udf->name.str=strdup_root(&mem,udf->name.str);
- udf->dl=strdup_root(&mem,udf->dl);
+ udf->name.str= strdup_root(&mem,udf->name.str);
+ udf->dl= strdup_root(&mem,udf->dl);
if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type)))
goto err;
- u_d->dlhandle = dl;
- u_d->func=udf->func;
- u_d->func_init=udf->func_init;
- u_d->func_deinit=udf->func_deinit;
- u_d->func_clear=udf->func_clear;
- u_d->func_add=udf->func_add;
+ u_d->dlhandle= dl;
+ u_d->func= udf->func;
+ u_d->func_init= udf->func_init;
+ u_d->func_deinit= udf->func_deinit;
+ u_d->func_clear= udf->func_clear;
+ u_d->func_add= udf->func_add;
/* create entry in mysql.func table */
@@ -523,6 +585,8 @@ int mysql_create_function(THD *thd,udf_func *udf)
del_udf(u_d);
goto err;
}
+
+done:
mysql_rwlock_unlock(&THR_LOCK_udf);
/* Binlog the create function. */
@@ -531,7 +595,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
DBUG_RETURN(0);
- err:
+err:
if (new_dl)
dlclose(dl);
mysql_rwlock_unlock(&THR_LOCK_udf);
@@ -544,8 +608,6 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
TABLE *table;
TABLE_LIST tables;
udf_func *udf;
- char *exact_name_str;
- uint exact_name_len;
DBUG_ENTER("mysql_drop_function");
if (!initialized)
@@ -553,7 +615,8 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
if (opt_noacl)
my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
else
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES),
+ MYF(0));
DBUG_RETURN(1);
}
@@ -563,35 +626,26 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
mysql_rwlock_wrlock(&THR_LOCK_udf);
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 (!(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;
}
- exact_name_str= udf->name.str;
- exact_name_len= udf->name.length;
- del_udf(udf);
- /*
- Close the handle if this was function that was found during boot or
- CREATE FUNCTION and it's not in use by any other udf function
- */
- if (udf->dlhandle && !find_udf_dl(udf->dl))
- dlclose(udf->dlhandle);
- if (!table)
+ if (mysql_drop_function_internal(thd, udf, table))
goto err;
- 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 ((error = table->file->ha_delete_row(table->record[0])))
- table->file->print_error(error, MYF(0));
- }
+
+done:
mysql_rwlock_unlock(&THR_LOCK_udf);
/*