patch 4.0
This commit is contained in:
@ -12,93 +12,132 @@
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "ob_expr_calc_partition_id.h"
|
||||
#include "share/part/ob_part_mgr_ad.h"
|
||||
#include "sql/code_generator/ob_static_engine_expr_cg.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "sql/engine/expr/ob_expr_func_part_hash.h"
|
||||
#include "sql/engine/expr/ob_expr_calc_partition_id.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
using namespace share::schema;
|
||||
namespace sql {
|
||||
namespace sql
|
||||
{
|
||||
|
||||
OB_SERIALIZE_MEMBER(
|
||||
CalcPartitionIdInfo, ref_table_id_, part_level_, part_type_, subpart_type_, part_num_, subpart_num_);
|
||||
OB_SERIALIZE_MEMBER(CalcPartitionBaseInfo,
|
||||
ref_table_id_,
|
||||
related_table_ids_,
|
||||
part_level_,
|
||||
part_type_,
|
||||
subpart_type_,
|
||||
part_num_,
|
||||
subpart_num_,
|
||||
partition_id_calc_type_,
|
||||
may_add_interval_part_,
|
||||
calc_id_type_);
|
||||
|
||||
int CalcPartitionIdInfo::deep_copy(
|
||||
common::ObIAllocator& allocator, const ObExprOperatorType type, ObIExprExtraInfo*& copied_info) const
|
||||
int CalcPartitionBaseInfo::deep_copy(common::ObIAllocator &allocator,
|
||||
const ObExprOperatorType type,
|
||||
ObIExprExtraInfo *&copied_info) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(ObExprExtraInfoFactory::alloc(allocator, type, copied_info))) {
|
||||
if (OB_FAIL(ObExprExtraInfoFactory::alloc(allocator, type,
|
||||
copied_info))) {
|
||||
LOG_WARN("failed to alloc extra info", K(ret));
|
||||
} else {
|
||||
*copied_info = *this;
|
||||
CalcPartitionBaseInfo *base_info = static_cast<CalcPartitionBaseInfo*>(copied_info);
|
||||
if (OB_FAIL(base_info->related_table_ids_.assign(related_table_ids_))) {
|
||||
LOG_WARN("assign related table ids failed", K(ret));
|
||||
} else {
|
||||
base_info->ref_table_id_ = ref_table_id_;
|
||||
base_info->part_level_ = part_level_;
|
||||
base_info->part_type_ = part_type_;
|
||||
base_info->subpart_type_ = subpart_type_;
|
||||
base_info->part_num_ = part_num_;
|
||||
base_info->subpart_num_ = subpart_num_;
|
||||
base_info->partition_id_calc_type_ = partition_id_calc_type_;
|
||||
base_info->may_add_interval_part_ = may_add_interval_part_;
|
||||
base_info->calc_id_type_ = calc_id_type_;
|
||||
base_info->first_part_id_ = first_part_id_;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprCalcPartitionId::ObExprCalcPartitionId(ObIAllocator& alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_CALC_PARTITION_ID, N_CALC_PARTITION_ID, PARAM_NUM_UNKNOWN, NOT_ROW_DIMENSION)
|
||||
{}
|
||||
int ObExprCalcPartitionBase::set_may_add_interval_part(ObExpr *expr,
|
||||
const MayAddIntervalPart info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CalcPartitionBaseInfo *calc_part_info = NULL;
|
||||
CK (OB_NOT_NULL(expr));
|
||||
OX (calc_part_info = reinterpret_cast<CalcPartitionBaseInfo *>(expr->extra_info_));
|
||||
CK (OB_NOT_NULL(calc_part_info));
|
||||
OX (calc_part_info->may_add_interval_part_ = info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprCalcPartitionId::~ObExprCalcPartitionId()
|
||||
{}
|
||||
|
||||
int ObExprCalcPartitionId::calc_result_typeN(
|
||||
ObExprResType& type, ObExprResType* types_array, int64_t param_num, common::ObExprTypeCtx& type_ctx) const
|
||||
int ObExprCalcPartitionBase::calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *types_array,
|
||||
int64_t param_num,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(types_array);
|
||||
UNUSED(param_num);
|
||||
UNUSED(type_ctx);
|
||||
type.set_int();
|
||||
type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].precision_);
|
||||
type.set_scale(DEFAULT_SCALE_FOR_INTEGER);
|
||||
if (CALC_PARTITION_TABLET_ID == get_calc_id_type()) {
|
||||
type.set_binary();
|
||||
type.set_length(sizeof(uint64_t) * 2);
|
||||
} else {
|
||||
type.set_int();
|
||||
type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].precision_);
|
||||
type.set_scale(DEFAULT_SCALE_FOR_INTEGER);
|
||||
}
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::cg_expr(ObExprCGCtx& expr_cg_ctx, const ObRawExpr& raw_expr, ObExpr& rt_expr) const
|
||||
int ObExprCalcPartitionBase::cg_expr(ObExprCGCtx &expr_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
uint64_t ref_table_id = raw_expr.get_extra();
|
||||
CalcPartitionIdInfo* calc_part_info = NULL;
|
||||
const ObTableSchema* table_schema = NULL;
|
||||
ObSqlCtx* sql_ctx = NULL;
|
||||
;
|
||||
ObTableID ref_table_id = reinterpret_cast<ObTableID>(raw_expr.get_extra());
|
||||
CalcPartitionBaseInfo *calc_part_info = NULL;
|
||||
const ObTableSchema *table_schema = NULL;
|
||||
OptRouteType opt_route = OPT_ROUTE_NONE;
|
||||
if (OB_ISNULL(expr_cg_ctx.exec_ctx_) || OB_ISNULL(sql_ctx = expr_cg_ctx.exec_ctx_->get_sql_ctx()) ||
|
||||
OB_ISNULL(sql_ctx->schema_guard_)) {
|
||||
if (OB_ISNULL(expr_cg_ctx.schema_guard_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", K(ret), KP(expr_cg_ctx.exec_ctx_));
|
||||
LOG_WARN("invalid argument", K(ret));
|
||||
} else if (0 == ref_table_id) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid ref table id", K(ref_table_id), K(ret));
|
||||
} else if (OB_FAIL(sql_ctx->schema_guard_->get_table_schema(ref_table_id, table_schema))) {
|
||||
} else if (OB_FAIL(expr_cg_ctx.schema_guard_->get_table_schema(
|
||||
MTL_ID(), ref_table_id, table_schema))) {
|
||||
LOG_WARN("fail to get table schema", K(ref_table_id), K(ret));
|
||||
} else if (OB_ISNULL(table_schema)) {
|
||||
ret = OB_TABLE_NOT_EXIST;
|
||||
LOG_WARN("Table not exist", K(ref_table_id), K(ret));
|
||||
} else if (OB_FAIL(init_calc_part_info(expr_cg_ctx, *table_schema, calc_part_info))) {
|
||||
} else if (OB_FAIL(init_calc_part_info(expr_cg_ctx.allocator_,
|
||||
*table_schema,
|
||||
raw_expr.get_partition_id_calc_type(),
|
||||
raw_expr.get_may_add_interval_part(),
|
||||
calc_part_info))) {
|
||||
LOG_WARN("fail to init tl expr info", K(ret));
|
||||
} else if (OB_ISNULL(calc_part_info)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("fail to init tl expr info", K(ret), K(calc_part_info));
|
||||
} else if (OB_FAIL(get_opt_route(*table_schema, raw_expr, opt_route))) {
|
||||
LOG_WARN("fail to check use opt", K(ret));
|
||||
} else {
|
||||
rt_expr.extra_info_ = calc_part_info;
|
||||
int64_t param_cnt = raw_expr.get_param_count();
|
||||
if (OPT_ROUTE_HASH_ONE == opt_route) {
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionId::calc_opt_route_hash_one;
|
||||
} else if (0 == param_cnt) {
|
||||
if (0 == param_cnt) {
|
||||
OB_ASSERT(PARTITION_LEVEL_ZERO == calc_part_info->part_level_);
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionId::calc_no_partition_location;
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionBase::calc_no_partition_location;
|
||||
} else if (1 == param_cnt) {
|
||||
OB_ASSERT(PARTITION_LEVEL_ONE == calc_part_info->part_level_);
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionId::calc_partition_level_one;
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionBase::calc_partition_level_one;
|
||||
} else if (2 == param_cnt) {
|
||||
OB_ASSERT(PARTITION_LEVEL_TWO == calc_part_info->part_level_);
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionId::calc_partition_level_two;
|
||||
rt_expr.eval_func_ = ObExprCalcPartitionBase::calc_partition_level_two;
|
||||
} else {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param cnt", K(ret), K(param_cnt));
|
||||
@ -108,97 +147,72 @@ int ObExprCalcPartitionId::cg_expr(ObExprCGCtx& expr_cg_ctx, const ObRawExpr& ra
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::init_calc_part_info(
|
||||
ObExprCGCtx& expr_cg_ctx, const ObTableSchema& table_schema, CalcPartitionIdInfo*& calc_part_info)
|
||||
int ObExprCalcPartitionBase::init_calc_part_info(ObIAllocator *allocator,
|
||||
const ObTableSchema &table_schema,
|
||||
PartitionIdCalcType calc_type,
|
||||
MayAddIntervalPart add_part,
|
||||
CalcPartitionBaseInfo *&calc_part_info) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
calc_part_info = NULL;
|
||||
CK(OB_NOT_NULL(expr_cg_ctx.allocator_));
|
||||
CK(OB_NOT_NULL(allocator));
|
||||
if (OB_SUCC(ret)) {
|
||||
void* buf = expr_cg_ctx.allocator_->alloc(sizeof(CalcPartitionIdInfo));
|
||||
void *buf = allocator->alloc(sizeof(CalcPartitionBaseInfo));
|
||||
if (OB_ISNULL(buf)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc memory", K(ret));
|
||||
} else {
|
||||
calc_part_info = new (buf) CalcPartitionIdInfo(*expr_cg_ctx.allocator_, T_FUN_SYS_CALC_PARTITION_ID);
|
||||
calc_part_info = new(buf) CalcPartitionBaseInfo(*allocator, get_type());
|
||||
calc_part_info->ref_table_id_ = table_schema.get_table_id();
|
||||
calc_part_info->part_level_ = table_schema.get_part_level();
|
||||
calc_part_info->part_type_ = table_schema.get_part_option().get_part_func_type();
|
||||
calc_part_info->subpart_type_ = table_schema.get_sub_part_option().get_sub_part_func_type();
|
||||
calc_part_info->part_num_ = table_schema.get_first_part_num();
|
||||
calc_part_info->subpart_num_ = OB_INVALID_ID; // unsed for now
|
||||
LOG_DEBUG("table location expr info", K(*calc_part_info), K(ret));
|
||||
calc_part_info->subpart_num_ = OB_INVALID_ID; // 目前未使用,要使用的话需要考虑二级分区个数异构
|
||||
calc_part_info->partition_id_calc_type_ = calc_type;
|
||||
calc_part_info->may_add_interval_part_ = add_part;
|
||||
calc_part_info->calc_id_type_ = get_calc_id_type();
|
||||
LOG_DEBUG("table location expr info", KPC(calc_part_info), K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::calc_no_partition_location(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res_datum)
|
||||
int ObExprCalcPartitionBase::calc_no_partition_location(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr);
|
||||
UNUSED(ctx);
|
||||
res_datum.set_int(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::calc_partition_level_one(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_ASSERT(1 == expr.arg_cnt_);
|
||||
OB_ASSERT(expr.extra_ > 0);
|
||||
CalcPartitionIdInfo* calc_part_info = reinterpret_cast<CalcPartitionIdInfo*>(expr.extra_);
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[0],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
NONE_PARTITION_ID, /*first_part_id*/
|
||||
res_datum))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::calc_partition_level_two(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_ASSERT(2 == expr.arg_cnt_);
|
||||
OB_ASSERT(expr.extra_ > 0);
|
||||
CalcPartitionIdInfo* calc_part_info = reinterpret_cast<CalcPartitionIdInfo*>(expr.extra_);
|
||||
PartitionIdCalcType calc_type = ctx.exec_ctx_.get_partition_id_calc_type();
|
||||
if (CALC_IGNORE_FIRST_PART == calc_type) {
|
||||
int64_t first_part_id = ctx.exec_ctx_.get_fixed_id();
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[1], ctx, *calc_part_info, first_part_id, res_datum))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
}
|
||||
} else if (CALC_IGNORE_SUB_PART == calc_type) {
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[0],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
NONE_PARTITION_ID, /*first_part_id*/
|
||||
res_datum))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(calc_partition_id(*expr.args_[0],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
NONE_PARTITION_ID, /*first_part_id*/
|
||||
res_datum))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
ObDASTabletMapper tablet_mapper;
|
||||
ObSEArray<ObTabletID, 1> tablet_ids;
|
||||
ObSEArray<ObObjectID, 1> partition_ids;
|
||||
CalcPartitionBaseInfo *calc_part_info = reinterpret_cast<CalcPartitionBaseInfo *>(expr.extra_info_);
|
||||
if (OB_FAIL(ctx.exec_ctx_.get_das_ctx().get_das_tablet_mapper(calc_part_info->ref_table_id_,
|
||||
tablet_mapper,
|
||||
&calc_part_info->related_table_ids_))) {
|
||||
LOG_WARN("get das tablet mapper failed", K(ret), K(calc_part_info));
|
||||
} else if (OB_FAIL(tablet_mapper.get_non_partition_tablet_id(tablet_ids, partition_ids))) {
|
||||
LOG_WARN("fail to get non partition tablet id", K(ret));
|
||||
} else {
|
||||
int64_t first_part_id = res_datum.get_int();
|
||||
if (NONE_PARTITION_ID == first_part_id) {
|
||||
// do nothing
|
||||
// The first level partition is not calculated, return NONE_PARTITION_ID
|
||||
} else {
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[1], ctx, *calc_part_info, first_part_id, res_datum))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
} else if (NONE_PARTITION_ID == res_datum.get_int()) {
|
||||
// do nothing
|
||||
if (CALC_TABLET_ID == calc_part_info->calc_id_type_) {
|
||||
if (0 == tablet_ids.count()) {
|
||||
res_datum.set_int(ObTabletID::INVALID_TABLET_ID);
|
||||
} else {
|
||||
res_datum.set_int(generate_phy_part_id(first_part_id, res_datum.get_int(), PARTITION_LEVEL_TWO));
|
||||
res_datum.set_int(tablet_ids.at(0).id());
|
||||
}
|
||||
} else if (CALC_PARTITION_ID == calc_part_info->calc_id_type_) {
|
||||
if (0 == partition_ids.count()) {
|
||||
res_datum.set_int(OB_INVALID_ID);
|
||||
} else {
|
||||
res_datum.set_int(partition_ids.at(0));
|
||||
}
|
||||
} else if (CALC_PARTITION_TABLET_ID == calc_part_info->calc_id_type_) {
|
||||
if (OB_FAIL(concat_part_and_tablet_id(expr, ctx, res_datum,
|
||||
(0 == partition_ids.count()) ? OB_INVALID_ID : partition_ids.at(0),
|
||||
(0 == tablet_ids.count()) ? OB_INVALID_ID : tablet_ids.at(0).id()))) {
|
||||
LOG_WARN("fail to concat partition id and tablet id", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,12 +220,177 @@ int ObExprCalcPartitionId::calc_partition_level_two(const ObExpr& expr, ObEvalCt
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::build_row(ObEvalCtx& ctx, ObIAllocator& allocator, const ObExpr& expr, ObNewRow& row)
|
||||
int ObExprCalcPartitionBase::calc_partition_level_one(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_ASSERT(1 == expr.arg_cnt_);
|
||||
CalcPartitionBaseInfo *calc_part_info = reinterpret_cast<CalcPartitionBaseInfo *>(expr.extra_info_);
|
||||
CK (OB_NOT_NULL(calc_part_info));
|
||||
ObTabletID tablet_id(ObTabletID::INVALID_TABLET_ID);
|
||||
ObObjectID partition_id = OB_INVALID_ID;
|
||||
OZ (calc_partition_id(*expr.args_[0],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
OB_INVALID_ID, /*first_part_id*/
|
||||
tablet_id,
|
||||
partition_id));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (CALC_TABLET_ID == calc_part_info->calc_id_type_) {
|
||||
res_datum.set_int(tablet_id.id());
|
||||
} else if (CALC_PARTITION_ID == calc_part_info->calc_id_type_) {
|
||||
res_datum.set_int(partition_id);
|
||||
} else if (CALC_PARTITION_TABLET_ID == calc_part_info->calc_id_type_) {
|
||||
if (OB_FAIL(concat_part_and_tablet_id(expr, ctx, res_datum, partition_id, tablet_id.id()))) {
|
||||
LOG_WARN("fail to concat partition id and tablet id", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionBase::calc_partition_level_two(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_ASSERT(2 == expr.arg_cnt_);
|
||||
OB_ASSERT(nullptr != expr.extra_info_);
|
||||
CalcPartitionBaseInfo *calc_part_info = reinterpret_cast<CalcPartitionBaseInfo *>(expr.extra_info_);
|
||||
PartitionIdCalcType calc_type = CALC_INVALID == calc_part_info->partition_id_calc_type_ ?
|
||||
ctx.exec_ctx_.get_partition_id_calc_type() :
|
||||
calc_part_info->partition_id_calc_type_;
|
||||
ObObjectID first_part_id = OB_INVALID_ID;
|
||||
ObTabletID tablet_id(ObTabletID::INVALID_TABLET_ID);
|
||||
ObObjectID partition_id = OB_INVALID_ID;
|
||||
if (CALC_IGNORE_FIRST_PART == calc_type) {
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[1],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
calc_part_info->first_part_id_,
|
||||
tablet_id,
|
||||
partition_id))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
}
|
||||
} else if (CALC_IGNORE_SUB_PART == calc_type) {
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[0],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
OB_INVALID_ID, /*first_part_id*/
|
||||
tablet_id,
|
||||
partition_id))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
} else {
|
||||
// FIXME @YISHEN
|
||||
tablet_id = ObTabletID(partition_id);
|
||||
}
|
||||
} else if (OB_FAIL(calc_partition_id(*expr.args_[0],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
OB_INVALID_ID, /*first_part_id*/
|
||||
tablet_id,
|
||||
first_part_id))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
} else {
|
||||
if (OB_INVALID_ID == first_part_id) {
|
||||
// do nothing
|
||||
} else {
|
||||
if (OB_FAIL(calc_partition_id(*expr.args_[1],
|
||||
ctx,
|
||||
*calc_part_info,
|
||||
first_part_id,
|
||||
tablet_id,
|
||||
partition_id))) {
|
||||
LOG_WARN("fail to calc partitoin id", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (CALC_TABLET_ID == calc_part_info->calc_id_type_) {
|
||||
res_datum.set_int(tablet_id.id());
|
||||
} else if (CALC_PARTITION_ID == calc_part_info->calc_id_type_) {
|
||||
res_datum.set_int(partition_id);
|
||||
} else if (CALC_PARTITION_TABLET_ID == calc_part_info->calc_id_type_) {
|
||||
if (OB_FAIL(concat_part_and_tablet_id(expr, ctx, res_datum, partition_id, tablet_id.id()))) {
|
||||
LOG_WARN("fail to concat partition id and tablet id", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionBase::concat_part_and_tablet_id(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &res_datum,
|
||||
uint64_t partition_id,
|
||||
uint64_t tablet_id)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
uint64_t buf_len = sizeof(uint64_t) * 2;
|
||||
uint64_t *buf = reinterpret_cast<uint64_t *>(expr.get_str_res_mem(ctx, buf_len));
|
||||
if (OB_ISNULL(buf)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc memory", K(ret));
|
||||
} else {
|
||||
buf[0] = partition_id;
|
||||
buf[1] = tablet_id;
|
||||
res_datum.set_string(reinterpret_cast<char *>(buf), buf_len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionBase::extract_part_and_tablet_id(const ObDatum &part_datum,
|
||||
ObObjectID &part_id,
|
||||
ObTabletID &tablet_id)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObString &part_str = part_datum.get_string();
|
||||
if (part_str.length() < sizeof(uint64_t) * 2) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("the partition string need 16 byte at least", K(ret));
|
||||
} else {
|
||||
const uint64_t *id_array = reinterpret_cast<const uint64_t*>(part_str.ptr());
|
||||
part_id = id_array[0];
|
||||
tablet_id = id_array[1];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionBase::calc_part_and_tablet_id(const ObExpr *calc_part_id,
|
||||
ObEvalCtx &eval_ctx,
|
||||
ObObjectID &partition_id,
|
||||
ObTabletID &tablet_id)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *partition_id_datum = NULL;
|
||||
if (OB_ISNULL(calc_part_id) || !calc_part_id->datum_meta_.is_binary()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("calc part id is invalid", K(ret), KPC(calc_part_id));
|
||||
} else if (OB_FAIL(calc_part_id->eval(eval_ctx, partition_id_datum))) {
|
||||
LOG_WARN("calc part id expr failed", K(ret));
|
||||
} else if (OB_FAIL(extract_part_and_tablet_id(*partition_id_datum, partition_id, tablet_id))) {
|
||||
LOG_WARN("extract part and tablet id failed", K(ret));
|
||||
} else if (ObExprCalcPartitionId::NONE_PARTITION_ID == partition_id) {
|
||||
ret = OB_NO_PARTITION_FOR_GIVEN_VALUE;
|
||||
LOG_DEBUG("no partition matched", K(ret), KPC(calc_part_id), KPC(partition_id_datum));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionBase::build_row(ObEvalCtx &ctx,
|
||||
ObIAllocator &allocator,
|
||||
const ObExpr &expr,
|
||||
ObNewRow &row)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_ASSERT(T_OP_ROW == expr.type_);
|
||||
OB_ASSERT(expr.arg_cnt_ > 0);
|
||||
if (OB_ISNULL(row.cells_ = static_cast<ObObj*>(allocator.alloc(sizeof(ObObj) * expr.arg_cnt_)))) {
|
||||
//TODO shengle 这里后面可以将第一次分配的cells_内存放入expr_ctx,
|
||||
// 重复使用进行优化;
|
||||
if (OB_ISNULL(row.cells_ = static_cast<ObObj *>(
|
||||
allocator.alloc(sizeof(ObObj) * expr.arg_cnt_)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("allocate memory failed", K(ret));
|
||||
} else {
|
||||
@ -224,9 +403,11 @@ int ObExprCalcPartitionId::build_row(ObEvalCtx& ctx, ObIAllocator& allocator, co
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; i++) {
|
||||
ObExpr* col_expr = expr.args_[i];
|
||||
ObDatum& col_datum = col_expr->locate_expr_datum(ctx);
|
||||
if (OB_FAIL(col_datum.to_obj(row.cells_[i], col_expr->obj_meta_, col_expr->obj_datum_map_))) {
|
||||
ObExpr *col_expr = expr.args_[i];
|
||||
ObDatum &col_datum = col_expr->locate_expr_datum(ctx);
|
||||
if (OB_FAIL(col_datum.to_obj(row.cells_[i],
|
||||
col_expr->obj_meta_,
|
||||
col_expr->obj_datum_map_))) {
|
||||
LOG_WARN("convert datum to obj failed", K(ret));
|
||||
}
|
||||
}
|
||||
@ -235,31 +416,77 @@ int ObExprCalcPartitionId::build_row(ObEvalCtx& ctx, ObIAllocator& allocator, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::calc_partition_id(const ObExpr& part_expr, ObEvalCtx& ctx,
|
||||
const CalcPartitionIdInfo& calc_part_info, int64_t first_part_id, ObDatum& res_datum)
|
||||
int ObExprCalcPartitionBase::add_interval_part(ObExecContext &exec_ctx,
|
||||
const CalcPartitionBaseInfo &calc_part_info,
|
||||
ObIAllocator &allocator, ObNewRow &row)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObTaskExecutorCtx* tctx = GET_TASK_EXECUTOR_CTX(ctx.exec_ctx_);
|
||||
ObSqlCtx* sql_ctx = ctx.exec_ctx_.get_sql_ctx();
|
||||
int64_t res_part_id = NONE_PARTITION_ID;
|
||||
ObSEArray<int64_t, 1> partition_ids;
|
||||
ObPartitionLevel part_level = (NONE_PARTITION_ID == first_part_id) ? PARTITION_LEVEL_ONE : PARTITION_LEVEL_TWO;
|
||||
ObPartitionFuncType part_type =
|
||||
(PARTITION_LEVEL_ONE == part_level) ? calc_part_info.part_type_ : calc_part_info.subpart_type_;
|
||||
if (OB_ISNULL(tctx) || OB_ISNULL(sql_ctx) || OB_ISNULL(sql_ctx->schema_guard_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", K(tctx), K(sql_ctx), K(ret));
|
||||
} else if (is_virtual_table(calc_part_info.ref_table_id_) &&
|
||||
OB_FAIL(tctx->init_calc_virtual_part_id_params(calc_part_info.ref_table_id_))) {
|
||||
LOG_WARN("fail to init_calc_virtual_part_id_params", K(ret), K(calc_part_info));
|
||||
// As long as init_calc_virtual_part_id_params is run, it must be run
|
||||
// reset_calc_virtual_part_id_params
|
||||
tctx->reset_calc_virtual_part_id_params();
|
||||
if (MayAddIntervalPart::YES == calc_part_info.may_add_interval_part_) {
|
||||
const uint64_t tenant_id = MTL_ID();
|
||||
const ObTableSchema *table_schema = NULL;
|
||||
bool is_interval = false;
|
||||
CK (OB_NOT_NULL(exec_ctx.get_sql_ctx()));
|
||||
OZ (exec_ctx.get_sql_ctx()->schema_guard_->get_table_schema(
|
||||
tenant_id, calc_part_info.ref_table_id_, table_schema));
|
||||
CK (OB_NOT_NULL(table_schema));
|
||||
OX (is_interval = table_schema->is_interval_part());
|
||||
if (OB_SUCC(ret) && is_interval) {
|
||||
if (OB_FAIL(ObTableLocation::send_add_interval_partition_rpc_new_engine(
|
||||
allocator, exec_ctx.get_sql_ctx()->session_info_,
|
||||
exec_ctx.get_sql_ctx()->schema_guard_, table_schema, row))) {
|
||||
if (is_need_retry_interval_part_error(ret)) {
|
||||
set_interval_partition_insert_error(ret);
|
||||
}
|
||||
LOG_WARN("failed to send add interval partition rpc", K(ret));
|
||||
} else {
|
||||
set_interval_partition_insert_error(ret);
|
||||
}
|
||||
}
|
||||
} else if (MayAddIntervalPart::PART_CHANGE_ERR == calc_part_info.may_add_interval_part_) {
|
||||
ret = OB_ERR_UPD_CAUSE_PART_CHANGE;
|
||||
LOG_WARN("cause partition movement", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
when the table is partitioned by interval, call this function may have three different action
|
||||
when the partition id is not exist.
|
||||
1. set part id to 0 indicate part not found, this is default action. used by normal part calc such
|
||||
as join repart
|
||||
2. add interval partition and set an error code force stmt retry. used by dml such as pdml shuffle
|
||||
3. set and error code and make the query stop and report and error msg to client, used by update
|
||||
partition key column which may cause partition changed. ex: update t1 set c1 = c1 + 201; t1 is
|
||||
interval partitioned which only has one partition created (0-200), and partitioned by c1.
|
||||
|
||||
function add_interval_part handle case 2, 3. case 1 is default.
|
||||
*
|
||||
*/
|
||||
int ObExprCalcPartitionBase::calc_partition_id(const ObExpr &part_expr,
|
||||
ObEvalCtx &ctx,
|
||||
const CalcPartitionBaseInfo &calc_part_info,
|
||||
ObObjectID first_part_id,
|
||||
ObTabletID &tablet_id,
|
||||
ObObjectID &partition_id)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSqlCtx *sql_ctx = ctx.exec_ctx_.get_sql_ctx();
|
||||
tablet_id.reset();
|
||||
partition_id = OB_INVALID_ID;
|
||||
ObPartitionLevel part_level = (OB_INVALID_ID == first_part_id)
|
||||
? PARTITION_LEVEL_ONE : PARTITION_LEVEL_TWO;
|
||||
ObPartitionFuncType part_type = (PARTITION_LEVEL_ONE == part_level)
|
||||
? calc_part_info.part_type_ : calc_part_info.subpart_type_;
|
||||
ObDASTabletMapper tablet_mapper;
|
||||
if (OB_FAIL(ctx.exec_ctx_.get_das_ctx().get_das_tablet_mapper(calc_part_info.ref_table_id_,
|
||||
tablet_mapper,
|
||||
&calc_part_info.related_table_ids_))) {
|
||||
LOG_WARN("get das tablet mapper failed", K(ret), K(calc_part_info));
|
||||
} else if (T_OP_ROW == part_expr.type_) {
|
||||
ObDatum* tmp_datum = NULL;
|
||||
// Calculate the value of expr child in advance, instead of calling eval directly in the build row,
|
||||
// It is to avoid reset tmp alloc used in eval calculation, which affects the following allocation row
|
||||
// cell memory usage of reset tmp alloc
|
||||
ObDatum *tmp_datum = NULL;
|
||||
//这里提前计算下expr child值, 而不是在build row中直接调用eval,
|
||||
//是为了避免eval计算里面会使用reset tmp alloc, 影响下面分配row中
|
||||
//cell内存对reset tmp alloc的使用
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < part_expr.arg_cnt_; i++) {
|
||||
if (OB_FAIL(part_expr.args_[i]->eval(ctx, tmp_datum))) {
|
||||
LOG_WARN("fail to eval part expr", K(ret), K(part_expr));
|
||||
@ -267,192 +494,132 @@ int ObExprCalcPartitionId::calc_partition_id(const ObExpr& part_expr, ObEvalCtx&
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObNewRow row;
|
||||
ObIAllocator& allocator = ctx.get_reset_tmp_alloc();
|
||||
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
|
||||
ObIAllocator &allocator = alloc_guard.get_allocator();
|
||||
if (OB_FAIL(build_row(ctx, allocator, part_expr, row))) {
|
||||
LOG_WARN("fail to build row", K(ret));
|
||||
} else if (OB_FAIL(sql_ctx->schema_guard_->get_part(
|
||||
calc_part_info.ref_table_id_, part_level, first_part_id, row, partition_ids))) {
|
||||
} else if (OB_FAIL(tablet_mapper.get_tablet_and_object_id(
|
||||
part_level,
|
||||
first_part_id,
|
||||
row,
|
||||
tablet_id,
|
||||
partition_id))) {
|
||||
LOG_WARN("Failed to get part id", K(ret), K(row));
|
||||
} else if (partition_ids.count() != 0 && partition_ids.count() != 1) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid partition cnt", K(ret), K(partition_ids));
|
||||
} else {
|
||||
res_part_id = (0 == partition_ids.count()) ? NONE_PARTITION_ID : partition_ids.at(0);
|
||||
if ((OB_INVALID_ID == partition_id) &&
|
||||
PARTITION_LEVEL_ONE == part_level &&
|
||||
NULL != ctx.exec_ctx_.get_my_session() &&
|
||||
ORACLE_MODE == ctx.exec_ctx_.get_my_session()->get_compatibility_mode()) {
|
||||
OZ (add_interval_part(ctx.exec_ctx_, calc_part_info, allocator, row),
|
||||
calc_part_info, first_part_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // not list/range columns
|
||||
} else { // not list/range columns
|
||||
ObObj func_value;
|
||||
ObObj result;
|
||||
ObDatum* datum = NULL;
|
||||
ObDatum *datum = NULL;
|
||||
if (OB_FAIL(part_expr.eval(ctx, datum))) {
|
||||
LOG_WARN("part expr evaluate failed", K(ret));
|
||||
} else if (OB_FAIL(datum->to_obj(func_value, part_expr.obj_meta_, part_expr.obj_datum_map_))) {
|
||||
} else if (OB_FAIL(datum->to_obj(func_value,
|
||||
part_expr.obj_meta_,
|
||||
part_expr.obj_datum_map_))) {
|
||||
LOG_WARN("convert datum to obj failed", K(ret));
|
||||
} else if (!is_inner_table(calc_part_info.ref_table_id_)) {
|
||||
} else {
|
||||
result = func_value;
|
||||
if (PARTITION_FUNC_TYPE_HASH == part_type || PARTITION_FUNC_TYPE_HASH_V2 == part_type) {
|
||||
if (share::is_oracle_mode()) {
|
||||
if (PARTITION_FUNC_TYPE_HASH == part_type) {
|
||||
if (lib::is_oracle_mode()) {
|
||||
// do nothing
|
||||
} else if (PARTITION_FUNC_TYPE_HASH == part_type) {
|
||||
if (OB_FAIL(ObExprFuncPartOldHash::calc_value_for_mysql(func_value, result))) {
|
||||
LOG_WARN("Failed to calc hash value mysql mode", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(ObExprFuncPartHash::calc_value_for_mysql(func_value, result))) {
|
||||
} else if (OB_FAIL(ObExprFuncPartHash::calc_value_for_mysql(func_value, result,
|
||||
func_value.get_type()))) {
|
||||
LOG_WARN("Failed to calc hash value mysql mode", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObSEArray<ObTabletID, 1> tablet_ids;
|
||||
ObSEArray<ObObjectID, 1> partition_ids;
|
||||
//这里也可以统一使用上面的ObNewRow接口, 并把calc_value_for_mysql
|
||||
// 用datum实现下, 暂时和以前的方式保持一致
|
||||
ObRowkey rowkey(const_cast<ObObj*>(&result), 1);
|
||||
ObNewRange range;
|
||||
if (OB_FAIL(range.build_range(calc_part_info.ref_table_id_, rowkey))) {
|
||||
LOG_WARN("Failed to build range", K(ret));
|
||||
} else if (OB_FAIL(sql_ctx->schema_guard_->get_part(
|
||||
calc_part_info.ref_table_id_, part_level, first_part_id, range, false, partition_ids))) {
|
||||
} else if (OB_FAIL(tablet_mapper.get_tablet_and_object_id(
|
||||
part_level,
|
||||
first_part_id,
|
||||
range,
|
||||
tablet_ids,
|
||||
partition_ids))) {
|
||||
LOG_WARN("Failed to get part id", K(ret));
|
||||
} else if (partition_ids.count() != 0 && partition_ids.count() != 1) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid partition cnt", K(ret), K(partition_ids));
|
||||
LOG_WARN("invalid partition cnt", K(ret), K(part_expr), K(partition_ids), K(range), K(rowkey));
|
||||
} else {
|
||||
res_part_id = (0 == partition_ids.count()) ? NONE_PARTITION_ID : partition_ids.at(0);
|
||||
if (0 == partition_ids.count() &&
|
||||
PARTITION_LEVEL_ONE == part_level &&
|
||||
NULL != ctx.exec_ctx_.get_my_session() &&
|
||||
ORACLE_MODE == ctx.exec_ctx_.get_my_session()->get_compatibility_mode()) {
|
||||
ObEvalCtx::TempAllocGuard alloc_guard(ctx);
|
||||
ObIAllocator &allocator = alloc_guard.get_allocator();
|
||||
ObNewRow row(const_cast<ObObj*>(&result), 1);
|
||||
OZ (add_interval_part(ctx.exec_ctx_, calc_part_info, allocator, row),
|
||||
calc_part_info, first_part_id);
|
||||
}
|
||||
if (OB_SUCC(ret) && 1 == partition_ids.count()) {
|
||||
partition_id = partition_ids.at(0);
|
||||
if (1 == tablet_ids.count()) {
|
||||
tablet_id = tablet_ids.at(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // inner table
|
||||
int64_t calc_result = 0;
|
||||
if (OB_FAIL(func_value.get_int(calc_result))) {
|
||||
LOG_WARN("Fail to get int64 from result", K(result), K(ret));
|
||||
} else if (OB_INVALID_PARTITION_ID == calc_result && is_virtual_table(calc_part_info.ref_table_id_)) {
|
||||
res_part_id = NONE_PARTITION_ID;
|
||||
// addr is invalid, and partition id calculated by this addr is also invalid, so, do nothing
|
||||
} else if (calc_result < 0 || 0 == calc_part_info.part_num_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid arguments", K(calc_result), K(calc_part_info), K(ret));
|
||||
} else {
|
||||
res_part_id = calc_result % calc_part_info.part_num_;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
res_datum.set_int(res_part_id);
|
||||
int64_t part_idx = (NONE_PARTITION_ID == res_part_id) ? OB_INVALID_INDEX : 0;
|
||||
ctx.exec_ctx_.get_part_row_manager().set_part_idx(part_idx);
|
||||
if (is_virtual_table(calc_part_info.ref_table_id_)) {
|
||||
tctx->reset_calc_virtual_part_id_params();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprCalcPartitionId::get_opt_route(
|
||||
const ObTableSchema& table_schema, const ObRawExpr& raw_expr, OptRouteType& opt_route_type)
|
||||
//calc partition id
|
||||
ObExprCalcPartitionId::ObExprCalcPartitionId(ObIAllocator &alloc)
|
||||
: ObExprCalcPartitionBase(alloc,
|
||||
T_FUN_SYS_CALC_PARTITION_ID,
|
||||
N_CALC_PARTITION_ID,
|
||||
PARAM_NUM_UNKNOWN,
|
||||
NOT_ROW_DIMENSION)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool enable_opt = false;
|
||||
if (OB_FAIL(enable_opt_route_hash_one(table_schema, raw_expr, enable_opt))) {
|
||||
LOG_WARN("fail to check enable use opt route hash one", K(ret));
|
||||
} else if (enable_opt) {
|
||||
opt_route_type = OPT_ROUTE_HASH_ONE;
|
||||
}
|
||||
// If there are other optimized execution paths, add judgment after this
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Determine the optimal path in different partition definition scenarios:
|
||||
// 1.OPT_ROUTE_HASH_ONE optimization
|
||||
// 1) Conditions:
|
||||
// a. The access is not the internal table
|
||||
// b. First-level partition
|
||||
// c. hash partition (non-columns partition)
|
||||
// d. All part_idx_ and part_id in ObPartition are the same, that is,
|
||||
// no partition management related operations have been done,
|
||||
// 2) Perform optimization:
|
||||
// The number of hash partitions is stored in CalcPartitionIdInfo, no need to obtain schema,
|
||||
// After calculating the partition part_idx according to the partition definition,
|
||||
// there is no need to look up the mapping table of part_idx-->part_id, and return to part_idx directly
|
||||
// 2. For other optimization scenarios,
|
||||
// we will continue to sort out the part_idx-->part id mapping table in the expression for optimization calculations
|
||||
int ObExprCalcPartitionId::enable_opt_route_hash_one(
|
||||
const ObTableSchema& table_schema, const ObRawExpr& raw_expr, bool& enable_opt_route_hash_one)
|
||||
ObExprCalcPartitionId::~ObExprCalcPartitionId()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
enable_opt_route_hash_one = true;
|
||||
const ObRawExpr* part_expr = NULL;
|
||||
if (is_inner_table(table_schema.get_table_id())) {
|
||||
enable_opt_route_hash_one = false;
|
||||
} else if (PARTITION_LEVEL_ONE != table_schema.get_part_level()) {
|
||||
enable_opt_route_hash_one = false;
|
||||
} else if (PARTITION_FUNC_TYPE_HASH != table_schema.get_part_option().get_part_func_type() &&
|
||||
PARTITION_FUNC_TYPE_HASH_V2 != table_schema.get_part_option().get_part_func_type()) {
|
||||
enable_opt_route_hash_one = false;
|
||||
} else if (1 != raw_expr.get_param_count() || (NULL == (part_expr = raw_expr.get_param_expr(0)))) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", K(raw_expr), K(table_schema), K(ret));
|
||||
} else if (T_OP_ROW == part_expr->get_expr_type()) {
|
||||
enable_opt_route_hash_one = false;
|
||||
} else {
|
||||
ObPartition** part_array = table_schema.get_part_array();
|
||||
bool same = true;
|
||||
for (int64_t i = 0; same && OB_SUCC(ret) && i < table_schema.get_partition_num(); i++) {
|
||||
if (OB_ISNULL(part_array[i])) {
|
||||
ret = OB_SCHEMA_ERROR;
|
||||
LOG_WARN("get invalid partiton array", K(ret), K(i));
|
||||
} else if (part_array[i]->get_part_idx() != part_array[i]->get_part_id()) {
|
||||
same = false;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !same) {
|
||||
enable_opt_route_hash_one = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 1.OPT_ROUTE_HASH_ONE optimization
|
||||
// 1) Conditions:
|
||||
// a. The access is not the internal table
|
||||
// b. First-level partition
|
||||
// c. hash partition (non-columns partition)
|
||||
// d. All part_idx_ and part_id in ObPartition are the same, that is,
|
||||
// no partition management related operations have been done,
|
||||
// 2) Perform optimization:
|
||||
// The number of hash partitions is stored in CalcPartitionIdInfo, no need to obtain schema,
|
||||
// After calculating the partition part_idx according to the partition definition,
|
||||
// there is no need to look up the mapping table of part_idx-->part_id, and return to part_idx directly
|
||||
int ObExprCalcPartitionId::calc_opt_route_hash_one(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res_datum)
|
||||
//calc tablet id
|
||||
ObExprCalcTabletId::ObExprCalcTabletId(ObIAllocator &alloc)
|
||||
: ObExprCalcPartitionBase(alloc,
|
||||
T_FUN_SYS_CALC_TABLET_ID,
|
||||
N_CALC_TABLET_ID,
|
||||
PARAM_NUM_UNKNOWN,
|
||||
NOT_ROW_DIMENSION)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OB_ASSERT(1 == expr.arg_cnt_);
|
||||
OB_ASSERT(NULL != expr.args_[0]);
|
||||
OB_ASSERT(expr.extra_ > 0);
|
||||
CalcPartitionIdInfo* calc_part_info = reinterpret_cast<CalcPartitionIdInfo*>(expr.extra_);
|
||||
ObDatum* datum = NULL;
|
||||
int64_t part_idx = 0;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, datum))) {
|
||||
LOG_WARN("part expr evaluate failed", K(ret));
|
||||
} else {
|
||||
int64_t value = 0;
|
||||
if (datum->is_null()) {
|
||||
// do nothing
|
||||
} else {
|
||||
value = datum->get_int();
|
||||
if (OB_UNLIKELY(INT64_MIN == value)) {
|
||||
value = INT64_MAX;
|
||||
} else {
|
||||
value = value < 0 ? -value : value;
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ObPartitionUtils::calc_hash_part_idx(value, calc_part_info->part_num_, part_idx))) {
|
||||
LOG_WARN("fail to calc hash part idx", K(ret), K(*calc_part_info), K(datum->get_int()));
|
||||
} else {
|
||||
res_datum.set_int(part_idx);
|
||||
LOG_TRACE("calc part id use opt route hash one", K(res_datum), K(*datum), K(*calc_part_info), K(value));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
ObExprCalcTabletId::~ObExprCalcTabletId()
|
||||
{
|
||||
}
|
||||
|
||||
//calc partition id and tablet id
|
||||
ObExprCalcPartitionTabletId::ObExprCalcPartitionTabletId(ObIAllocator &alloc)
|
||||
: ObExprCalcPartitionBase(alloc,
|
||||
T_FUN_SYS_CALC_PARTITION_TABLET_ID,
|
||||
N_CALC_PARTITION_TABLET_ID,
|
||||
PARAM_NUM_UNKNOWN,
|
||||
NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprCalcPartitionTabletId::~ObExprCalcPartitionTabletId()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user