[FEAT MERGE] [v4.2] add table generator and several random utility functions
This commit is contained in:
@ -133,6 +133,8 @@
|
||||
#include "ob_expr_fun_default.h"
|
||||
#include "ob_expr_substrb.h"
|
||||
#include "ob_expr_remainder.h"
|
||||
#include "ob_expr_rand.h"
|
||||
#include "ob_expr_randstr.h"
|
||||
#include "ob_expr_random.h"
|
||||
#include "ob_expr_width_bucket.h"
|
||||
#include "ob_expr_sys_extract_utc.h"
|
||||
@ -310,6 +312,12 @@
|
||||
#include "ob_expr_cast.h"
|
||||
#include "ob_expr_icu_version.h"
|
||||
#include "ob_expr_sql_mode_convert.h"
|
||||
#include "ob_expr_generator_func.h"
|
||||
#include "ob_expr_random.h"
|
||||
#include "ob_expr_randstr.h"
|
||||
#include "ob_expr_zipf.h"
|
||||
#include "ob_expr_normal.h"
|
||||
#include "ob_expr_uniform.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -317,6 +325,11 @@ using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
//
|
||||
// this file is for function serialization
|
||||
// Without maps defined here, you can not get correct function ptr
|
||||
// when serialize between different observer versions
|
||||
//
|
||||
extern int cast_eval_arg(const ObExpr &, ObEvalCtx &, ObDatum &);
|
||||
extern int anytype_to_varchar_char_explicit(const ObExpr &, ObEvalCtx &, ObDatum &);
|
||||
extern int anytype_anytype_explicit(const ObExpr &, ObEvalCtx &, ObDatum &);
|
||||
@ -712,8 +725,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
ObExprFunDefault::calc_default_expr, /* 316 */
|
||||
ObExprSubstrb::calc_substrb_expr, /* 317 */
|
||||
ObExprRemainder::calc_remainder_expr, /* 318 */
|
||||
ObExprRandom::calc_random_expr_const_seed, /* 319 */
|
||||
ObExprRandom::calc_random_expr_nonconst_seed, /* 320 */
|
||||
ObExprRand::calc_random_expr_const_seed, /* 319 */
|
||||
ObExprRand::calc_random_expr_nonconst_seed, /* 320 */
|
||||
ObExprWidthBucket::calc_width_bucket_expr, /* 321 */
|
||||
ObExprSysExtractUtc::calc_sys_extract_utc, /* 322 */
|
||||
ObExprToClob::calc_to_clob_expr, /* 323 */
|
||||
@ -980,6 +993,15 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
ObExprDecode::eval_decode, /* 580 */
|
||||
ObExprICUVersion::eval_version, /* 581 */
|
||||
ObExprCast::eval_cast_multiset, /* 582 */
|
||||
ObExprGeneratorFunc::eval_next_value, /* 583 */
|
||||
ObExprZipf::eval_next_value, /* 584 */
|
||||
ObExprNormal::eval_next_value, /* 585 */
|
||||
ObExprUniform::eval_next_int_value, /* 586 */
|
||||
ObExprUniform::eval_next_real_value, /* 587 */
|
||||
ObExprUniform::eval_next_number_value, /* 588 */
|
||||
ObExprRandom::calc_random_expr_const_seed, /* 589 */
|
||||
ObExprRandom::calc_random_expr_nonconst_seed, /* 590 */
|
||||
ObExprRandstr::calc_random_str /* 591 */
|
||||
};
|
||||
|
||||
static ObExpr::EvalBatchFunc g_expr_eval_batch_functions[] = {
|
||||
|
||||
105
src/sql/engine/expr/ob_expr_generator_func.cpp
Normal file
105
src/sql/engine/expr/ob_expr_generator_func.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "sql/engine/expr/ob_expr_generator_func.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
ObExprGeneratorFunc::ObExprGeneratorFunc(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_GENERATOR, "generator", 1, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprGeneratorFunc::~ObExprGeneratorFunc()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprGeneratorFunc::calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &limit,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
limit.set_calc_type(ObIntType);
|
||||
type.set_int();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprGeneratorFunc::eval_next_value(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprGeneratorFuncCtx *generator_ctx = NULL;
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
if (OB_ISNULL(generator_ctx = static_cast<ObExprGeneratorFuncCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, generator_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else if (OB_ISNULL(generator_ctx)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("generator ctx is NULL", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum *limit_datum = NULL;
|
||||
if (OB_UNLIKELY(1 != expr.arg_cnt_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected arg_cnt", K(ret), K(expr.arg_cnt_));
|
||||
} else if (OB_FAIL(expr.eval_param_value(ctx, limit_datum))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_UNLIKELY(limit_datum->is_null())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "generator function. The argument should be an integer.");
|
||||
} else {
|
||||
int64_t limit = limit_datum->get_int();
|
||||
int64_t next_value_res = (++generator_ctx->curr_value_);
|
||||
if (OB_UNLIKELY(next_value_res > limit)) {
|
||||
ret = OB_ITER_END;
|
||||
} else {
|
||||
res_datum.set_int(next_value_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprGeneratorFunc::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
if (OB_UNLIKELY(1 != raw_expr.get_param_count())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param count for in expr", K(ret));
|
||||
} else if (OB_ISNULL(raw_expr.get_param_expr(0))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid null param expr", K(ret));
|
||||
} else if (!raw_expr.get_param_expr(0)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "generator function. The argument should be a constant integer");
|
||||
}
|
||||
rt_expr.eval_func_ = ObExprGeneratorFunc::eval_next_value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
50
src/sql/engine/expr/ob_expr_generator_func.h
Normal file
50
src/sql/engine/expr/ob_expr_generator_func.h
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 OCEANBASE_SQL_OB_EXPR_FUNC_GENERATOR_FUNC_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_GENERATOR_FUNC_H_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprGeneratorFunc : public ObFuncExprOperator
|
||||
{
|
||||
class ObExprGeneratorFuncCtx: public ObExprOperatorCtx
|
||||
{
|
||||
public:
|
||||
ObExprGeneratorFuncCtx() : curr_value_(0) {}
|
||||
~ObExprGeneratorFuncCtx() = default;
|
||||
// increment 1 after every call to expr evaluation
|
||||
int64_t curr_value_;
|
||||
};
|
||||
public:
|
||||
explicit ObExprGeneratorFunc(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprGeneratorFunc();
|
||||
virtual int calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &limit,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual bool need_rt_ctx() const override { return true; }
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_next_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprGeneratorFunc);
|
||||
};
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
|
||||
#endif /* OCEANBASE_SQL_OB_EXPR_FUNC_GENERATOR_FUNC_H_ */
|
||||
140
src/sql/engine/expr/ob_expr_normal.cpp
Normal file
140
src/sql/engine/expr/ob_expr_normal.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "sql/engine/expr/ob_expr_normal.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
|
||||
int ObExprNormal::ObExprNormalCtx::initialize(ObEvalCtx &ctx, const ObExpr &expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum &p1 = expr.locate_param_datum(ctx, 0);
|
||||
ObDatum &p2 = expr.locate_param_datum(ctx, 1);
|
||||
if (p1.is_null() || p2.is_null()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "normal function. first and second argument must be constant expression.");
|
||||
} else {
|
||||
double mean = p1.get_double();
|
||||
double stddev = p2.get_double();
|
||||
std::normal_distribution<double>::param_type param(mean, stddev);
|
||||
normal_dist_.param(param);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObExprNormal::ObExprNormalCtx::generate_next_value(int64_t seed, double &result)
|
||||
{
|
||||
normal_dist_.reset();
|
||||
gen_.seed(static_cast<uint64_t>(seed));
|
||||
result = normal_dist_(gen_);
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
ObExprNormal::ObExprNormal(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_NORMAL, "normal", 3, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprNormal::~ObExprNormal()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprNormal::calc_result_type3(ObExprResType &result_type,
|
||||
ObExprResType &mean,
|
||||
ObExprResType &stddev,
|
||||
ObExprResType &rand_expr,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
mean.set_calc_type(ObDoubleType);
|
||||
stddev.set_calc_type(ObDoubleType);
|
||||
rand_expr.set_calc_type(ObIntType);
|
||||
result_type.set_double();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNormal::eval_next_value(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprNormalCtx *normal_ctx = NULL;
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
|
||||
if (OB_FAIL(expr.eval_param_value(ctx))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_ISNULL(normal_ctx = static_cast<ObExprNormalCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, normal_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else if (OB_ISNULL(normal_ctx)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("normal ctx is NULL", K(ret));
|
||||
} else if (OB_FAIL(normal_ctx->initialize(ctx, expr))) {
|
||||
LOG_WARN("fail init normal context", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum &rand_val = expr.locate_param_datum(ctx, 2);
|
||||
if (OB_UNLIKELY(rand_val.is_null())) {
|
||||
res_datum.set_null();
|
||||
} else {
|
||||
int64_t seed = rand_val.get_int();
|
||||
double next_value_res = 0.0;
|
||||
if (OB_FAIL(normal_ctx->generate_next_value(seed, next_value_res))) {
|
||||
LOG_WARN("fail generate next normal value", K(ret), K(seed));
|
||||
} else {
|
||||
res_datum.set_double(next_value_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNormal::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
if (OB_UNLIKELY(3 != raw_expr.get_param_count())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param count for in expr", K(ret));
|
||||
} else if (OB_ISNULL(raw_expr.get_param_expr(0)) ||
|
||||
OB_ISNULL(raw_expr.get_param_expr(1))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid null param expr", K(ret));
|
||||
} else if (!raw_expr.get_param_expr(0)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "normal function's first argument. must be a constant expression.");
|
||||
} else if (!raw_expr.get_param_expr(1)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "normal function's second argument. must be a constant expression.");
|
||||
}
|
||||
|
||||
rt_expr.eval_func_ = ObExprNormal::eval_next_value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
56
src/sql/engine/expr/ob_expr_normal.h
Normal file
56
src/sql/engine/expr/ob_expr_normal.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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 OCEANBASE_SQL_OB_EXPR_FUNC_NORMAL_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_NORMAL_H_
|
||||
|
||||
#include <random>
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprNormal : public ObFuncExprOperator
|
||||
{
|
||||
class ObExprNormalCtx: public ObExprOperatorCtx
|
||||
{
|
||||
public:
|
||||
ObExprNormalCtx() = default;
|
||||
~ObExprNormalCtx() = default;
|
||||
int initialize(ObEvalCtx &ctx, const ObExpr &expr);
|
||||
int generate_next_value(int64_t sample, double &result);
|
||||
private:
|
||||
std::normal_distribution<double> normal_dist_;
|
||||
std::mt19937_64 gen_; // map continuous small number to large sparse space
|
||||
};
|
||||
public:
|
||||
explicit ObExprNormal(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprNormal();
|
||||
virtual int calc_result_type3(ObExprResType &result_type,
|
||||
ObExprResType &mean,
|
||||
ObExprResType &stddev,
|
||||
ObExprResType &rand_expr,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual bool need_rt_ctx() const override { return true; }
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_next_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprNormal);
|
||||
};
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
|
||||
#endif /* OCEANBASE_SQL_OB_EXPR_FUNC_NORMAL_H_ */
|
||||
@ -202,7 +202,13 @@
|
||||
#include "sql/engine/expr/ob_expr_estimate_ndv.h"
|
||||
#include "sql/engine/expr/ob_expr_left.h"
|
||||
#include "sql/engine/expr/ob_expr_space.h"
|
||||
#include "sql/engine/expr/ob_expr_rand.h"
|
||||
#include "sql/engine/expr/ob_expr_randstr.h"
|
||||
#include "sql/engine/expr/ob_expr_random.h"
|
||||
#include "sql/engine/expr/ob_expr_generator_func.h"
|
||||
#include "sql/engine/expr/ob_expr_zipf.h"
|
||||
#include "sql/engine/expr/ob_expr_normal.h"
|
||||
#include "sql/engine/expr/ob_expr_uniform.h"
|
||||
#include "sql/engine/expr/ob_expr_obj_access.h"
|
||||
#include "sql/engine/expr/ob_expr_rownum.h"
|
||||
#include "sql/engine/expr/ob_expr_type_to_str.h"
|
||||
@ -762,7 +768,7 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP(ObExprBitCount);
|
||||
REG_OP(ObExprFindInSet);
|
||||
REG_OP(ObExprLeft);
|
||||
REG_OP(ObExprRandom);
|
||||
REG_OP(ObExprRand);
|
||||
REG_OP(ObExprMakeSet);
|
||||
REG_OP(ObExprEstimateNdv);
|
||||
REG_OP(ObExprSysOpOpnsize);
|
||||
@ -969,6 +975,12 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP(ObExprEncode);
|
||||
REG_OP(ObExprDecode);
|
||||
REG_OP(ObExprICUVersion);
|
||||
REG_OP(ObExprGeneratorFunc);
|
||||
REG_OP(ObExprZipf);
|
||||
REG_OP(ObExprNormal);
|
||||
REG_OP(ObExprUniform);
|
||||
REG_OP(ObExprRandom);
|
||||
REG_OP(ObExprRandstr);
|
||||
}();
|
||||
// 注册oracle系统函数
|
||||
REG_OP_ORCL(ObExprSysConnectByPath);
|
||||
@ -1258,7 +1270,12 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP_ORCL(ObExprJsonArray);
|
||||
REG_OP_ORCL(ObExprJsonObject);
|
||||
REG_OP_ORCL(ObExprTreat);
|
||||
|
||||
REG_OP_ORCL(ObExprGeneratorFunc);
|
||||
REG_OP_ORCL(ObExprZipf);
|
||||
REG_OP_ORCL(ObExprNormal);
|
||||
REG_OP_ORCL(ObExprUniform);
|
||||
REG_OP_ORCL(ObExprRandom);
|
||||
REG_OP_ORCL(ObExprRandstr);
|
||||
}
|
||||
|
||||
bool ObExprOperatorFactory::is_expr_op_type_valid(ObExprOperatorType type)
|
||||
|
||||
194
src/sql/engine/expr/ob_expr_rand.cpp
Normal file
194
src/sql/engine/expr/ob_expr_rand.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "lib/time/ob_time_utility.h" /* time */
|
||||
#include "sql/engine/expr/ob_expr_rand.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
OB_SERIALIZE_MEMBER((ObExprRand, ObFuncExprOperator), is_seed_const_);
|
||||
|
||||
const uint64_t ObExprRand::ObExprRandCtx::max_value_ = 0x3FFFFFFFL;
|
||||
|
||||
ObExprRand::ObExprRandCtx::ObExprRandCtx()
|
||||
: seed1_(1), seed2_(1)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprRand::ObExprRandCtx::~ObExprRandCtx()
|
||||
{
|
||||
}
|
||||
|
||||
void ObExprRand::ObExprRandCtx::set_seed(uint32_t seed)
|
||||
{
|
||||
seed1_ = static_cast<uint32_t>(seed * 0x10001L + 55555555L) % max_value_;
|
||||
seed2_ = static_cast<uint32_t>(seed * 0x10000001L) % max_value_;
|
||||
}
|
||||
|
||||
void ObExprRand::ObExprRandCtx::get_next_random(double &res)
|
||||
{
|
||||
seed1_ = (seed1_ * 3 + seed2_) % max_value_;
|
||||
seed2_ = (seed1_ + seed2_ + 33) % max_value_;
|
||||
res = static_cast<double> (seed1_) / static_cast<double> (max_value_);
|
||||
}
|
||||
|
||||
ObExprRand::ObExprRand(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_RAND, "rand", ZERO_OR_ONE, NOT_ROW_DIMENSION),
|
||||
is_seed_const_(true)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprRand::~ObExprRand()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprRand::calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *types,
|
||||
int64_t param_num,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(types);
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (param_num > 1) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid number of arguments", K(param_num));
|
||||
} else {
|
||||
if(param_num == 1) {
|
||||
types[0].set_calc_type(ObIntType);
|
||||
}
|
||||
type.set_double();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprRand::assign(const ObExprOperator &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObExprRand *tmp_other = dynamic_cast<const ObExprRand*>(&other);
|
||||
if (OB_UNLIKELY(NULL == tmp_other)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument. wrong type for other", K(ret), K(other));
|
||||
} else if (OB_LIKELY(this != tmp_other)) {
|
||||
if (OB_FAIL(ObExprOperator::assign(other))) {
|
||||
LOG_WARN("copy in Base class ObExprOperator failed", K(ret));
|
||||
} else {
|
||||
this->is_seed_const_ = tmp_other->is_seed_const_;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprRand::calc_random_expr_const_seed(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *seed_datum = NULL;
|
||||
if (OB_UNLIKELY(0 != expr.arg_cnt_ && 1 != expr.arg_cnt_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected arg_cnt", K(ret), K(expr.arg_cnt_));
|
||||
} else if (1 == expr.arg_cnt_ && OB_FAIL(expr.eval_param_value(ctx, seed_datum))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else {
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
ObExprRandCtx *random_ctx = NULL;
|
||||
if (OB_ISNULL(random_ctx = static_cast<ObExprRandCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, random_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else {
|
||||
uint32_t seed = 0;
|
||||
if (expr.arg_cnt_ == 1) {
|
||||
if(!seed_datum->is_null()) {
|
||||
seed = static_cast<uint32_t> (seed_datum->get_int());
|
||||
}
|
||||
} else {
|
||||
// use timestamp as the seed for rand expression
|
||||
seed = static_cast<uint32_t> (ObTimeUtility::current_time());
|
||||
}
|
||||
random_ctx->set_seed(seed);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_ISNULL(random_ctx)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("random ctx is NULL", K(ret));
|
||||
} else {
|
||||
double rand_res = 0.0;
|
||||
random_ctx->get_next_random(rand_res);
|
||||
res_datum.set_double(rand_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprRand::calc_random_expr_nonconst_seed(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *seed_datum = NULL;
|
||||
if (OB_UNLIKELY(1 != expr.arg_cnt_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected arg_cnt", K(ret), K(expr.arg_cnt_));
|
||||
} else if (OB_FAIL(expr.eval_param_value(ctx, seed_datum))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else {
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
ObExprRandCtx *random_ctx = NULL;
|
||||
if (OB_ISNULL(random_ctx = static_cast<ObExprRandCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, random_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_ISNULL(random_ctx)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("random ctx is NULL", K(ret));
|
||||
} else {
|
||||
uint32_t seed = 0;
|
||||
if(!seed_datum->is_null()) {
|
||||
seed = static_cast<uint32_t>(seed_datum->get_int());
|
||||
}
|
||||
double rand_res = 0.0;
|
||||
random_ctx->set_seed(seed);
|
||||
random_ctx->get_next_random(rand_res);
|
||||
res_datum.set_double(rand_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprRand::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
if (is_seed_const_) {
|
||||
rt_expr.eval_func_ = ObExprRand::calc_random_expr_const_seed;
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprRand::calc_random_expr_nonconst_seed;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
69
src/sql/engine/expr/ob_expr_rand.h
Normal file
69
src/sql/engine/expr/ob_expr_rand.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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 OCEANBASE_SQL_OB_EXPR_FUNC_RAND_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_RAND_H_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprRand: public ObFuncExprOperator
|
||||
{
|
||||
OB_UNIS_VERSION(1);
|
||||
class ObExprRandCtx: public ObExprOperatorCtx
|
||||
{
|
||||
public:
|
||||
ObExprRandCtx();
|
||||
virtual ~ObExprRandCtx();
|
||||
void set_seed(uint32_t seed);
|
||||
void get_next_random(double &res);
|
||||
private:
|
||||
static const uint64_t max_value_;
|
||||
uint64_t seed1_;
|
||||
uint64_t seed2_;
|
||||
};
|
||||
public:
|
||||
explicit ObExprRand(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprRand();
|
||||
virtual int calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *types,
|
||||
int64_t param_num,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
inline void set_seed_const(bool is_seed_const);
|
||||
|
||||
// engine 3.0
|
||||
virtual bool need_rt_ctx() const override { return true; }
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int calc_random_expr_const_seed(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &res_datum);
|
||||
static int calc_random_expr_nonconst_seed(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &res_datum);
|
||||
public:
|
||||
virtual int assign(const ObExprOperator &other) override;
|
||||
private:
|
||||
bool is_seed_const_;
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprRand);
|
||||
};
|
||||
|
||||
inline void ObExprRand::set_seed_const(bool is_seed_const)
|
||||
{
|
||||
is_seed_const_ = is_seed_const;
|
||||
}
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
|
||||
#endif /* OCEANBASE_SQL_OB_EXPR_FUNC_RANDOM_H_ */
|
||||
@ -22,10 +22,8 @@ namespace sql
|
||||
{
|
||||
OB_SERIALIZE_MEMBER((ObExprRandom, ObFuncExprOperator), is_seed_const_);
|
||||
|
||||
const uint64_t ObExprRandom::ObExprRandomCtx::max_value_ = 0x3FFFFFFFL;
|
||||
|
||||
ObExprRandom::ObExprRandomCtx::ObExprRandomCtx()
|
||||
: seed1_(1), seed2_(1)
|
||||
: gen_()
|
||||
{
|
||||
}
|
||||
|
||||
@ -33,21 +31,19 @@ ObExprRandom::ObExprRandomCtx::~ObExprRandomCtx()
|
||||
{
|
||||
}
|
||||
|
||||
void ObExprRandom::ObExprRandomCtx::set_seed(uint32_t seed)
|
||||
void ObExprRandom::ObExprRandomCtx::set_seed(uint64_t seed)
|
||||
{
|
||||
seed1_ = static_cast<uint32_t>(seed * 0x10001L + 55555555L) % max_value_;
|
||||
seed2_ = static_cast<uint32_t>(seed * 0x10000001L) % max_value_;
|
||||
gen_.seed(seed);
|
||||
}
|
||||
|
||||
void ObExprRandom::ObExprRandomCtx::get_next_random(double &res)
|
||||
void ObExprRandom::ObExprRandomCtx::get_next_random(int64_t &res)
|
||||
{
|
||||
seed1_ = (seed1_ * 3 + seed2_) % max_value_;
|
||||
seed2_ = (seed1_ + seed2_ + 33) % max_value_;
|
||||
res = static_cast<double> (seed1_) / static_cast<double> (max_value_);
|
||||
uint64_t rd = gen_();
|
||||
res = rd + INT64_MIN;
|
||||
}
|
||||
|
||||
ObExprRandom::ObExprRandom(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_RAND, "rand", ZERO_OR_ONE, NOT_ROW_DIMENSION),
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_RANDOM, "random", ZERO_OR_ONE, NOT_ROW_DIMENSION),
|
||||
is_seed_const_(true)
|
||||
{
|
||||
}
|
||||
@ -71,7 +67,7 @@ int ObExprRandom::calc_result_typeN(ObExprResType &type,
|
||||
if(param_num == 1) {
|
||||
types[0].set_calc_type(ObIntType);
|
||||
}
|
||||
type.set_double();
|
||||
type.set_int();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -107,33 +103,29 @@ int ObExprRandom::calc_random_expr_const_seed(const ObExpr &expr, ObEvalCtx &ctx
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
ObExprRandomCtx *random_ctx = NULL;
|
||||
if (OB_ISNULL(random_ctx = static_cast<ObExprRandomCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, random_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else {
|
||||
uint32_t seed = 0;
|
||||
if (OB_ISNULL(random_ctx = static_cast<ObExprRandomCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, random_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else {
|
||||
uint64_t seed = 0;
|
||||
if (expr.arg_cnt_ == 1) {
|
||||
if(!seed_datum->is_null()) {
|
||||
seed = static_cast<uint32_t> (seed_datum->get_int());
|
||||
seed = static_cast<uint64_t> (seed_datum->get_int());
|
||||
}
|
||||
} else {
|
||||
// use timestamp as the seed for rand expression
|
||||
seed = static_cast<uint32_t> (ObTimeUtility::current_time());
|
||||
seed = static_cast<uint64_t> (ObTimeUtility::current_time());
|
||||
}
|
||||
random_ctx->set_seed(seed);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_ISNULL(random_ctx)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("random ctx is NULL", K(ret));
|
||||
} else {
|
||||
double rand_res = 0.0;
|
||||
random_ctx->get_next_random(rand_res);
|
||||
res_datum.set_double(rand_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
int64_t rand_res = 0;
|
||||
random_ctx->get_next_random(rand_res);
|
||||
res_datum.set_int(rand_res);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -163,14 +155,14 @@ int ObExprRandom::calc_random_expr_nonconst_seed(const ObExpr &expr, ObEvalCtx &
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("random ctx is NULL", K(ret));
|
||||
} else {
|
||||
uint32_t seed = 0;
|
||||
uint64_t seed = 0;
|
||||
if(!seed_datum->is_null()) {
|
||||
seed = static_cast<uint32_t>(seed_datum->get_int());
|
||||
seed = static_cast<uint64_t>(seed_datum->get_int());
|
||||
}
|
||||
double rand_res = 0.0;
|
||||
int64_t rand_res = 0;
|
||||
random_ctx->set_seed(seed);
|
||||
random_ctx->get_next_random(rand_res);
|
||||
res_datum.set_double(rand_res);
|
||||
res_datum.set_int(rand_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#ifndef OCEANBASE_SQL_OB_EXPR_FUNC_RANDOM_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_RANDOM_H_
|
||||
|
||||
#include <random>
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
@ -27,12 +28,10 @@ class ObExprRandom: public ObFuncExprOperator
|
||||
public:
|
||||
ObExprRandomCtx();
|
||||
virtual ~ObExprRandomCtx();
|
||||
void set_seed(uint32_t seed);
|
||||
void get_next_random(double &res);
|
||||
void set_seed(uint64_t seed);
|
||||
void get_next_random(int64_t &res);
|
||||
private:
|
||||
static const uint64_t max_value_;
|
||||
uint64_t seed1_;
|
||||
uint64_t seed2_;
|
||||
std::mt19937_64 gen_;
|
||||
};
|
||||
public:
|
||||
explicit ObExprRandom(common::ObIAllocator &alloc);
|
||||
|
||||
126
src/sql/engine/expr/ob_expr_randstr.cpp
Normal file
126
src/sql/engine/expr/ob_expr_randstr.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "sql/engine/expr/ob_expr_randstr.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
ObExprRandstr::ObExprRandstr(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_RANDSTR, "randstr", 2, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprRandstr::~ObExprRandstr()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprRandstr::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &len,
|
||||
ObExprResType &seed,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
len.set_calc_type(ObIntType);
|
||||
seed.set_calc_type(ObIntType);
|
||||
if (lib::is_mysql_mode()) {
|
||||
int64_t mbmaxlen = 0;
|
||||
if (OB_FAIL(ObCharset::get_mbmaxlen_by_coll(
|
||||
common::ObCharset::get_default_collation(common::ObCharset::get_default_charset()), mbmaxlen))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_RESV_LOG(WARN, "fail to get mbmaxlen");
|
||||
} else if (0 == mbmaxlen){
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("mb maxlen invalid");
|
||||
} else {
|
||||
type.set_type(ObVarcharType);
|
||||
// must divide by mbmaxlen,
|
||||
// otherwise create table as select would fail with randstr() function
|
||||
type.set_length(OB_MAX_VARCHAR_LENGTH / mbmaxlen);
|
||||
}
|
||||
} else {
|
||||
type.set_collation_type(type_ctx.get_coll_type());
|
||||
type.set_collation_level(CS_LEVEL_IMPLICIT);
|
||||
type.set_length_semantics(LS_CHAR);
|
||||
type.set_type(ObVarcharType);
|
||||
type.set_length(OB_MAX_ORACLE_VARCHAR_LENGTH);
|
||||
}
|
||||
type.set_collation_level(common::CS_LEVEL_IMPLICIT);
|
||||
type.set_collation_type(common::ObCharset::get_default_collation(common::ObCharset::get_default_charset()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprRandstr::calc_random_str(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t max_size = 0;
|
||||
if (OB_UNLIKELY(2 != expr.arg_cnt_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected arg_cnt", K(ret), K(expr.arg_cnt_));
|
||||
} else if (OB_FAIL(expr.eval_param_value(ctx))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_FAIL(ctx.exec_ctx_.get_my_session()->get_max_allowed_packet(max_size))) {
|
||||
LOG_WARN("get max length failed", K(ret));
|
||||
} else {
|
||||
int64_t rand_res = 0;
|
||||
ObDatum &len = expr.locate_param_datum(ctx, 0);
|
||||
ObDatum &seed = expr.locate_param_datum(ctx, 1);
|
||||
if (len.is_null() || seed.is_null()) {
|
||||
res_datum.set_null();
|
||||
} else if (OB_UNLIKELY(len.get_int() < 0)) {
|
||||
res_datum.set_null();
|
||||
} else if (OB_UNLIKELY(len.get_int() > max_size)) {
|
||||
res_datum.set_null();
|
||||
LOG_USER_WARN(OB_ERR_FUNC_RESULT_TOO_LARGE, "randstr", static_cast<int>(max_size));
|
||||
} else {
|
||||
ObString output;
|
||||
ObExprStrResAlloc expr_res_alloc(expr, ctx);
|
||||
int64_t len_val = len.get_int();
|
||||
int64_t seed_val = seed.get_int();
|
||||
char *buf = static_cast<char *>(expr_res_alloc.alloc(len_val));
|
||||
if (OB_ISNULL(buf)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail alloc memory", K(ret), K(len_val));
|
||||
} else {
|
||||
static const char dict[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
for (int64_t i = 0; i < len_val && OB_SUCC(ret); ++i) {
|
||||
// LCG, Linear Congruential Method for Generating Pseudo Random Number
|
||||
seed_val = (seed_val * 1103515245 + 12345) & ((1U << 31) - 1);
|
||||
buf[i] = dict[seed_val % (sizeof(dict) - 1)];
|
||||
}
|
||||
output.assign_ptr(buf, static_cast<int32_t>(len_val));
|
||||
res_datum.set_string(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprRandstr::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
rt_expr.eval_func_ = ObExprRandstr::calc_random_str;
|
||||
return ret;
|
||||
}
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
42
src/sql/engine/expr/ob_expr_randstr.h
Normal file
42
src/sql/engine/expr/ob_expr_randstr.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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 OCEANBASE_SQL_OB_EXPR_FUNC_RANDSTR_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_RANDSTR_H_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprRandstr: public ObFuncExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprRandstr(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprRandstr();
|
||||
virtual int calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &len,
|
||||
ObExprResType &seed,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int calc_random_str(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprRandstr);
|
||||
};
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
|
||||
#endif /* OCEANBASE_SQL_OB_EXPR_FUNC_RANDSTR_H_ */
|
||||
278
src/sql/engine/expr/ob_expr_uniform.cpp
Normal file
278
src/sql/engine/expr/ob_expr_uniform.cpp
Normal file
@ -0,0 +1,278 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
|
||||
#include "sql/engine/expr/ob_expr_uniform.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "lib/json_type/ob_json_base.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
int ObExprUniform::ObExprUniformIntCtx::initialize(ObEvalCtx &ctx, const ObExpr &expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum &p1 = expr.locate_param_datum(ctx, 0);
|
||||
ObDatum &p2 = expr.locate_param_datum(ctx, 1);
|
||||
if (p1.is_null() || p2.is_null()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "uniform min/max value. must be a constant expression.");
|
||||
} else {
|
||||
int64_t a = p1.get_int();
|
||||
int64_t b = p2.get_int();
|
||||
std::uniform_int_distribution<int64_t>::param_type param(a, b);
|
||||
int_dist_.param(param);
|
||||
if (a > b) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "uniform min/max value. min value must be smaller than or equal to max value.");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprUniform::ObExprUniformIntCtx::generate_next_value(int64_t seed, int64_t &res)
|
||||
{
|
||||
gen_.seed(seed);
|
||||
res = int_dist_(gen_);
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprUniform::ObExprUniformRealCtx::initialize(ObEvalCtx &ctx, const ObExpr &expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum &p1 = expr.locate_param_datum(ctx, 0);
|
||||
ObDatum &p2 = expr.locate_param_datum(ctx, 1);
|
||||
if (p1.is_null() || p2.is_null()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "uniform min/max value. must be a constant number.");
|
||||
} else {
|
||||
double a = p1.get_double();
|
||||
double b = p2.get_double();
|
||||
std::uniform_real_distribution<double>::param_type param(a, b);
|
||||
real_dist_.param(param);
|
||||
if (a > b) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "uniform min/max value. min value must be smaller than or equal to max value.");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprUniform::ObExprUniformRealCtx::generate_next_value(int64_t seed, double &res)
|
||||
{
|
||||
gen_.seed(seed);
|
||||
res = real_dist_(gen_);
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
ObExprUniform::ObExprUniform(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_UNIFORM, "uniform", 3, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprUniform::~ObExprUniform()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprUniform::calc_result_type3(ObExprResType &result_type,
|
||||
ObExprResType &min_type,
|
||||
ObExprResType &max_type,
|
||||
ObExprResType &rand_expr,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (lib::is_oracle_mode()) {
|
||||
min_type.set_calc_type(ObDoubleType);
|
||||
max_type.set_calc_type(ObDoubleType);
|
||||
result_type.set_number();
|
||||
result_type.set_precision(PRECISION_UNKNOWN_YET);
|
||||
result_type.set_scale(ORA_NUMBER_SCALE_UNKNOWN_YET);
|
||||
} else if (ob_is_integer_type(min_type.get_type()) && ob_is_integer_type(max_type.get_type())) {
|
||||
min_type.set_calc_type(ObIntType);
|
||||
max_type.set_calc_type(ObIntType);
|
||||
result_type.set_int();
|
||||
} else {
|
||||
min_type.set_calc_type(ObDoubleType);
|
||||
max_type.set_calc_type(ObDoubleType);
|
||||
result_type.set_double();
|
||||
}
|
||||
rand_expr.set_calc_type(ObIntType);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprUniform::eval_next_int_value(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprUniformIntCtx *uniform_ctx = NULL;
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
|
||||
if (OB_FAIL(expr.eval_param_value(ctx))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_ISNULL(uniform_ctx = static_cast<ObExprUniformIntCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, uniform_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else if (OB_ISNULL(uniform_ctx)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("uniform ctx is NULL", K(ret));
|
||||
} else if (OB_FAIL(uniform_ctx->initialize(ctx, expr))) {
|
||||
LOG_WARN("fail init uniform context", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum &rand_val = expr.locate_param_datum(ctx, 2);
|
||||
if (OB_UNLIKELY(rand_val.is_null())) {
|
||||
res_datum.set_null();
|
||||
} else {
|
||||
int64_t seed = rand_val.get_int();
|
||||
int64_t res = 0;
|
||||
if (OB_FAIL(uniform_ctx->generate_next_value(seed, res))) {
|
||||
LOG_WARN("fail generate next uniform value", K(ret), K(seed));
|
||||
} else {
|
||||
res_datum.set_int(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprUniform::eval_next_real_value(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprUniformRealCtx *uniform_ctx = NULL;
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
|
||||
if (OB_FAIL(expr.eval_param_value(ctx))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_ISNULL(uniform_ctx = static_cast<ObExprUniformRealCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, uniform_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else if (OB_ISNULL(uniform_ctx)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("uniform ctx is NULL", K(ret));
|
||||
} else if (OB_FAIL(uniform_ctx->initialize(ctx, expr))) {
|
||||
LOG_WARN("fail init uniform context", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum &rand_val = expr.locate_param_datum(ctx, 2);
|
||||
if (OB_UNLIKELY(rand_val.is_null())) {
|
||||
res_datum.set_null();
|
||||
} else {
|
||||
int64_t seed = rand_val.get_int();
|
||||
double res = 0.0;
|
||||
if (OB_FAIL(uniform_ctx->generate_next_value(seed, res))) {
|
||||
LOG_WARN("fail generate next uniform value", K(ret), K(seed));
|
||||
} else {
|
||||
res_datum.set_double(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// No need to introduce a native number solution. just reuse double solution,
|
||||
// and convert the double result into number format
|
||||
int ObExprUniform::eval_next_number_value(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprUniformRealCtx *uniform_ctx = NULL;
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
|
||||
if (OB_FAIL(expr.eval_param_value(ctx))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_ISNULL(uniform_ctx = static_cast<ObExprUniformRealCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, uniform_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else if (OB_ISNULL(uniform_ctx)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("uniform ctx is NULL", K(ret));
|
||||
} else if (OB_FAIL(uniform_ctx->initialize(ctx, expr))) {
|
||||
LOG_WARN("fail init uniform context", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum &rand_val = expr.locate_param_datum(ctx, 2);
|
||||
if (OB_UNLIKELY(rand_val.is_null())) {
|
||||
res_datum.set_null();
|
||||
} else {
|
||||
int64_t seed = rand_val.get_int();
|
||||
double d = 0.0;
|
||||
number::ObNumber res;
|
||||
char local_buff[number::ObNumber::MAX_BYTE_LEN];
|
||||
ObDataBuffer local_alloc(local_buff, number::ObNumber::MAX_BYTE_LEN);
|
||||
if (OB_FAIL(uniform_ctx->generate_next_value(seed, d))) {
|
||||
LOG_WARN("fail generate next uniform value", K(ret), K(seed));
|
||||
} else if (OB_FAIL(ObJsonBaseUtil::double_to_number(d, local_alloc, res))) {
|
||||
LOG_WARN("fail convert double to number", K(seed), K(d));
|
||||
} else {
|
||||
res_datum.set_number(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObExprUniform::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
if (OB_UNLIKELY(3 != raw_expr.get_param_count())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param count for in expr", K(ret));
|
||||
} else if (OB_ISNULL(raw_expr.get_param_expr(0)) ||
|
||||
OB_ISNULL(raw_expr.get_param_expr(1))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid null param expr", K(ret));
|
||||
} else if (!raw_expr.get_param_expr(0)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "uniform function's first argument. must be a constant expression.");
|
||||
} else if (!raw_expr.get_param_expr(1)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "uniform function's second argument. must be a constant expression.");
|
||||
}
|
||||
|
||||
if (lib::is_oracle_mode()) {
|
||||
rt_expr.eval_func_ = ObExprUniform::eval_next_number_value;
|
||||
} else if (ob_is_integer_type(raw_expr.get_param_expr(0)->get_data_type())
|
||||
&& ob_is_integer_type(raw_expr.get_param_expr(1)->get_data_type())) {
|
||||
rt_expr.eval_func_ = ObExprUniform::eval_next_int_value;
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprUniform::eval_next_real_value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
69
src/sql/engine/expr/ob_expr_uniform.h
Normal file
69
src/sql/engine/expr/ob_expr_uniform.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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 OCEANBASE_SQL_OB_EXPR_FUNC_UNIFORM_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_UNIFORM_H_
|
||||
|
||||
#include <random>
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprUniform : public ObFuncExprOperator
|
||||
{
|
||||
class ObExprUniformIntCtx: public ObExprOperatorCtx
|
||||
{
|
||||
public:
|
||||
ObExprUniformIntCtx() = default;
|
||||
~ObExprUniformIntCtx() = default;
|
||||
int initialize(ObEvalCtx &ctx, const ObExpr &expr);
|
||||
int generate_next_value(int64_t sample, int64_t &res);
|
||||
private:
|
||||
std::uniform_int_distribution<int64_t> int_dist_;
|
||||
std::mt19937_64 gen_; // map continuous small number to large sparse space
|
||||
};
|
||||
class ObExprUniformRealCtx: public ObExprOperatorCtx
|
||||
{
|
||||
public:
|
||||
ObExprUniformRealCtx() = default;
|
||||
~ObExprUniformRealCtx() = default;
|
||||
int initialize(ObEvalCtx &ctx, const ObExpr &expr);
|
||||
int generate_next_value(int64_t sample, double &res);
|
||||
private:
|
||||
std::uniform_real_distribution<double> real_dist_;
|
||||
std::mt19937_64 gen_; // map continuous small number to large sparse space
|
||||
};
|
||||
public:
|
||||
explicit ObExprUniform(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprUniform();
|
||||
virtual int calc_result_type3(ObExprResType &result_type,
|
||||
ObExprResType &exponent,
|
||||
ObExprResType &size,
|
||||
ObExprResType &rand_expr,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual bool need_rt_ctx() const override { return true; }
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_next_int_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
static int eval_next_real_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
static int eval_next_number_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprUniform);
|
||||
};
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
|
||||
#endif /* OCEANBASE_SQL_OB_EXPR_FUNC_UNIFORM_H_ */
|
||||
164
src/sql/engine/expr/ob_expr_zipf.cpp
Normal file
164
src/sql/engine/expr/ob_expr_zipf.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "sql/engine/expr/ob_expr_zipf.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
|
||||
int ObExprZipf::ObExprZipfCtx::initialize(ObEvalCtx &ctx, const ObExpr &expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum &p1 = expr.locate_param_datum(ctx, 0);
|
||||
ObDatum &p2 = expr.locate_param_datum(ctx, 1);
|
||||
double alpha = 0.0;
|
||||
int64_t n = 0;
|
||||
probe_cp_.set_label("ZipfFunc");
|
||||
if (p1.is_null()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "zipf first argument. must be a constant expression no less than 1");
|
||||
} else if (p2.is_null()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "zipf second argument. must be a constant expression between 1 and 16777215 inclusive");
|
||||
} else if (FALSE_IT(alpha = p1.get_double())) {
|
||||
} else if (FALSE_IT(n = p2.get_int())) {
|
||||
} else if (alpha < 1) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "zipf first argument. must be a constant expression no less than 1");
|
||||
} else if (n < 1 || n > 16777215) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "zipf second argument. must be a constant expression between 1 and 16777215 inclusive");
|
||||
} else if (OB_FAIL(probe_cp_.reserve(n))) {
|
||||
LOG_WARN("fail allocate memory", K(ret), K(n));
|
||||
} else {
|
||||
double acc_sum = 0.0;
|
||||
for (int64_t i = 1; OB_SUCC(ret) && i <= n; ++i) {
|
||||
double f = 1.0 / pow(i, alpha);
|
||||
acc_sum += f;
|
||||
if (OB_FAIL(probe_cp_.push_back(acc_sum))) {
|
||||
LOG_WARN("fail push value", K(acc_sum), K(f), K(ret));
|
||||
}
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < n; ++i) {
|
||||
probe_cp_[i] = probe_cp_[i] / acc_sum;
|
||||
}
|
||||
// Make sure the last cumulative probability is one.
|
||||
probe_cp_[n -1] = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprZipf::ObExprZipfCtx::generate_next_value(int64_t seed, int64_t &result)
|
||||
{
|
||||
gen_.seed(static_cast<uint64_t>(seed));
|
||||
double normalized_seed = static_cast<double>(gen_()) / UINT64_MAX;
|
||||
auto pos = std::lower_bound(probe_cp_.begin(), probe_cp_.end(), normalized_seed);
|
||||
result = pos - probe_cp_.begin();
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
ObExprZipf::ObExprZipf(common::ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_ZIPF, "zipf", 3, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprZipf::~ObExprZipf()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprZipf::calc_result_type3(ObExprResType &result_type,
|
||||
ObExprResType &exponent,
|
||||
ObExprResType &size,
|
||||
ObExprResType &rand_expr,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
exponent.set_calc_type(ObDoubleType);
|
||||
size.set_calc_type(ObIntType);
|
||||
rand_expr.set_calc_type(ObIntType);
|
||||
result_type.set_int();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprZipf::eval_next_value(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprZipfCtx *zipf_ctx = NULL;
|
||||
uint64_t op_id = expr.expr_ctx_id_;
|
||||
ObExecContext &exec_ctx = ctx.exec_ctx_;
|
||||
|
||||
if (OB_FAIL(expr.eval_param_value(ctx))) {
|
||||
LOG_WARN("expr.eval_param_value failed", K(ret));
|
||||
} else if (OB_ISNULL(zipf_ctx = static_cast<ObExprZipfCtx *>(
|
||||
exec_ctx.get_expr_op_ctx(op_id)))) {
|
||||
if (OB_FAIL(exec_ctx.create_expr_op_ctx(op_id, zipf_ctx))) {
|
||||
LOG_WARN("failed to create operator ctx", K(ret), K(op_id));
|
||||
} else if (OB_ISNULL(zipf_ctx)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("zipf ctx is NULL", K(ret));
|
||||
} else if (OB_FAIL(zipf_ctx->initialize(ctx, expr))) {
|
||||
LOG_WARN("fail init zipf context", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum &rand_val = expr.locate_param_datum(ctx, 2);
|
||||
if (OB_UNLIKELY(rand_val.is_null())) {
|
||||
res_datum.set_null();
|
||||
} else {
|
||||
int64_t seed = rand_val.get_int();
|
||||
int64_t next_value_res = 0;
|
||||
if (OB_FAIL(zipf_ctx->generate_next_value(seed, next_value_res))) {
|
||||
LOG_WARN("fail generate next zipf value", K(ret), K(seed));
|
||||
} else {
|
||||
res_datum.set_int(next_value_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprZipf::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
if (OB_UNLIKELY(3 != raw_expr.get_param_count())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param count for in expr", K(ret));
|
||||
} else if (OB_ISNULL(raw_expr.get_param_expr(0)) ||
|
||||
OB_ISNULL(raw_expr.get_param_expr(1))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid null param expr", K(ret));
|
||||
} else if (!raw_expr.get_param_expr(0)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "zipf first argument. must be a constant expression no less than 1");
|
||||
} else if (!raw_expr.get_param_expr(1)->is_const_expr()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "zipf second argument. must be a constant expression between 1 and 16777215 inclusive");
|
||||
}
|
||||
rt_expr.eval_func_ = ObExprZipf::eval_next_value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
56
src/sql/engine/expr/ob_expr_zipf.h
Normal file
56
src/sql/engine/expr/ob_expr_zipf.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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 OCEANBASE_SQL_OB_EXPR_FUNC_ZIPF_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_FUNC_ZIPF_H_
|
||||
|
||||
#include <random>
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprZipf : public ObFuncExprOperator
|
||||
{
|
||||
class ObExprZipfCtx: public ObExprOperatorCtx
|
||||
{
|
||||
public:
|
||||
ObExprZipfCtx() = default;
|
||||
~ObExprZipfCtx() = default;
|
||||
int initialize(ObEvalCtx &ctx, const ObExpr &expr);
|
||||
int generate_next_value(int64_t seed, int64_t &result);
|
||||
private:
|
||||
common::ObArray<double> probe_cp_; // cumulative probability array
|
||||
std::mt19937_64 gen_; // map continuous small number to large sparse space
|
||||
};
|
||||
public:
|
||||
explicit ObExprZipf(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprZipf();
|
||||
virtual int calc_result_type3(ObExprResType &result_type,
|
||||
ObExprResType &exponent,
|
||||
ObExprResType &size,
|
||||
ObExprResType &rand_expr,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual bool need_rt_ctx() const override { return true; }
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int eval_next_value(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprZipf);
|
||||
};
|
||||
|
||||
} /* namespace sql */
|
||||
} /* namespace oceanbase */
|
||||
|
||||
#endif /* OCEANBASE_SQL_OB_EXPR_FUNC_ZIPF_H_ */
|
||||
Reference in New Issue
Block a user