Files
oceanbase/src/sql/engine/user_defined_function/ob_udf_util.h
2023-01-12 19:02:33 +08:00

180 lines
7.7 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OB_UDF_UTIL_H_
#define OB_UDF_UTIL_H_
#include <dlfcn.h>
#include "share/schema/ob_udf.h"
#include "sql/engine/user_defined_function/ob_user_defined_function.h"
#include "sql/engine/user_defined_function/ob_udf_registration_types.h"
#include "sql/engine/expr/ob_expr.h"
#include "rpc/obmysql/ob_mysql_global.h"
#include "sql/engine/expr/ob_expr_res_type.h"
namespace oceanbase
{
namespace common
{
class ObExprCtx;
class ObExprTypeCtx;
}
namespace sql
{
#define GET_AGG_UDF_ID(GROUP_ID, COL_COUNT, AGG_COUNT, AGG_IDX) \
((GROUP_ID)*((COL_COUNT)+(AGG_COUNT)) + AGG_IDX)
class ObPhysicalPlanCtx;
class obUdfConstArgs;
class ObUdfFunction;
class ObUdfUtil
{
public :
/*
* for example, if the defined func named 'my_udf_add', we wanna load the auxiliary function.
* then we use 'my_udf_add_init' 'my_udf_add_deinit' 'my_udf_add_clear' or 'my_udf_add_add' to load
* these functions (actually the max_expand_length is '_deinit\0').
* */
static const int UDF_MAX_EXPAND_LENGTH = 10;
/* from mysql */
static const int UDF_MAX_MBWIDTH = 3; /* Max multibyte sequence */
static const int UDF_MAX_FIELD_CHARLENGTH = 255;
static const int UDF_MAX_FIELD_WIDTH = (UDF_MAX_FIELD_CHARLENGTH * UDF_MAX_MBWIDTH + 1); /* Max column width +1 */
static const int UDF_DECIMAL_BUFF_LENGTH = 9; /** maximum length of buffer in our big digits (uint32). */
static const int UDF_DECIMAL_MAX_POSSIBLE_PRECISION = (UDF_DECIMAL_BUFF_LENGTH * 9); /* the number of digits that my_decimal can possibly contain */
static const int UDF_DECIMAL_MAX_STR_LENGTH = (UDF_DECIMAL_MAX_POSSIBLE_PRECISION + 2);
public :
enum load_function_type {
UDF_ORIGIN,
UDF_INIT,
UDF_DEINIT,
UDF_CLEAR,
UDF_ADD,
};
static const char *load_function_postfix[5];
const char * get_postfix_name(load_function_type type) {
return load_function_postfix[type];
}
public :
/*
* calc udf's result type
* */
static int calc_udf_result_type(common::ObIAllocator &allocator,
const ObUdfFunction *udf_func,
const share::schema::ObUDFMeta &udf_meta,
const common::ObIArray<common::ObString> &udf_attributes,
const common::ObIArray<ObExprResType> &udf_attributes_types,
ObExprResType &type,
ObExprResType *param_types,
const int64_t param_num,
common::ObExprTypeCtx &type_ctx);
/*
* load all function to our server
* */
static void unload_so(ObUdfSoHandler &handler);
static int load_so(const common::ObString dl, ObUdfSoHandler &handler);
template <typename T>
static int load_function(const common::ObString &name,
const ObUdfSoHandler handler,
const common::ObString &postfix,
const bool ignore_error,
T &func);
/*
* helper function
* */
static int deep_copy_udf_args_cell(common::ObIAllocator &allocator, int64_t param_num, const common::ObObj *src_objs, common::ObObj *& dst_objs);
static int set_udf_args(common::ObExprCtx &expr_ctx, int64_t param_num, common::ObObj *src_objs, ObUdfArgs &udf_args);
// set the copied datum (with %alloc) to udf arg.
static int set_udf_arg(common::ObIAllocator &alloc,
const ObDatum &src_datum,
const ObExpr &expr,
ObUdfArgs &udf_arg,
const int64_t arg_idx);
static int init_udf_args(common::ObIAllocator &allocator,
const common::ObIArray<common::ObString> &udf_attributes,
const common::ObIArray<ObExprResType> &udf_attributes_types,
ObUdfArgs &udf_args);
static int init_const_args(common::ObIAllocator &allocator,
const common::ObIArray<ObUdfConstArgs> &const_results,
ObUdfArgs &udf_args,
common::ObExprCtx &expr_ctx);
static void construct_udf_args(ObUdfArgs &args);
static void construct_udf_init(ObUdfInit &init);
static const char* result_type_name(enum UdfItemResult result);
static void print_udf_args_to_log(const ObUdfArgs &args);
static void print_udf_init_to_log(const ObUdfInit &init);
static void assign_udf_args(const ObUdfArgs &src_args, ObUdfArgs &dst_args);
static void assign_udf_init(const ObUdfInit &src_init, ObUdfInit &dst_init);
static int is_udf_ctx_valid(const ObUdfArgs &src_args, const ObUdfInit &dst_init);
/*
* interface to invoke udf
* */
static int process_udf_func(share::schema::ObUDF::UDFRetType ret_type,
common::ObIAllocator &allocator,
ObUdfInit &udf_init,
ObUdfArgs &udf_args,
const ObUdfFuncAny func,
common::ObObj &result);
static int process_str(common::ObIAllocator &allocator, ObUdfInit &udf_init, ObUdfArgs &udf_args, const ObUdfFuncAny func, common::ObObj &result);
static int process_dec(common::ObIAllocator &allocator, ObUdfInit &udf_init, ObUdfArgs &udf_args, const ObUdfFuncAny func, common::ObObj &result);
static int process_int(common::ObIAllocator &allocator, ObUdfInit &udf_init, ObUdfArgs &udf_args, const ObUdfFuncAny func, common::ObObj &result);
static int process_real(common::ObIAllocator &allocator, ObUdfInit &udf_init, ObUdfArgs &udf_args, const ObUdfFuncAny func, common::ObObj &result);
static int process_add_func(ObUdfInit &udf_init, ObUdfArgs &udf_args, const ObUdfFuncAdd func);
static int process_clear_func(ObUdfInit &udf_init, const ObUdfFuncClear func);
/*
* convert function, from ob type to mysql field type
* */
static int convert_ob_type_to_udf_type(common::ObObjType ob_type, UdfItemResult &udf_type);
static int convert_mysql_type_to_udf_type(const obmysql::EMySQLFieldType &mysql_type, UdfItemResult &udf_type);
// return ObNullType for invalid udf_type
static common::ObObjType udf_type2obj_type(const UdfItemResult udf_type);
};
template <typename T>
int ObUdfUtil::load_function(const common::ObString &name,
const ObUdfSoHandler handler,
const common::ObString &postfix,
const bool ignore_error,
T &func)
{
int ret = common::OB_SUCCESS;
T func_tmp = nullptr;
int func_len = common::OB_MAX_UDF_NAME_LENGTH + ObUdfUtil::UDF_MAX_EXPAND_LENGTH;
char func_name[common::OB_MAX_UDF_NAME_LENGTH + ObUdfUtil::UDF_MAX_EXPAND_LENGTH];
MEMSET(func_name, 0, func_len);
MEMCPY(func_name, name.ptr(), name.length());
char *postfix_start_pos = func_name + name.length();
MEMCPY(postfix_start_pos, postfix.ptr(), postfix.length());
if (OB_ISNULL(((func_tmp = (T)dlsym(handler, func_name))))) {
ret = ignore_error ? common::OB_SUCCESS : common::OB_ERR_UNEXPECTED;
SQL_LOG(WARN, "Can't find symbol", K(ret), K(name), K(func_name));
} else {
func = func_tmp;
SQL_LOG(DEBUG, "get func_init function", K(handler), K(func));
}
return ret;
}
}
}
#endif