init push
This commit is contained in:
782
src/sql/engine/expr/ob_expr.h
Normal file
782
src/sql/engine/expr/ob_expr.h
Normal file
@ -0,0 +1,782 @@
|
||||
/**
|
||||
* 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_EXPR_OB_EXPR_H_
|
||||
#define OCEANBASE_EXPR_OB_EXPR_H_
|
||||
|
||||
#include "lib/container/ob_2d_array.h"
|
||||
#include "lib/allocator/ob_allocator.h"
|
||||
#include "share/datum/ob_datum.h"
|
||||
#include "sql/engine/ob_serializable_function.h"
|
||||
#include "sql/parser/ob_item_type.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace common {
|
||||
class ObObjParam;
|
||||
}
|
||||
namespace sql {
|
||||
|
||||
using lib::is_mysql_mode;
|
||||
using lib::is_oracle_mode;
|
||||
|
||||
class ObExecContext;
|
||||
class ObIExprExtraInfo;
|
||||
using common::ObDatum;
|
||||
|
||||
typedef ObItemType ObExprOperatorType;
|
||||
|
||||
struct ObDatumMeta {
|
||||
OB_UNIS_VERSION(1);
|
||||
|
||||
public:
|
||||
ObDatumMeta() : type_(common::ObNullType), cs_type_(common::CS_TYPE_INVALID), scale_(-1), precision_(-1)
|
||||
{}
|
||||
ObDatumMeta(const common::ObObjType type, const common::ObCollationType cs_type, const int8_t scale)
|
||||
: type_(type), cs_type_(cs_type), scale_(scale), precision_(-1)
|
||||
{}
|
||||
ObDatumMeta(const common::ObObjType type, const common::ObCollationType cs_type, const int8_t scale,
|
||||
const common::ObPrecision prec)
|
||||
: type_(type), cs_type_(cs_type), scale_(scale), precision_(prec)
|
||||
{}
|
||||
|
||||
void reset()
|
||||
{
|
||||
new (this) ObDatumMeta();
|
||||
}
|
||||
TO_STRING_KV(K_(type), K_(cs_type), K_(scale), K_(precision));
|
||||
|
||||
common::ObObjType type_;
|
||||
common::ObCollationType cs_type_;
|
||||
int8_t scale_;
|
||||
union {
|
||||
common::ObPrecision precision_;
|
||||
common::ObLengthSemantics length_semantics_;
|
||||
};
|
||||
OB_INLINE bool is_clob() const
|
||||
{
|
||||
return (is_oracle_mode() && (static_cast<uint8_t>(common::ObLongTextType) == type_) &&
|
||||
(common::CS_TYPE_BINARY != cs_type_));
|
||||
}
|
||||
OB_INLINE bool is_varchar() const
|
||||
{
|
||||
return ((static_cast<uint8_t>(common::ObVarcharType) == type_) && (common::CS_TYPE_BINARY != cs_type_));
|
||||
}
|
||||
OB_INLINE bool is_char() const
|
||||
{
|
||||
return ((static_cast<uint8_t>(common::ObCharType) == type_) && (common::CS_TYPE_BINARY != cs_type_));
|
||||
}
|
||||
};
|
||||
|
||||
// Expression evaluate result info
|
||||
struct ObEvalInfo {
|
||||
void clear_evaluated_flag()
|
||||
{
|
||||
if (evaluated_) {
|
||||
evaluated_ = false;
|
||||
}
|
||||
}
|
||||
DECLARE_TO_STRING;
|
||||
|
||||
union {
|
||||
struct {
|
||||
// is already evaluated
|
||||
uint16_t evaluated_ : 1;
|
||||
// is projected
|
||||
uint16_t projected_ : 1;
|
||||
// all datums are not null.
|
||||
// may not set even all datums are not null,
|
||||
// e.g.: the null values are filtered by skip bitmap.
|
||||
uint16_t notnull_ : 1;
|
||||
// pointer is point to reserved buffer in frame.
|
||||
uint16_t point_to_frame_ : 1;
|
||||
};
|
||||
uint16_t flag_;
|
||||
};
|
||||
// result count (set to batch_size in batch_eval)
|
||||
uint16_t cnt_;
|
||||
};
|
||||
|
||||
// expression evaluate context
|
||||
struct ObEvalCtx {
|
||||
friend class ObExpr;
|
||||
ObEvalCtx(ObExecContext& exec_ctx, common::ObArenaAllocator& res_alloc, common::ObArenaAllocator& tmp_alloc);
|
||||
|
||||
common::ObArenaAllocator& get_reset_tmp_alloc()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
tmp_alloc_.reset();
|
||||
#else
|
||||
if (tmp_alloc_.used() > common::OB_MALLOC_MIDDLE_BLOCK_SIZE) {
|
||||
tmp_alloc_.reset_remain_one_page();
|
||||
}
|
||||
#endif
|
||||
return tmp_alloc_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Allocate expression result memory.
|
||||
void* alloc_expr_res(const int64_t size)
|
||||
{
|
||||
return expr_res_alloc_.alloc(size);
|
||||
}
|
||||
|
||||
public:
|
||||
char** frames_;
|
||||
ObExecContext& exec_ctx_;
|
||||
|
||||
private:
|
||||
// Expression result allocator, never reset.
|
||||
common::ObArenaAllocator& expr_res_alloc_;
|
||||
|
||||
// Temporary allocator for expression evaluating, may be reset immediately after ObExpr::eval().
|
||||
// Can not use allocator for expression result. (ObExpr::get_str_res_mem() is used for result).
|
||||
common::ObArenaAllocator& tmp_alloc_;
|
||||
};
|
||||
|
||||
typedef uint64_t (*ObExprHashFuncType)(const common::ObDatum& datum, const uint64_t seed);
|
||||
typedef int (*ObExprCmpFuncType)(const common::ObDatum& datum1, const common::ObDatum& datum2);
|
||||
struct ObExprBasicFuncs {
|
||||
// Default hash method:
|
||||
// murmur for non string tyeps
|
||||
// mysql string hash for string types
|
||||
// Try not to use it unless you need to be compatible with ObObj::hash()/ObObj::varchar_hash(),
|
||||
// use murmur_hash_ instead.
|
||||
ObExprHashFuncType default_hash_;
|
||||
// For murmur/xx/wy functions, the specified hash method is used for all tyeps.
|
||||
ObExprHashFuncType murmur_hash_;
|
||||
ObExprHashFuncType xx_hash_;
|
||||
ObExprHashFuncType wy_hash_;
|
||||
ObExprCmpFuncType null_first_cmp_;
|
||||
ObExprCmpFuncType null_last_cmp_;
|
||||
};
|
||||
|
||||
struct ObDynReserveBuf {
|
||||
static const uint32_t MAGIC_NUM = 0xD928e5bf;
|
||||
static bool supported(const common::ObObjType& type)
|
||||
{
|
||||
const common::ObObjTypeClass tc = common::ob_obj_type_class(type);
|
||||
return common::ObStringTC == tc || common::ObTextTC == tc || common::ObRawTC == tc || common::ObRowIDTC == tc ||
|
||||
common::ObLobTC == tc;
|
||||
}
|
||||
|
||||
ObDynReserveBuf() = default;
|
||||
|
||||
uint32_t magic_;
|
||||
uint32_t len_;
|
||||
char* mem_;
|
||||
};
|
||||
static_assert(16 == sizeof(ObDynReserveBuf), "ObDynReserveBuf size can not be changed");
|
||||
|
||||
typedef common::ObFixedArray<common::ObString, common::ObIAllocator> ObStrValues;
|
||||
|
||||
struct ObExpr {
|
||||
OB_UNIS_VERSION(1);
|
||||
|
||||
public:
|
||||
const static uint32_t INVALID_EXP_CTX_ID = UINT32_MAX;
|
||||
|
||||
ObExpr();
|
||||
OB_INLINE int eval(ObEvalCtx& ctx, common::ObDatum*& datum) const;
|
||||
int eval_enumset(ObEvalCtx& ctx, const common::ObIArray<common::ObString>& str_values, const uint64_t cast_mode,
|
||||
common::ObDatum*& datum) const;
|
||||
|
||||
void reset()
|
||||
{
|
||||
new (this) ObExpr();
|
||||
}
|
||||
ObDatum& locate_expr_datum(ObEvalCtx& ctx) const
|
||||
{
|
||||
// performance critical, do not check pointer validity.
|
||||
return *reinterpret_cast<ObDatum*>(ctx.frames_[frame_idx_] + datum_off_);
|
||||
}
|
||||
|
||||
ObEvalInfo& get_eval_info(ObEvalCtx& ctx) const
|
||||
{
|
||||
return *reinterpret_cast<ObEvalInfo*>(ctx.frames_[frame_idx_] + eval_info_off_);
|
||||
}
|
||||
|
||||
// locate expr datum && reset ptr_ to reserved buf
|
||||
OB_INLINE ObDatum& locate_datum_for_write(ObEvalCtx& ctx) const;
|
||||
OB_INLINE ObDatum& locate_param_datum(ObEvalCtx& ctx, int param_index) const
|
||||
{
|
||||
return args_[param_index]->locate_expr_datum(ctx);
|
||||
}
|
||||
|
||||
// Get result memory for string type.
|
||||
// Dynamic allocated memory is allocated if reserved buffer if not enough.
|
||||
char* get_str_res_mem(ObEvalCtx& ctx, const int64_t size) const
|
||||
{
|
||||
return OB_LIKELY(size <= res_buf_len_) ? ctx.frames_[frame_idx_] + res_buf_off_ : alloc_str_res_mem(ctx, size);
|
||||
}
|
||||
|
||||
// Evaluate all parameters, assign the first sizeof...(args) parameters to %args.
|
||||
//
|
||||
// e.g.:
|
||||
// arg_cnt_ = 2;
|
||||
//
|
||||
// eval_param_values(ctx):
|
||||
// call: args_[0]->eval(), args_[1]->eval()
|
||||
//
|
||||
// eval_param_values(ctx, param0);
|
||||
// call:args_[0]->eval(param0), args_[1]->eval();
|
||||
//
|
||||
// eval_param_values(ctx, param0, param1, param2
|
||||
// call: args[0]->eval(param0), args[1]->eval(param1)
|
||||
// keep param2 unchanged.
|
||||
template <typename... TS>
|
||||
OB_INLINE int eval_param_value(ObEvalCtx& ctx, TS&... args) const;
|
||||
|
||||
// deep copy %datum to reserve buffer or new allocated buffer if reserved buffer is not enough.
|
||||
OB_INLINE int deep_copy_datum(ObEvalCtx& ctx, const common::ObDatum& datum) const;
|
||||
|
||||
typedef common::ObIArray<ObExpr> ObExprIArray;
|
||||
static ObExprIArray*& get_serialize_array()
|
||||
{
|
||||
static lib::CoVar<ObExprIArray*> g_expr_ser_array;
|
||||
return g_expr_ser_array;
|
||||
}
|
||||
|
||||
TO_STRING_KV("type", get_type_name(type_), K_(datum_meta), K_(obj_meta), K_(obj_datum_map), KP_(eval_func),
|
||||
KP_(inner_functions), K_(inner_func_cnt), K_(arg_cnt), K_(parent_cnt), K_(frame_idx), K_(datum_off),
|
||||
K_(res_buf_off), K_(res_buf_len), K_(expr_ctx_id), K_(extra), KP(this));
|
||||
|
||||
private:
|
||||
char* alloc_str_res_mem(ObEvalCtx& ctx, const int64_t size) const;
|
||||
|
||||
public:
|
||||
typedef int (*EvalFunc)(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& expr_datum);
|
||||
typedef int (*EvalEnumSetFunc)(const ObExpr& expr, const common::ObIArray<common::ObString>& str_values,
|
||||
const uint64_t cast_mode, ObEvalCtx& ctx, ObDatum& expr_datum);
|
||||
|
||||
const static uint64_t MAGIC_NUM = 0x6367614D72707845L; // string of "ExprMagc"
|
||||
uint64_t magic_;
|
||||
ObExprOperatorType type_;
|
||||
// meta data of datum
|
||||
ObDatumMeta datum_meta_;
|
||||
// meta data of ObObj, used for ObObj converting.
|
||||
common::ObObjMeta obj_meta_;
|
||||
// max length of datum value. can be less than 0
|
||||
int32_t max_length_;
|
||||
// type of ObObj memory layout to ObDatum memory layout mapping,
|
||||
// used to convert ObDatum to ObObj and vice versa.
|
||||
common::ObObjDatumMapType obj_datum_map_;
|
||||
// expr evaluate function
|
||||
union {
|
||||
EvalFunc eval_func_;
|
||||
// helper union member for eval_func_ serialize && deserialize
|
||||
sql::serializable_function ser_eval_func_;
|
||||
};
|
||||
// aux evaluate functions for eval_func_, array of any function pointers, which interpreted
|
||||
// by eval_func_.
|
||||
// mysql row operand use the inner function array
|
||||
// to compare condition pairs. e.g.:
|
||||
// (a, b, c) = (1, 2, 3)
|
||||
// arg_cnt_ is 6
|
||||
// inner_func_cnt_ is 3
|
||||
union {
|
||||
void** inner_functions_;
|
||||
// helper member for inner_functions_ serialize && deserialize
|
||||
sql::serializable_function* ser_inner_functions_;
|
||||
};
|
||||
uint32_t inner_func_cnt_;
|
||||
ObExpr** args_;
|
||||
uint32_t arg_cnt_;
|
||||
ObExpr** parents_;
|
||||
uint32_t parent_cnt_;
|
||||
// frame index
|
||||
uint32_t frame_idx_;
|
||||
// offset of ObDatum in frame
|
||||
uint32_t datum_off_;
|
||||
// offset of ObEvalInfo
|
||||
uint32_t eval_info_off_;
|
||||
// reserve buffer offset in frame
|
||||
uint32_t res_buf_off_;
|
||||
// reserve buffer length
|
||||
uint32_t res_buf_len_;
|
||||
// expr context id
|
||||
uint32_t expr_ctx_id_;
|
||||
// extra info, reinterpreted by each expr
|
||||
union {
|
||||
uint64_t extra_;
|
||||
int64_t div_calc_scale_;
|
||||
ObIExprExtraInfo* extra_info_;
|
||||
};
|
||||
ObExprBasicFuncs* basic_funcs_;
|
||||
};
|
||||
|
||||
// helper template to access ObExpr::extra_
|
||||
template <typename T>
|
||||
struct ObExprExtraInfoAccess {
|
||||
static T& get_info(int64_t& v)
|
||||
{
|
||||
return *reinterpret_cast<T*>(&v);
|
||||
}
|
||||
static const T& get_info(const int64_t& v)
|
||||
{
|
||||
return *reinterpret_cast<const T*>(&v);
|
||||
}
|
||||
static T& get_info(ObExpr& e)
|
||||
{
|
||||
return get_info(*reinterpret_cast<int64_t*>(&e.extra_));
|
||||
}
|
||||
static const T& get_info(const ObExpr& e)
|
||||
{
|
||||
return get_info(*reinterpret_cast<const int64_t*>(&e.extra_));
|
||||
}
|
||||
};
|
||||
|
||||
// Wrap expression string result buffer allocation to allocator interface.
|
||||
// Please try not to use this, if you mast use it, make sure it only allocate one time and is
|
||||
// for expression result.
|
||||
class ObExprStrResAlloc : public common::ObIAllocator {
|
||||
public:
|
||||
ObExprStrResAlloc(const ObExpr& expr, ObEvalCtx& ctx) : off_(0), expr_(expr), ctx_(ctx)
|
||||
{}
|
||||
|
||||
void* alloc(const int64_t size) override;
|
||||
|
||||
private:
|
||||
int64_t off_;
|
||||
const ObExpr& expr_;
|
||||
ObEvalCtx& ctx_;
|
||||
};
|
||||
|
||||
struct ObDatumObj {
|
||||
public:
|
||||
void set_scale(common::ObScale scale)
|
||||
{
|
||||
meta_.scale_ = scale;
|
||||
}
|
||||
TO_STRING_KV(K_(meta));
|
||||
|
||||
public:
|
||||
ObDatumMeta meta_;
|
||||
common::ObDatum datum_;
|
||||
};
|
||||
|
||||
typedef common::ObIArray<ObExpr*> ObExprPtrIArray;
|
||||
|
||||
// copy from ObObjParam
|
||||
struct ObDatumObjParam : public ObDatumObj {
|
||||
ObDatumObjParam() : ObDatumObj(), accuracy_(), res_flags_(0), flag_()
|
||||
{}
|
||||
ObDatumObjParam(const ObDatumObj& other) : ObDatumObj(other), accuracy_(), res_flags_(0), flag_()
|
||||
{}
|
||||
|
||||
TO_STRING_KV(K_(accuracy), K_(res_flags), K_(datum), K_(meta));
|
||||
|
||||
public:
|
||||
int from_objparam(const common::ObObjParam& objparam);
|
||||
|
||||
int to_objparam(common::ObObjParam& obj_param);
|
||||
|
||||
OB_INLINE void set_datum(const common::ObDatum& datum)
|
||||
{
|
||||
datum_ = datum;
|
||||
}
|
||||
|
||||
OB_INLINE void set_meta(const ObDatumMeta& meta)
|
||||
{
|
||||
meta_ = meta;
|
||||
}
|
||||
// accuracy.
|
||||
OB_INLINE void set_accuracy(const common::ObAccuracy& accuracy)
|
||||
{
|
||||
accuracy_.set_accuracy(accuracy);
|
||||
}
|
||||
OB_INLINE void set_length(common::ObLength length)
|
||||
{
|
||||
accuracy_.set_length(length);
|
||||
}
|
||||
OB_INLINE void set_precision(common::ObPrecision precision)
|
||||
{
|
||||
accuracy_.set_precision(precision);
|
||||
}
|
||||
OB_INLINE void set_length_semantics(common::ObLengthSemantics length_semantics)
|
||||
{
|
||||
accuracy_.set_length_semantics(length_semantics);
|
||||
}
|
||||
OB_INLINE void set_scale(common::ObScale scale)
|
||||
{
|
||||
ObDatumObj::set_scale(scale);
|
||||
accuracy_.set_scale(scale);
|
||||
}
|
||||
OB_INLINE void set_udt_id(uint64_t id)
|
||||
{
|
||||
accuracy_.set_accuracy(id);
|
||||
}
|
||||
OB_INLINE const common::ObAccuracy& get_accuracy() const
|
||||
{
|
||||
return accuracy_;
|
||||
}
|
||||
OB_INLINE common::ObLength get_length() const
|
||||
{
|
||||
return accuracy_.get_length();
|
||||
}
|
||||
OB_INLINE common::ObPrecision get_precision() const
|
||||
{
|
||||
return accuracy_.get_precision();
|
||||
}
|
||||
OB_INLINE common::ObScale get_scale() const
|
||||
{
|
||||
return accuracy_.get_scale();
|
||||
}
|
||||
OB_INLINE uint64_t get_udt_id() const
|
||||
{
|
||||
return meta_.type_ == static_cast<uint8_t>(common::ObExtendType) ? accuracy_.get_accuracy()
|
||||
: common::OB_INVALID_INDEX;
|
||||
}
|
||||
OB_INLINE void set_result_flag(uint32_t flag)
|
||||
{
|
||||
res_flags_ |= flag;
|
||||
}
|
||||
OB_INLINE void unset_result_flag(uint32_t flag)
|
||||
{
|
||||
res_flags_ &= (~flag);
|
||||
}
|
||||
OB_INLINE bool has_result_flag(uint32_t flag) const
|
||||
{
|
||||
return res_flags_ & flag;
|
||||
}
|
||||
OB_INLINE uint32_t get_result_flag() const
|
||||
{
|
||||
return res_flags_;
|
||||
}
|
||||
|
||||
OB_INLINE const common::ParamFlag& get_param_flag() const
|
||||
{
|
||||
return flag_;
|
||||
}
|
||||
OB_INLINE void set_need_to_check_type(bool flag)
|
||||
{
|
||||
flag_.need_to_check_type_ = flag;
|
||||
}
|
||||
OB_INLINE bool need_to_check_type() const
|
||||
{
|
||||
return flag_.need_to_check_type_;
|
||||
}
|
||||
|
||||
OB_INLINE void set_need_to_check_bool_value(bool flag)
|
||||
{
|
||||
flag_.need_to_check_bool_value_ = flag;
|
||||
}
|
||||
OB_INLINE bool need_to_check_bool_value() const
|
||||
{
|
||||
return flag_.need_to_check_bool_value_;
|
||||
}
|
||||
|
||||
OB_INLINE void set_expected_bool_value(bool b_value)
|
||||
{
|
||||
flag_.expected_bool_value_ = b_value;
|
||||
}
|
||||
OB_INLINE bool expected_bool_value() const
|
||||
{
|
||||
return flag_.expected_bool_value_;
|
||||
}
|
||||
|
||||
NEED_SERIALIZE_AND_DESERIALIZE;
|
||||
|
||||
static uint32_t accuracy_offset_bits()
|
||||
{
|
||||
return offsetof(ObDatumObjParam, accuracy_) * 8;
|
||||
}
|
||||
static uint32_t res_flags_offset_bits()
|
||||
{
|
||||
return offsetof(ObDatumObjParam, res_flags_) * 8;
|
||||
}
|
||||
static uint32_t flag_offset_bits()
|
||||
{
|
||||
return offsetof(ObDatumObjParam, flag_) * 8;
|
||||
}
|
||||
|
||||
private:
|
||||
common::ObAccuracy accuracy_;
|
||||
uint32_t res_flags_; // BINARY, NUM, NOT_NULL, TIMESTAMP, etc
|
||||
// reference: src/lib/regex/include/mysql_com.h
|
||||
common::ParamFlag flag_;
|
||||
};
|
||||
|
||||
typedef common::Ob2DArray<ObDatumObjParam, common::OB_MALLOC_BIG_BLOCK_SIZE, common::ObWrapperAllocator>
|
||||
DatumParamStore;
|
||||
|
||||
// Helper function for print datum which interpreted by expression
|
||||
// Can only be used in log message like this:
|
||||
// LOG_WARN(....., "datum", DATUM2STR(*expr, *datum))
|
||||
struct ObToStringDatum {
|
||||
ObToStringDatum(const ObExpr& e, const common::ObDatum& d) : e_(e), d_(d)
|
||||
{}
|
||||
|
||||
DECLARE_TO_STRING;
|
||||
|
||||
const ObExpr& e_;
|
||||
const common::ObDatum& d_;
|
||||
};
|
||||
typedef ObToStringDatum DATUM2STR;
|
||||
|
||||
// Helper function for expression evaluate && print result
|
||||
// Can only be used in log message like this:
|
||||
// LOG_WARN(....., "datum", EXPR2STR(eval_ctx_, *expr))
|
||||
//
|
||||
// do not call EXPR2STR/ObToStringExpr in eval_func_ of ObExpr,
|
||||
// since EXPR2STR/ObToStringExpr will call eval_func_ again,
|
||||
// which can form a infinite loop.
|
||||
struct ObToStringExpr {
|
||||
ObToStringExpr(ObEvalCtx& ctx, const ObExpr& e) : c_(ctx), e_(e)
|
||||
{}
|
||||
|
||||
DECLARE_TO_STRING;
|
||||
|
||||
ObEvalCtx& c_;
|
||||
const ObExpr& e_;
|
||||
};
|
||||
typedef ObToStringExpr EXPR2STR;
|
||||
|
||||
// Helper function for expression array evaluate && print result
|
||||
// Can only be used in log message like this:
|
||||
// LOG_WARN(......, "row", ROWEXPR2STR(eval_ctx_, output_)
|
||||
struct ObToStringExprRow {
|
||||
ObToStringExprRow(ObEvalCtx& ctx, const common::ObIArray<ObExpr*>& exprs) : c_(ctx), exprs_(exprs)
|
||||
{
|
||||
for (int64_t i = 0; i < exprs_.count(); i++) {
|
||||
common::ObDatum* datum = NULL;
|
||||
ObExpr* e = exprs_.at(i);
|
||||
if (OB_NOT_NULL(e)) {
|
||||
IGNORE_RETURN e->eval(c_, datum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_TO_STRING;
|
||||
|
||||
ObEvalCtx& c_;
|
||||
const common::ObIArray<ObExpr*>& exprs_;
|
||||
};
|
||||
typedef ObToStringExprRow ROWEXPR2STR;
|
||||
|
||||
OB_INLINE ObDatum& ObExpr::locate_datum_for_write(ObEvalCtx& ctx) const
|
||||
{
|
||||
// performance critical, do not check pointer validity.
|
||||
char* frame = ctx.frames_[frame_idx_];
|
||||
OB_ASSERT(NULL != frame);
|
||||
ObDatum* expr_datum = (ObDatum*)(frame + datum_off_);
|
||||
if (expr_datum->ptr_ != frame + res_buf_off_) {
|
||||
expr_datum->ptr_ = frame + res_buf_off_;
|
||||
}
|
||||
return *expr_datum;
|
||||
}
|
||||
|
||||
template <typename... TS>
|
||||
OB_INLINE int ObExpr::eval_param_value(ObEvalCtx& ctx, TS&... args) const
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
common::ObDatum** params[] = {&args...};
|
||||
common::ObDatum* tmp = NULL;
|
||||
for (int param_index = 0; OB_SUCC(ret) && param_index < arg_cnt_; param_index++) {
|
||||
if (OB_FAIL(args_[param_index]->eval(ctx, param_index < ARRAYSIZEOF(params) ? *params[param_index] : tmp))) {
|
||||
SQL_LOG(WARN, "evaluate parameter failed", K(ret), K(param_index));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
OB_INLINE int ObExpr::eval(ObEvalCtx& ctx, common::ObDatum*& datum) const
|
||||
{
|
||||
// performance critical, do not check %frame_idx_ and %frame again. (checked in CG)
|
||||
int ret = common::OB_SUCCESS;
|
||||
char* frame = ctx.frames_[frame_idx_];
|
||||
OB_ASSERT(NULL != frame);
|
||||
datum = (ObDatum*)(frame + datum_off_);
|
||||
ObEvalInfo* eval_info = (ObEvalInfo*)(frame + eval_info_off_);
|
||||
|
||||
// do nothing for const/column reference expr or already evaluated expr
|
||||
if (NULL != eval_func_ && !eval_info->evaluated_) {
|
||||
if (datum->ptr_ != frame + res_buf_off_) {
|
||||
datum->ptr_ = frame + res_buf_off_;
|
||||
}
|
||||
ret = eval_func_(*this, ctx, *datum);
|
||||
if (OB_LIKELY(common::OB_SUCCESS == ret)) {
|
||||
eval_info->evaluated_ = true;
|
||||
} else {
|
||||
datum->set_null();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
OB_INLINE int ObExpr::deep_copy_datum(ObEvalCtx& ctx, const common::ObDatum& datum) const
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
// shadow copy datum first, because %datum may overlay with %dst
|
||||
common::ObDatum src = datum;
|
||||
ObDatum& dst = this->locate_datum_for_write(ctx);
|
||||
dst.pack_ = src.pack_;
|
||||
if (!src.null_) {
|
||||
if (OB_UNLIKELY(src.len_ > res_buf_len_)) {
|
||||
// only string datum may exceed %res_buf_len_;
|
||||
if (OB_ISNULL(dst.ptr_ = get_str_res_mem(ctx, src.len_))) {
|
||||
ret = common::OB_ALLOCATE_MEMORY_FAILED;
|
||||
SQL_LOG(WARN, "allocate memory failed", K(ret));
|
||||
} else {
|
||||
MEMMOVE(const_cast<char*>(dst.ptr_), src.ptr_, src.len_);
|
||||
}
|
||||
} else {
|
||||
MEMMOVE(const_cast<char*>(dst.ptr_), src.ptr_, src.len_);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace sql
|
||||
namespace common {
|
||||
namespace serialization {
|
||||
|
||||
// ObExpr pointer serialize && deserialize.
|
||||
// Convert pointer to index of expr array, serialize && deserialize the index.
|
||||
// The serialized index is the real index + 1, to make room for NULL.
|
||||
inline int64_t encoded_length(sql::ObExpr*)
|
||||
{
|
||||
return sizeof(uint32_t);
|
||||
}
|
||||
|
||||
inline int encode(char* buf, const int64_t buf_len, int64_t& pos, sql::ObExpr* expr)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
uint32_t idx = 0;
|
||||
if (NULL != expr) {
|
||||
sql::ObExpr::ObExprIArray* array = sql::ObExpr::get_serialize_array();
|
||||
if (OB_UNLIKELY(NULL == array || array->empty() || expr < &array->at(0) ||
|
||||
(idx = expr - &array->at(0) + 1) > array->count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_LOG(WARN, "expr not in array", K(ret), KP(array), KP(idx), KP(expr));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = encode_i32(buf, buf_len, pos, idx);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int decode(const char* buf, const int64_t data_len, int64_t& pos, sql::ObExpr*& expr)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
uint32_t idx = 0;
|
||||
ret = decode_i32(buf, data_len, pos, reinterpret_cast<int32_t*>(&idx));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (0 == idx) {
|
||||
expr = NULL;
|
||||
} else {
|
||||
sql::ObExpr::ObExprIArray* array = sql::ObExpr::get_serialize_array();
|
||||
if (OB_UNLIKELY(NULL == array) || OB_UNLIKELY(idx > array->count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_LOG(WARN, "expr index out of expr array range", K(ret), KP(array), K(idx));
|
||||
} else {
|
||||
expr = &array->at(idx - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct EnumEncoder<false, sql::ObExpr*> {
|
||||
static int encode(char* buf, const int64_t buf_len, int64_t& pos, sql::ObExpr* expr)
|
||||
{
|
||||
return serialization::encode(buf, buf_len, pos, expr);
|
||||
}
|
||||
|
||||
static int decode(const char* buf, const int64_t data_len, int64_t& pos, sql::ObExpr*& expr)
|
||||
{
|
||||
return serialization::decode(buf, data_len, pos, expr);
|
||||
}
|
||||
|
||||
static int64_t encoded_length(sql::ObExpr* expr)
|
||||
{
|
||||
return serialization::encoded_length(expr);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Simple c array wrapper for serialize && deserialize. e.g.:
|
||||
// OB_SERIALIZE_MEMBER(Foo, make_ser_carray(items_, item_cnt_))
|
||||
//
|
||||
template <typename T, typename U>
|
||||
struct ObSerCArray {
|
||||
ObSerCArray(T& data, U& cnt) : data_(data), cnt_(cnt)
|
||||
{}
|
||||
T& data_;
|
||||
U& cnt_;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
ObSerCArray<T, U> make_ser_carray(T& data, U& cnt)
|
||||
{
|
||||
return ObSerCArray<T, U>(data, cnt);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline int64_t encoded_length(const ObSerCArray<T* const, U>& array)
|
||||
{
|
||||
int64_t len = 0;
|
||||
OB_UNIS_ADD_LEN_ARRAY(array.data_, array.cnt_);
|
||||
return len;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline int encode(char* buf, const int64_t buf_len, int64_t& pos, const ObSerCArray<T* const, U>& array)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(array.cnt_ > 0 && NULL == array.data_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_LOG(WARN, "array not empty but data is NULL", K(ret), KP(array.data_), K(array.cnt_));
|
||||
} else {
|
||||
OB_UNIS_ENCODE_ARRAY(array.data_, array.cnt_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline int decode(const char* buf, const int64_t data_len, int64_t& pos, const ObSerCArray<T*, U>& array)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_UNIS_DECODE(array.cnt_);
|
||||
if (OB_SUCC(ret)) {
|
||||
if (0 == array.cnt_) {
|
||||
array.data_ = NULL;
|
||||
} else {
|
||||
const int64_t alloc_size = sizeof(*array.data_) * array.cnt_;
|
||||
array.data_ = static_cast<T*>(CURRENT_CONTEXT.get_arena_allocator().alloc(alloc_size));
|
||||
if (OB_ISNULL(array.data_)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
SQL_LOG(WARN, "alloc memory failed", K(ret), K(alloc_size));
|
||||
} else {
|
||||
int64_t idx = 0;
|
||||
for (; OB_SUCC(ret) && idx < array.cnt_; idx++) {
|
||||
new (&array.data_[idx]) T();
|
||||
OB_UNIS_DECODE(array.data_[idx]);
|
||||
}
|
||||
// deconstruct the constructed objects.
|
||||
if (OB_SUCCESS != ret) {
|
||||
for (int64_t i = idx; i >= 0; i--) {
|
||||
array.data_[i].~T();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace common
|
||||
} // end namespace oceanbase
|
||||
|
||||
#endif // OCEANBASE_EXPR_OB_EXPR_H_
|
||||
Reference in New Issue
Block a user