diff options
author | Alexander Barkov <bar@mariadb.org> | 2014-12-15 17:41:15 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2014-12-15 17:41:15 +0400 |
commit | 2dbd26932d0c22cb333a73262db8135779c6f098 (patch) | |
tree | 8a7ecf919349f219ca4555a3f8387011a38286a3 /sql/sql_udf.cc | |
parent | 48ed8ab2155b31d36358b2efd348f3036a294971 (diff) | |
download | mariadb-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.cc | 124 |
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); /* |