[FEAT MERGE] [v4.2] add table generator and several random utility functions

This commit is contained in:
raywill
2023-04-13 08:22:22 +00:00
committed by ob-robot
parent 94159e6675
commit 27488211d2
34 changed files with 1659 additions and 79 deletions

View File

@ -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[] = {

View 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 */

View 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_ */

View 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 */

View 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_ */

View File

@ -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)

View 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 */

View 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_ */

View File

@ -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);
}
}
}

View File

@ -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);

View 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 */

View 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_ */

View 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 */

View 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_ */

View 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 */

View 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_ */