summaryrefslogtreecommitdiff
path: root/sql/sql_udf.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2014-12-15 17:41:15 +0400
committerAlexander Barkov <bar@mariadb.org>2014-12-15 17:41:15 +0400
commit2dbd26932d0c22cb333a73262db8135779c6f098 (patch)
tree8a7ecf919349f219ca4555a3f8387011a38286a3 /sql/sql_udf.cc
parent48ed8ab2155b31d36358b2efd348f3036a294971 (diff)
downloadmariadb-git-2dbd26932d0c22cb333a73262db8135779c6f098.tar.gz
MDEV-7283 UDF: CREATE OR REPLACE, CREATE IF NOT EXISTS, DROP IF EXISTS
MDEV-7282 SP: CREATE OR REPLACE, CREATE IF NOT EXISTS
Diffstat (limited to 'sql/sql_udf.cc')
-rw-r--r--sql/sql_udf.cc124
1 files changed, 87 insertions, 37 deletions
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index bd5732c3696..2354f120041 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -413,6 +413,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.
@@ -466,10 +510,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(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)))
{
@@ -496,16 +556,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 */
@@ -527,6 +587,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. */
@@ -535,7 +597,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);
@@ -548,8 +610,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)
@@ -567,35 +627,25 @@ 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(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);
/*