1
0
mirror of https://github.com/MariaDB/server.git synced 2025-05-29 21:42:28 +03:00

MDEV-31174 New class Native_functions_hash

This commit is contained in:
Alexander Barkov 2023-04-28 14:41:27 +04:00
parent 9b6f87b62a
commit 01ea779149
7 changed files with 101 additions and 53 deletions

View File

@ -140,7 +140,7 @@ Create_func_trt_trx_sees<X> Create_func_trt_trx_sees<X>::s_singleton;
#define BUILDER(F) & F::s_singleton #define BUILDER(F) & F::s_singleton
static Native_func_registry func_array[] = static const Native_func_registry func_array_vers[] =
{ {
{ { C_STRING_WITH_LEN("TRT_BEGIN_TS") }, BUILDER(Create_func_trt<TR_table::FLD_BEGIN_TS>)}, { { C_STRING_WITH_LEN("TRT_BEGIN_TS") }, BUILDER(Create_func_trt<TR_table::FLD_BEGIN_TS>)},
{ { C_STRING_WITH_LEN("TRT_COMMIT_ID") }, BUILDER(Create_func_trt<TR_table::FLD_COMMIT_ID>)}, { { C_STRING_WITH_LEN("TRT_COMMIT_ID") }, BUILDER(Create_func_trt<TR_table::FLD_COMMIT_ID>)},
@ -164,7 +164,7 @@ static int versioning_plugin_init(void *p __attribute__ ((unused)))
{ {
DBUG_ENTER("versioning_plugin_init"); DBUG_ENTER("versioning_plugin_init");
// No need in locking since we so far single-threaded // No need in locking since we so far single-threaded
int res= item_create_append(func_array); int res= native_functions_hash.append(func_array_vers);
if (res) if (res)
{ {
my_message(ER_PLUGIN_IS_NOT_LOADED, "Can't append function array" , MYF(0)); my_message(ER_PLUGIN_IS_NOT_LOADED, "Can't append function array" , MYF(0));
@ -177,7 +177,7 @@ static int versioning_plugin_init(void *p __attribute__ ((unused)))
static int versioning_plugin_deinit(void *p __attribute__ ((unused))) static int versioning_plugin_deinit(void *p __attribute__ ((unused)))
{ {
DBUG_ENTER("versioning_plugin_deinit"); DBUG_ENTER("versioning_plugin_deinit");
(void) item_create_remove(func_array); (void) native_functions_hash.remove(func_array_vers);
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -7249,7 +7249,7 @@ Create_func_year_week::create_native(THD *thd, const LEX_CSTRING *name,
- keep 1 line per entry, it makes grep | sort easier - keep 1 line per entry, it makes grep | sort easier
*/ */
Native_func_registry func_array[] = const Native_func_registry func_array[] =
{ {
{ { STRING_WITH_LEN("ABS") }, BUILDER(Create_func_abs)}, { { STRING_WITH_LEN("ABS") }, BUILDER(Create_func_abs)},
{ { STRING_WITH_LEN("ACOS") }, BUILDER(Create_func_acos)}, { { STRING_WITH_LEN("ACOS") }, BUILDER(Create_func_acos)},
@ -7609,9 +7609,10 @@ Native_func_registry func_array[] =
{ {0, 0}, NULL} { {0, 0}, NULL}
}; };
size_t func_array_length= sizeof(func_array) / sizeof(Native_func_registry) - 1;
static HASH native_functions_hash; const size_t func_array_length= sizeof(func_array) / sizeof(Native_func_registry) - 1;
Native_functions_hash native_functions_hash;
extern "C" uchar* extern "C" uchar*
get_native_fct_hash_key(const uchar *buff, size_t *length, get_native_fct_hash_key(const uchar *buff, size_t *length,
@ -7628,85 +7629,89 @@ get_native_fct_hash_key(const uchar *buff, size_t *length,
startup only (before going multi-threaded) startup only (before going multi-threaded)
*/ */
int item_create_init() bool Native_functions_hash::init(size_t count)
{ {
DBUG_ENTER("item_create_init"); DBUG_ENTER("Native_functions_hash::init");
if (my_hash_init(& native_functions_hash, if (my_hash_init(this,
system_charset_info, system_charset_info,
array_elements(func_array), (ulong) count,
0, 0,
0, 0,
(my_hash_get_key) get_native_fct_hash_key, (my_hash_get_key) get_native_fct_hash_key,
NULL, /* Nothing to free */ NULL, /* Nothing to free */
MYF(0))) MYF(0)))
DBUG_RETURN(1); DBUG_RETURN(true);
DBUG_RETURN(item_create_append(func_array)); DBUG_RETURN(false);
} }
int item_create_append(Native_func_registry array[])
{
Native_func_registry *func;
DBUG_ENTER("item_create_append"); bool Native_functions_hash::append(const Native_func_registry array[])
{
const Native_func_registry *func;
DBUG_ENTER("Native_functions_hash::append");
for (func= array; func->builder != NULL; func++) for (func= array; func->builder != NULL; func++)
{ {
if (my_hash_insert(& native_functions_hash, (uchar*) func)) if (my_hash_insert(this, (uchar*) func))
DBUG_RETURN(1); DBUG_RETURN(true);
} }
#ifndef DBUG_OFF #ifndef DBUG_OFF
for (uint i=0 ; i < native_functions_hash.records ; i++) for (uint i=0 ; i < records ; i++)
{ {
func= (Native_func_registry*) my_hash_element(& native_functions_hash, i); func= (Native_func_registry*) my_hash_element(this, i);
DBUG_PRINT("info", ("native function: %s length: %u", DBUG_PRINT("info", ("native function: %s length: %u",
func->name.str, (uint) func->name.length)); func->name.str, (uint) func->name.length));
} }
#endif #endif
DBUG_RETURN(0); DBUG_RETURN(false);
} }
int item_create_remove(Native_func_registry array[])
{
Native_func_registry *func;
DBUG_ENTER("item_create_remove"); bool Native_functions_hash::remove(const Native_func_registry array[])
{
const Native_func_registry *func;
DBUG_ENTER("Native_functions_hash::remove");
for (func= array; func->builder != NULL; func++) for (func= array; func->builder != NULL; func++)
{ {
if (my_hash_delete(& native_functions_hash, (uchar*) func)) if (my_hash_delete(this, (uchar*) func))
DBUG_RETURN(1); DBUG_RETURN(true);
} }
DBUG_RETURN(0); DBUG_RETURN(false);
} }
/* /*
Empty the hash table for native functions. Empty the hash table for native functions.
Note: this code is not thread safe, and is intended to be used at server Note: this code is not thread safe, and is intended to be used at server
shutdown only (after thread requests have been executed). shutdown only (after thread requests have been executed).
*/ */
void item_create_cleanup() void Native_functions_hash::cleanup()
{ {
DBUG_ENTER("item_create_cleanup"); DBUG_ENTER("Native_functions_hash::cleanup");
my_hash_free(& native_functions_hash); my_hash_free(this);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
Create_func * Create_func *
find_native_function_builder(THD *thd, const LEX_CSTRING *name) Native_functions_hash::find(THD *thd, const LEX_CSTRING &name) const
{ {
Native_func_registry *func; Native_func_registry *func;
Create_func *builder= NULL; Create_func *builder= NULL;
/* Thread safe */ /* Thread safe */
func= (Native_func_registry*) my_hash_search(&native_functions_hash, func= (Native_func_registry*) my_hash_search(this,
(uchar*) name->str, (uchar*) name.str,
name->length); name.length);
if (func) if (func)
{ {
@ -7716,6 +7721,19 @@ find_native_function_builder(THD *thd, const LEX_CSTRING *name)
return builder; return builder;
} }
int item_create_init()
{
return native_functions_hash.init(func_array, array_elements(func_array));
}
void item_create_cleanup()
{
native_functions_hash.cleanup();
}
Create_qfunc * Create_qfunc *
find_qualified_function_builder(THD *thd) find_qualified_function_builder(THD *thd)
{ {

View File

@ -144,16 +144,6 @@ protected:
}; };
/**
Find the native function builder associated with a given function name.
@param thd The current thread
@param name The native function name
@return The native function builder associated with the name, or NULL
*/
extern Create_func *find_native_function_builder(THD *thd,
const LEX_CSTRING *name);
/** /**
Find the function builder for qualified functions. Find the function builder for qualified functions.
@param thd The current thread @param thd The current thread
@ -200,9 +190,52 @@ struct Native_func_registry
Create_func *builder; Create_func *builder;
}; };
class Native_functions_hash: public HASH
{
public:
Native_functions_hash()
{
bzero(this, sizeof(*this));
}
~Native_functions_hash()
{
/*
No automatic free because objects of this type
are expected to be declared statically.
The code in cleanup() calls my_hash_free() which may not work correctly
at the very end of mariadbd shutdown.
The the upper level code should call cleanup() explicitly.
Unfortunatelly, it's not possible to use DBUG_ASSERT(!records) here,
because the server terminates using exit() in some cases,
e.g. in the test main.named_pipe with the "Create named pipe failed"
error.
*/
}
bool init(size_t count);
bool init(const Native_func_registry array[], size_t count)
{
return init(count) || append(array);
}
bool append(const Native_func_registry array[]);
bool remove(const Native_func_registry array[]);
void cleanup();
/**
Find the native function builder associated with a given function name.
@param thd The current thread
@param name The native function name
@return The native function builder associated with the name, or NULL
*/
Create_func *find(THD *thd, const LEX_CSTRING &name) const;
};
extern MYSQL_PLUGIN_IMPORT Native_functions_hash native_functions_hash;
extern const Native_func_registry func_array[];
extern const size_t func_array_length;
int item_create_init(); int item_create_init();
int item_create_append(Native_func_registry array[]);
int item_create_remove(Native_func_registry array[]);
void item_create_cleanup(); void item_create_cleanup();
Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list); Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list);

View File

@ -943,7 +943,7 @@ bool is_lex_native_function(const LEX_CSTRING *name)
bool is_native_function(THD *thd, const LEX_CSTRING *name) bool is_native_function(THD *thd, const LEX_CSTRING *name)
{ {
if (find_native_function_builder(thd, name)) if (native_functions_hash.find(thd, *name))
return true; return true;
if (is_lex_native_function(name)) if (is_lex_native_function(name))

View File

@ -76,9 +76,6 @@ extern size_t symbols_length;
extern SYMBOL sql_functions[]; extern SYMBOL sql_functions[];
extern size_t sql_functions_length; extern size_t sql_functions_length;
extern Native_func_registry func_array[];
extern size_t func_array_length;
enum enum_i_s_events_fields enum enum_i_s_events_fields
{ {
ISE_EVENT_CATALOG= 0, ISE_EVENT_CATALOG= 0,

View File

@ -11485,7 +11485,7 @@ function_call_generic:
This will be revised with WL#2128 (SQL PATH) This will be revised with WL#2128 (SQL PATH)
*/ */
builder= find_native_function_builder(thd, &$1); builder= native_functions_hash.find(thd, $1);
if (builder) if (builder)
{ {
item= builder->create_func(thd, &$1, $4); item= builder->create_func(thd, &$1, $4);

View File

@ -11600,7 +11600,7 @@ function_call_generic:
This will be revised with WL#2128 (SQL PATH) This will be revised with WL#2128 (SQL PATH)
*/ */
builder= find_native_function_builder(thd, &$1); builder= native_functions_hash.find(thd, $1);
if (builder) if (builder)
{ {
item= builder->create_func(thd, &$1, $4); item= builder->create_func(thd, &$1, $4);