5599 lines
235 KiB
C++
5599 lines
235 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#define USING_LOG_PREFIX SQL_OPT
|
|
#include "common/ob_smart_call.h"
|
|
#include "common/sql_mode/ob_sql_mode_utils.h"
|
|
#include "share/ob_i_tablet_scan.h"
|
|
#include "share/schema/ob_part_mgr_util.h"
|
|
#include "sql/ob_sql_define.h"
|
|
#include "sql/optimizer/ob_table_location.h"
|
|
#include "sql/ob_sql_utils.h"
|
|
#include "sql/ob_sql_trans_control.h"
|
|
#include "sql/resolver/dml/ob_update_stmt.h"
|
|
#include "sql/resolver/dml/ob_insert_stmt.h"
|
|
#include "sql/resolver/dml/ob_delete_resolver.h"
|
|
#include "sql/rewrite/ob_query_range_provider.h"
|
|
#include "sql/code_generator/ob_expr_generator_impl.h"
|
|
#include "sql/engine/expr/ob_sql_expression.h"
|
|
#include "sql/engine/expr/ob_expr_func_part_hash.h"
|
|
#include "sql/engine/expr/ob_expr_column_conv.h"
|
|
#include "storage/access/ob_dml_param.h"
|
|
#include "sql/engine/expr/ob_expr_result_type_util.h"
|
|
#include "sql/optimizer/ob_log_plan.h"
|
|
#include "sql/engine/cmd/ob_table_executor.h"
|
|
#include "sql/resolver/ddl/ob_alter_table_stmt.h"
|
|
#include "sql/resolver/expr/ob_raw_expr_printer.h"
|
|
#include "observer/omt/ob_tenant_timezone_mgr.h"
|
|
#include "sql/resolver/expr/ob_raw_expr.h"
|
|
#include "sql/resolver/expr/ob_raw_expr_util.h"
|
|
#include "sql/ob_sql_context.h"
|
|
#include "sql/das/ob_das_location_router.h"
|
|
#include "sql/dblink/ob_dblink_utils.h"
|
|
|
|
using namespace oceanbase::transaction;
|
|
using namespace oceanbase::sql;
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::share;
|
|
using namespace oceanbase::share::schema;
|
|
|
|
static int get_part_id_by_mod(const int64_t calc_result, const int64_t part_num, int64_t &part_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (calc_result < 0 || 0 == part_num) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Input arguments is invalid", K(calc_result), K(part_num), K(ret));
|
|
} else {
|
|
part_id = calc_result % part_num;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int is_all_ranges_empty(const ObQueryRangeArray &query_array, bool &is_empty)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_empty = true;
|
|
for (int i = 0; is_empty && OB_SUCC(ret) && i < query_array.count(); i++) {
|
|
if (OB_ISNULL(query_array.at(i))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret));
|
|
} else if (!query_array.at(i)->empty()) {
|
|
is_empty = false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObListPartMapKey::operator==(const ObListPartMapKey &other) const {
|
|
return row_ == other.row_;
|
|
}
|
|
|
|
int ObListPartMapKey::hash(uint64_t &hash_val) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
hash_val = 0;
|
|
for (int64_t i = 0; i < row_.get_count() && OB_SUCC(ret); i ++) {
|
|
if (OB_FAIL(row_.get_cell(i).hash(hash_val, hash_val))) {
|
|
LOG_WARN("hash failed", K(ret), K(row_.get_cell(i)));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObHashPartMapKey::operator==(const ObHashPartMapKey &other) const {
|
|
return part_idx_ == other.part_idx_;
|
|
}
|
|
|
|
int64_t ObHashPartMapKey::hash() const
|
|
{
|
|
uint64_t hash_value = 0;
|
|
ObObj idx_obj(part_idx_);
|
|
idx_obj.hash(hash_value, hash_value);
|
|
return hash_value;
|
|
}
|
|
|
|
bool TableLocationKey::operator==(const TableLocationKey &other) const {
|
|
return table_id_ == other.table_id_ && ref_table_id_ == other.ref_table_id_;
|
|
}
|
|
|
|
bool TableLocationKey::operator!=(const TableLocationKey &other) const {
|
|
return !(*this == other);
|
|
}
|
|
|
|
int ObTableLocation::PartProjector::init_part_projector(ObExecContext *exec_ctx,
|
|
const ObRawExpr *part_expr,
|
|
ObPartitionLevel part_level,
|
|
RowDesc &row_desc)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (PARTITION_LEVEL_ONE == part_level) {
|
|
ret = init_part_projector(exec_ctx, part_expr, row_desc);
|
|
} else if (PARTITION_LEVEL_TWO == part_level) {
|
|
ret = init_subpart_projector(exec_ctx, part_expr, row_desc);
|
|
} else { /*do nothing*/ }
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::PartProjector::init_part_projector(ObExecContext *exec_ctx,
|
|
const ObRawExpr *part_expr,
|
|
RowDesc &row_desc)
|
|
{
|
|
return init_part_projector(exec_ctx, part_expr, row_desc,
|
|
part_projector_, part_projector_size_);
|
|
}
|
|
|
|
int ObTableLocation::PartProjector::init_subpart_projector(ObExecContext *exec_ctx,
|
|
const ObRawExpr *part_expr,
|
|
RowDesc &row_desc)
|
|
{
|
|
return init_part_projector(exec_ctx, part_expr, row_desc,
|
|
subpart_projector_, subpart_projector_size_);
|
|
}
|
|
|
|
int ObTableLocation::PartProjector::init_part_projector(ObExecContext *exec_ctx,
|
|
const ObRawExpr *part_expr,
|
|
RowDesc &row_desc,
|
|
int32_t *&projector,
|
|
int64_t &projector_size)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ObRawExpr*, 4> part_columns;
|
|
if (OB_ISNULL(exec_ctx) || OB_ISNULL(exec_ctx->get_sql_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(ret));
|
|
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(part_expr, part_columns))) {
|
|
LOG_WARN("extract column exprs failed", K(ret));
|
|
} else {
|
|
projector_size = part_columns.count();
|
|
if (OB_ISNULL(projector = static_cast<int32_t*>(allocator_.alloc(projector_size * sizeof(int64_t))))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("allocate memory failed", K(projector_size));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < projector_size; ++i) {
|
|
int64_t idx = OB_INVALID_INDEX;
|
|
const ObRawExpr *part_column = part_columns.at(i);
|
|
if (OB_ISNULL(part_column)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("part column is null");
|
|
} else if (OB_UNLIKELY(!part_column->is_column_ref_expr())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("part column isn't column reference", K(ret), K(*part_column));
|
|
} else if (OB_FAIL(row_desc.get_idx(part_column, idx)) && OB_ENTRY_NOT_EXIST != ret) {
|
|
LOG_WARN("get idx failed", K(ret));
|
|
} else if (OB_ENTRY_NOT_EXIST == ret ) {
|
|
ret = OB_SUCCESS;
|
|
const ObColumnRefRawExpr *col_ref = static_cast<const ObColumnRefRawExpr *>(part_column);
|
|
if (OB_UNLIKELY(!col_ref->is_generated_column())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("column reference isn't generated column", K(ret), K(*col_ref));
|
|
} else {
|
|
ObTempExpr *se_virtual_col = NULL;
|
|
OZ(ObStaticEngineExprCG::gen_expr_with_row_desc(col_ref->get_dependant_expr(),
|
|
row_desc, exec_ctx->get_allocator(),
|
|
exec_ctx->get_my_session(),
|
|
exec_ctx->get_sql_ctx()->schema_guard_,
|
|
se_virtual_col));
|
|
CK(OB_NOT_NULL(se_virtual_col));
|
|
OZ(se_virtual_column_exprs_.push_back(se_virtual_col));
|
|
OZ(virtual_column_result_idx_.push_back(row_desc.get_column_num()));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(row_desc.add_column(const_cast<ObRawExpr*>(part_column)))) {
|
|
LOG_WARN("add part column to row desc failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(row_desc.get_idx(part_column, idx))) {
|
|
LOG_WARN("part_column isn't invalid", K(ret), K(*part_column));
|
|
} else {
|
|
projector[i] = static_cast<int32_t>(idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::PartProjector::calc_part_row(ObExecContext &ctx,
|
|
const ObNewRow &input_row,
|
|
ObNewRow *&part_row) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRow &cur_part_row = ctx.get_part_row_manager().get_part_row();
|
|
int64_t virtual_col_size = se_virtual_column_exprs_.count();
|
|
if (virtual_col_size <= 0) {
|
|
cur_part_row.cells_ = input_row.cells_;
|
|
cur_part_row.count_ = column_cnt_;
|
|
} else {
|
|
cur_part_row.count_ = column_cnt_;
|
|
if (OB_ISNULL(cur_part_row.cells_)) {
|
|
//part row的cells未分配,这里先为cells分配空间
|
|
int64_t row_size = sizeof(ObObj) * column_cnt_;
|
|
cur_part_row.cells_ = static_cast<ObObj*>(ctx.get_allocator().alloc(row_size));
|
|
if (OB_ISNULL(cur_part_row.cells_)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("allocate memory for current part row failed", K(ret), K(row_size));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
int64_t copy_row_size = (column_cnt_ - virtual_col_size) * sizeof(ObObj);
|
|
memcpy(cur_part_row.cells_, input_row.cells_, copy_row_size);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
CK(se_virtual_column_exprs_.count() == virtual_column_result_idx_.count());
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < se_virtual_column_exprs_.count(); i++) {
|
|
ObTempExpr *expr = se_virtual_column_exprs_.at(i);
|
|
int64_t result_idx = virtual_column_result_idx_.at(i);
|
|
OZ(expr->eval(ctx, cur_part_row, cur_part_row.cells_[result_idx]));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
part_row = &cur_part_row;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObTableLocation::PartProjector::project_part_row(ObPartitionLevel part_level, ObNewRow &part_row) const
|
|
{
|
|
int32_t *projector = NULL;
|
|
int64_t projector_size = 0;
|
|
if (part_level == PARTITION_LEVEL_ONE) {
|
|
projector = part_projector_;
|
|
projector_size = part_projector_size_;
|
|
} else if (part_level == PARTITION_LEVEL_TWO) {
|
|
projector = subpart_projector_;
|
|
projector_size = subpart_projector_size_;
|
|
} else { /*do nothing*/ }
|
|
part_row.projector_ = projector;
|
|
part_row.projector_size_ = projector_size;
|
|
}
|
|
|
|
int ObTableLocation::PartProjector::deep_copy(const PartProjector &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
void *ptr = NULL;
|
|
int64_t buf_len = 0;
|
|
part_projector_size_ = other.part_projector_size_;
|
|
subpart_projector_size_ = other.subpart_projector_size_;
|
|
column_cnt_ = other.column_cnt_;
|
|
if (other.part_projector_ != NULL) {
|
|
buf_len = sizeof(int32_t) * other.part_projector_size_;
|
|
if (OB_ISNULL(ptr = allocator_.alloc(buf_len))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("allocate projector buffer failed", K(buf_len), K_(part_projector));
|
|
} else {
|
|
part_projector_ = static_cast<int32_t*>(ptr);
|
|
memcpy(part_projector_, other.part_projector_, buf_len);
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && other.subpart_projector_ != NULL) {
|
|
buf_len = sizeof(int32_t) * other.subpart_projector_size_;
|
|
if (OB_ISNULL(ptr = allocator_.alloc(buf_len))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("allocate subpart projector buffer failed", K(buf_len), K_(subpart_projector_size));
|
|
} else {
|
|
subpart_projector_ = static_cast<int32_t*>(ptr);
|
|
memcpy(subpart_projector_, other.subpart_projector_, buf_len);
|
|
}
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < other.se_virtual_column_exprs_.count(); i++) {
|
|
ObTempExpr *expr = NULL;
|
|
OZ(other.se_virtual_column_exprs_.at(i)->deep_copy(allocator_, expr));
|
|
OZ(se_virtual_column_exprs_.push_back(expr));
|
|
}
|
|
OZ(virtual_column_result_idx_.assign(other.virtual_column_result_idx_));
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE(ObTableLocation::PartProjector)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
OB_UNIS_ENCODE_ARRAY(part_projector_, part_projector_size_);
|
|
OB_UNIS_ENCODE_ARRAY(subpart_projector_, subpart_projector_size_);
|
|
OB_UNIS_ENCODE(column_cnt_);
|
|
if (OB_SUCC(ret)) {
|
|
OB_UNIS_ENCODE(se_virtual_column_exprs_.count());
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < se_virtual_column_exprs_.count(); i++) {
|
|
OB_UNIS_ENCODE(*se_virtual_column_exprs_.at(i));
|
|
}
|
|
OB_UNIS_ENCODE(virtual_column_result_idx_);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObTableLocation::PartProjector)
|
|
{
|
|
int64_t len = 0;
|
|
OB_UNIS_ADD_LEN_ARRAY(part_projector_, part_projector_size_);
|
|
OB_UNIS_ADD_LEN_ARRAY(subpart_projector_, subpart_projector_size_);
|
|
OB_UNIS_ADD_LEN(column_cnt_);
|
|
OB_UNIS_ADD_LEN(se_virtual_column_exprs_.count());
|
|
for (int64_t i = 0; i < se_virtual_column_exprs_.count(); i++) {
|
|
OB_UNIS_ADD_LEN(*se_virtual_column_exprs_.at(i));
|
|
}
|
|
OB_UNIS_ADD_LEN(virtual_column_result_idx_);
|
|
return len;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObTableLocation::PartProjector)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
void *ptr = NULL;
|
|
OB_UNIS_DECODE(part_projector_size_);
|
|
if (OB_SUCC(ret) && part_projector_size_ > 0) {
|
|
int64_t buf_len = sizeof(int32_t) * part_projector_size_;
|
|
if (OB_ISNULL(ptr = allocator_.alloc(buf_len))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("allocate projector buffer failed", K(buf_len), K_(part_projector));
|
|
} else {
|
|
part_projector_ = static_cast<int32_t*>(ptr);
|
|
OB_UNIS_DECODE_ARRAY(part_projector_, part_projector_size_);
|
|
}
|
|
}
|
|
OB_UNIS_DECODE(subpart_projector_size_);
|
|
if (OB_SUCC(ret) && subpart_projector_size_ > 0) {
|
|
int64_t buf_len = sizeof(int32_t) * subpart_projector_size_;
|
|
if (OB_ISNULL(ptr = allocator_.alloc(buf_len))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("allocate projector buffer failed", K(buf_len), K_(subpart_projector));
|
|
} else {
|
|
subpart_projector_ = static_cast<int32_t*>(ptr);
|
|
OB_UNIS_DECODE_ARRAY(subpart_projector_, subpart_projector_size_);
|
|
}
|
|
}
|
|
OB_UNIS_DECODE(column_cnt_);
|
|
int64_t virtual_col_count = 0;
|
|
OB_UNIS_DECODE(virtual_col_count);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < virtual_col_count; i++) {
|
|
ObTempExpr *expr = NULL;
|
|
char *mem = static_cast<char *>(allocator_.alloc(sizeof(ObTempExpr)));
|
|
CK(OB_NOT_NULL(mem));
|
|
OX(expr = new(mem)ObTempExpr(allocator_));
|
|
OB_UNIS_DECODE(*expr);
|
|
OZ(se_virtual_column_exprs_.push_back(expr));
|
|
}
|
|
OB_UNIS_DECODE(virtual_column_result_idx_);
|
|
|
|
return ret;
|
|
}
|
|
|
|
ObPartLocCalcNode *ObPartLocCalcNode::create_part_calc_node(
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
|
ObPartLocCalcNode::NodeType type)
|
|
{
|
|
void *ptr = NULL;
|
|
ObPartLocCalcNode *ret_node = NULL;
|
|
switch (type) {
|
|
case ObPartLocCalcNode::QUERY_RANGE: {
|
|
ptr = allocator.alloc(sizeof(ObPLQueryRangeNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLQueryRangeNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::FUNC_VALUE: {
|
|
ptr = allocator.alloc(sizeof(ObPLFuncValueNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLFuncValueNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::COLUMN_VALUE: {
|
|
ptr = allocator.alloc(sizeof(ObPLColumnValueNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLColumnValueNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::CALC_AND: {
|
|
ptr = allocator.alloc(sizeof(ObPLAndNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLAndNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::CALC_OR: {
|
|
ptr = allocator.alloc(sizeof(ObPLOrNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLOrNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
LOG_WARN_RET(OB_ERR_UNEXPECTED, "Invalid ObPartLocCalcNode type", K(type));
|
|
break;
|
|
}
|
|
}
|
|
if (OB_UNLIKELY(NULL == ptr)
|
|
|| OB_UNLIKELY(NULL == ret_node)) {
|
|
LOG_WARN_RET(OB_ALLOCATE_MEMORY_FAILED, "Failed to allocate ObPartLocCalcNode", K(type));
|
|
} else if (OB_SUCCESS != calc_nodes.push_back(ret_node)) {
|
|
ret_node->~ObPartLocCalcNode();
|
|
allocator.free(ret_node);
|
|
ret_node = NULL;
|
|
LOG_WARN_RET(OB_ERR_UNEXPECTED, "Store ObPartLocCalcNode failed");
|
|
} else { }//do nothing
|
|
|
|
return ret_node;
|
|
}
|
|
|
|
int ObPartLocCalcNode::create_part_calc_node(common::ObIAllocator &allocator,
|
|
ObPartLocCalcNode::NodeType type,
|
|
ObPartLocCalcNode *&calc_node)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
void *ptr = NULL;
|
|
ObPartLocCalcNode *ret_node = NULL;
|
|
switch (type) {
|
|
case ObPartLocCalcNode::QUERY_RANGE: {
|
|
ptr = allocator.alloc(sizeof(ObPLQueryRangeNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLQueryRangeNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::FUNC_VALUE: {
|
|
ptr = allocator.alloc(sizeof(ObPLFuncValueNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLFuncValueNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::COLUMN_VALUE: {
|
|
ptr = allocator.alloc(sizeof(ObPLColumnValueNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLColumnValueNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::CALC_AND: {
|
|
ptr = allocator.alloc(sizeof(ObPLAndNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLAndNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
case ObPartLocCalcNode::CALC_OR: {
|
|
ptr = allocator.alloc(sizeof(ObPLOrNode));
|
|
if (NULL != ptr) {
|
|
ret_node = new(ptr) ObPLOrNode(allocator);
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
LOG_WARN("Invalid ObPartLocCalcNode type", K(type));
|
|
break;
|
|
}
|
|
}
|
|
if (OB_UNLIKELY(NULL == ptr)
|
|
|| OB_UNLIKELY(NULL == ret_node)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Failed to allocate ObPartLocCalcNode", K(type));
|
|
} else {
|
|
calc_node = ret_node;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLAndNode::deep_copy(
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
|
ObPartLocCalcNode *&other) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(other = create_part_calc_node(allocator, calc_nodes, CALC_AND))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Allocate calc node failed", K(ret));
|
|
} else {
|
|
ObPartLocCalcNode *left_node = NULL;
|
|
ObPartLocCalcNode *right_node = NULL;
|
|
if (NULL != left_node_
|
|
&& OB_FAIL(left_node_->deep_copy(allocator, calc_nodes, left_node))) {
|
|
LOG_WARN("Failed to deep copy left node", K(ret));
|
|
} else if (NULL != right_node_
|
|
&& OB_FAIL(right_node_->deep_copy(allocator, calc_nodes, right_node))) {
|
|
LOG_WARN("Failed todeep copy right node", K(ret));
|
|
} else {
|
|
ObPLAndNode *and_node = static_cast<ObPLAndNode*>(other);
|
|
and_node->left_node_ = left_node;
|
|
and_node->right_node_ = right_node;
|
|
}
|
|
}
|
|
return ret;
|
|
|
|
}
|
|
|
|
int ObPLAndNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_NOT_NULL(left_node_) && OB_NOT_NULL(right_node_)) {
|
|
if (OB_FAIL(SMART_CALL(left_node_->add_part_calc_node(calc_nodes)))) {
|
|
LOG_WARN("fail to add part calc node", K(ret));
|
|
} else if (OB_FAIL(SMART_CALL(right_node_->add_part_calc_node(calc_nodes)))) {
|
|
LOG_WARN("fail to add part calc node", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(calc_nodes.push_back(this))) {
|
|
LOG_WARN("fail to push back calc nodes", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLOrNode::deep_copy(
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
|
ObPartLocCalcNode *&other) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(other = create_part_calc_node(allocator, calc_nodes, CALC_OR))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Allocate calc node failed", K(ret));
|
|
} else {
|
|
ObPartLocCalcNode *left_node = NULL;
|
|
ObPartLocCalcNode *right_node = NULL;
|
|
if (NULL != left_node_
|
|
&& OB_FAIL(left_node_->deep_copy(allocator, calc_nodes, left_node))) {
|
|
LOG_WARN("Failed to deep copy left node", K(ret));
|
|
} else if (NULL != right_node_
|
|
&& OB_FAIL(right_node_->deep_copy(allocator, calc_nodes, right_node))) {
|
|
LOG_WARN("Failed todeep copy right node", K(ret));
|
|
} else {
|
|
ObPLOrNode *or_node = static_cast<ObPLOrNode*>(other);
|
|
or_node->left_node_ = left_node;
|
|
or_node->right_node_ = right_node;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLOrNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_NOT_NULL(left_node_) && OB_NOT_NULL(right_node_)) {
|
|
if (OB_FAIL(SMART_CALL(left_node_->add_part_calc_node(calc_nodes)))) {
|
|
LOG_WARN("fail to add part calc node", K(ret));
|
|
} else if (OB_FAIL(SMART_CALL(right_node_->add_part_calc_node(calc_nodes)))) {
|
|
LOG_WARN("fail to add part calc node", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(calc_nodes.push_back(this))) {
|
|
LOG_WARN("fail to push back calc nodes", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLQueryRangeNode::deep_copy(
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
|
ObPartLocCalcNode *&other) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(other = create_part_calc_node(allocator, calc_nodes, QUERY_RANGE))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Allocate calc node failed", K(ret));
|
|
} else {
|
|
ObPLQueryRangeNode *qr_node = static_cast<ObPLQueryRangeNode*>(other);
|
|
if (OB_FAIL(qr_node->pre_query_range_.deep_copy(pre_query_range_))) {
|
|
LOG_WARN("Failed to deep copy pre query range", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLQueryRangeNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes)
|
|
{
|
|
return calc_nodes.push_back(this);
|
|
}
|
|
|
|
int ObPLFuncValueNode::deep_copy(
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
|
ObPartLocCalcNode *&other) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(other = create_part_calc_node(allocator, calc_nodes, FUNC_VALUE))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Allocate calc node failed", K(ret));
|
|
} else {
|
|
ObPLFuncValueNode *func_node = static_cast<ObPLFuncValueNode*>(other);
|
|
if (OB_FAIL(vie_.deep_copy(allocator, func_node->vie_))) {
|
|
LOG_WARN("Failed to deep copy value", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLFuncValueNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes)
|
|
{
|
|
return calc_nodes.push_back(this);
|
|
}
|
|
|
|
int ObPLColumnValueNode::deep_copy(
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObPartLocCalcNode*> &calc_nodes,
|
|
ObPartLocCalcNode *&other) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(other = create_part_calc_node(allocator, calc_nodes, COLUMN_VALUE))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Allocate calc node failed", K(ret));
|
|
} else {
|
|
ObPLColumnValueNode *column_node = static_cast<ObPLColumnValueNode*>(other);
|
|
if (OB_FAIL(vie_.deep_copy(allocator, column_node->vie_))) {
|
|
LOG_WARN("Failed to deep copy value", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
int ObPLColumnValueNode::add_part_calc_node(common::ObIArray<ObPartLocCalcNode*> &calc_nodes)
|
|
{
|
|
return calc_nodes.push_back(this);
|
|
}
|
|
|
|
|
|
int ObTableLocation::get_location_type(const common::ObAddr &server,
|
|
const ObCandiTabletLocIArray &phy_part_loc_info_list,
|
|
ObTableLocationType &location_type) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
location_type = OB_TBL_LOCATION_UNINITIALIZED;
|
|
const TableItem *table_item = NULL;
|
|
if (0 == phy_part_loc_info_list.count()) {
|
|
location_type = OB_TBL_LOCATION_LOCAL;
|
|
} else if (1 == phy_part_loc_info_list.count()) {
|
|
share::ObLSReplicaLocation replica_location;
|
|
if (OB_FAIL(phy_part_loc_info_list.at(0).get_selected_replica(replica_location))) {
|
|
LOG_WARN("fail to get selected replica", K(phy_part_loc_info_list.at(0)));
|
|
} else if (!replica_location.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("replica location is invalid", K(ret), K(replica_location));
|
|
} else {
|
|
location_type = ((server == replica_location.get_server()) ? OB_TBL_LOCATION_LOCAL
|
|
: OB_TBL_LOCATION_REMOTE);
|
|
}
|
|
} else {
|
|
location_type = OB_TBL_LOCATION_DISTRIBUTED;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObTableLocation::ObTableLocation(const ObTableLocation &other) :
|
|
inner_allocator_(ObModIds::OB_SQL_TABLE_LOCATION),
|
|
allocator_(inner_allocator_),
|
|
loc_meta_(inner_allocator_),
|
|
calc_node_(NULL),
|
|
gen_col_node_(NULL),
|
|
subcalc_node_(NULL),
|
|
sub_gen_col_node_(NULL),
|
|
part_projector_(allocator_),
|
|
related_list_(allocator_)
|
|
{
|
|
*this = other;
|
|
}
|
|
|
|
ObTableLocation& ObTableLocation::operator=(const ObTableLocation &other)
|
|
{
|
|
IGNORE_RETURN this->assign(other);
|
|
return *this;
|
|
}
|
|
|
|
int ObTableLocation::assign(const ObTableLocation &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (this != &other) {
|
|
reset();
|
|
inited_ = other.inited_;
|
|
is_partitioned_ = other.is_partitioned_;
|
|
part_level_ = other.part_level_;
|
|
part_type_ = other.part_type_;
|
|
subpart_type_ = other.subpart_type_;
|
|
part_get_all_ = other.part_get_all_;
|
|
subpart_get_all_ = other.subpart_get_all_;
|
|
is_col_part_expr_ = other.is_col_part_expr_;
|
|
is_col_subpart_expr_ = other.is_col_subpart_expr_;
|
|
is_oracle_temp_table_ = other.is_oracle_temp_table_;
|
|
table_type_ = other.table_type_;
|
|
part_col_type_ = other.part_col_type_;
|
|
part_collation_type_ = other.part_collation_type_;
|
|
subpart_col_type_ = other.subpart_col_type_;
|
|
subpart_collation_type_ = other.subpart_collation_type_;
|
|
is_in_hit_ = other.is_in_hit_;
|
|
stmt_type_ = other.stmt_type_;
|
|
is_valid_range_columns_part_range_ = other.is_valid_range_columns_part_range_;
|
|
is_valid_range_columns_subpart_range_ = other.is_valid_range_columns_subpart_range_;
|
|
has_dynamic_exec_param_ = other.has_dynamic_exec_param_;
|
|
is_valid_temporal_part_range_ = other.is_valid_temporal_part_range_;
|
|
is_valid_temporal_subpart_range_ = other.is_valid_temporal_subpart_range_;
|
|
is_part_range_get_ = other.is_part_range_get_;
|
|
is_subpart_range_get_ = other.is_subpart_range_get_;
|
|
is_non_partition_optimized_ = other.is_non_partition_optimized_;
|
|
tablet_id_ = other.tablet_id_;
|
|
object_id_ = other.object_id_;
|
|
check_no_partiton_ = other.check_no_partiton_;
|
|
if (OB_FAIL(loc_meta_.assign(other.loc_meta_))) {
|
|
LOG_WARN("assign loc meta failed", K(ret), K(other.loc_meta_));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL != other.calc_node_) {
|
|
if (OB_FAIL(other.calc_node_->deep_copy(allocator_, calc_nodes_, calc_node_))) {
|
|
LOG_WARN("Failed to deep copy node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL != other.gen_col_node_) {
|
|
if (OB_FAIL(other.gen_col_node_->deep_copy(allocator_, calc_nodes_,
|
|
gen_col_node_))) {
|
|
LOG_WARN("Failed to deep copy node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL != other.subcalc_node_) {
|
|
if (OB_FAIL(other.subcalc_node_->deep_copy(allocator_, calc_nodes_, subcalc_node_))) {
|
|
LOG_WARN("Failed to deep copy node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL != other.sub_gen_col_node_) {
|
|
if (OB_FAIL(other.sub_gen_col_node_->deep_copy(allocator_, calc_nodes_,
|
|
sub_gen_col_node_))) {
|
|
LOG_WARN("Failed to deep copy node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!is_partitioned_) {
|
|
// do nothing
|
|
} else if (OB_FAIL(part_projector_.deep_copy(other.part_projector_))) {
|
|
LOG_WARN("deep copy part projector failed", K(ret));
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(part_hint_ids_.assign(other.part_hint_ids_))) {
|
|
LOG_WARN("Failed to assign part hint ids", K(ret));
|
|
}
|
|
LOG_TRACE("deep copy table location", K(other));
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < other.vies_.count(); i++) {
|
|
ValueItemExpr vie;
|
|
OZ(other.vies_.at(i).deep_copy(allocator_, vie));
|
|
OZ(vies_.push_back(vie));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < other.sub_vies_.count(); i++) {
|
|
ValueItemExpr vie;
|
|
OZ(other.sub_vies_.at(i).deep_copy(allocator_, vie));
|
|
OZ(sub_vies_.push_back(vie));
|
|
}
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(other.se_part_expr_)) {
|
|
OZ(other.se_part_expr_->deep_copy(allocator_, se_part_expr_));
|
|
}
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(other.se_subpart_expr_)) {
|
|
OZ(other.se_subpart_expr_->deep_copy(allocator_, se_subpart_expr_));
|
|
}
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(other.se_gen_col_expr_)) {
|
|
OZ(other.se_gen_col_expr_->deep_copy(allocator_, se_gen_col_expr_));
|
|
}
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(other.se_sub_gen_col_expr_)) {
|
|
OZ(other.se_sub_gen_col_expr_->deep_copy(allocator_, se_sub_gen_col_expr_));
|
|
}
|
|
if (OB_SUCC(ret) && OB_FAIL(related_list_.assign(other.related_list_))) {
|
|
LOG_WARN("assign related list failed", K(ret));
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
inited_ = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObTableLocation::reset()
|
|
{
|
|
inited_ = false;
|
|
loc_meta_.reset();
|
|
is_partitioned_ = true;
|
|
part_level_ = PARTITION_LEVEL_ZERO;
|
|
part_type_ = PARTITION_FUNC_TYPE_MAX;
|
|
subpart_type_ = share::schema::PARTITION_FUNC_TYPE_MAX;
|
|
part_get_all_ = false;
|
|
subpart_get_all_ = false;
|
|
is_col_part_expr_ = false;
|
|
is_col_subpart_expr_ = false;
|
|
is_oracle_temp_table_ = false;
|
|
table_type_ = MAX_TABLE_TYPE;
|
|
|
|
calc_node_ = NULL;
|
|
gen_col_node_ = NULL;
|
|
subcalc_node_ = NULL;
|
|
sub_gen_col_node_ = NULL;
|
|
for (int64_t idx = 0; idx < calc_nodes_.count(); ++idx) {
|
|
if (NULL != calc_nodes_.at(idx)) {
|
|
calc_nodes_.at(idx)->~ObPartLocCalcNode();
|
|
}
|
|
}
|
|
calc_nodes_.reset();
|
|
stmt_type_ = stmt::T_NONE;
|
|
vies_.reset();
|
|
sub_vies_.reset();
|
|
se_part_expr_ = NULL;
|
|
se_gen_col_expr_ = NULL;
|
|
se_subpart_expr_ = NULL;
|
|
se_sub_gen_col_expr_ = NULL;
|
|
part_hint_ids_.reset();
|
|
part_col_type_ = ObNullType;
|
|
related_list_.reset();
|
|
inner_allocator_.reset();
|
|
part_collation_type_ = CS_TYPE_INVALID;
|
|
subpart_col_type_ = ObNullType;
|
|
subpart_collation_type_ = CS_TYPE_INVALID;
|
|
is_in_hit_ = false;
|
|
part_projector_.reset();
|
|
is_valid_range_columns_part_range_ = false;
|
|
is_valid_range_columns_subpart_range_ = false;
|
|
has_dynamic_exec_param_ = false;
|
|
is_valid_temporal_part_range_ = false;
|
|
is_valid_temporal_subpart_range_ = false;
|
|
is_part_range_get_ = false;
|
|
is_subpart_range_get_ = false;
|
|
is_non_partition_optimized_ = false;
|
|
tablet_id_.reset();
|
|
object_id_ = OB_INVALID_ID;
|
|
check_no_partiton_ = false;
|
|
}
|
|
int ObTableLocation::init(share::schema::ObSchemaGetterGuard &schema_guard,
|
|
const ObDMLStmt &stmt,
|
|
ObExecContext *exec_ctx,
|
|
const common::ObIArray<ObRawExpr*> &filter_exprs,
|
|
const uint64_t table_id,
|
|
const uint64_t ref_table_id,
|
|
const common::ObIArray<common::ObObjectID> *part_ids,
|
|
const common::ObDataTypeCastParams &dtc_params,
|
|
const bool is_dml_table,
|
|
common::ObIArray<ObRawExpr*> *sort_exprs)
|
|
{
|
|
int ret = common::OB_SUCCESS;
|
|
const share::schema::ObTableSchema *table_schema = NULL;
|
|
if (OB_ISNULL(exec_ctx) || OB_ISNULL(exec_ctx->get_my_session())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected NULL", K(ret), K(exec_ctx));
|
|
} else if (OB_FAIL(schema_guard.get_table_schema(exec_ctx->get_my_session()->get_effective_tenant_id(),
|
|
ref_table_id, table_schema))) {
|
|
SQL_OPT_LOG(WARN, "failed to get table schema", K(ret), K(ref_table_id));
|
|
} else if (OB_FAIL(init(table_schema, stmt, exec_ctx, filter_exprs, table_id,
|
|
ref_table_id, part_ids, dtc_params, is_dml_table, sort_exprs))) {
|
|
SQL_OPT_LOG(WARN, "failed to init", K(ret), K(ref_table_id));
|
|
}
|
|
return ret;
|
|
}
|
|
int ObTableLocation::init(ObSqlSchemaGuard &schema_guard,
|
|
const ObDMLStmt &stmt,
|
|
ObExecContext *exec_ctx,
|
|
const common::ObIArray<ObRawExpr*> &filter_exprs,
|
|
const uint64_t table_id,
|
|
const uint64_t ref_table_id,
|
|
const common::ObIArray<common::ObObjectID> *part_ids,
|
|
const common::ObDataTypeCastParams &dtc_params,
|
|
const bool is_dml_table,
|
|
common::ObIArray<ObRawExpr*> *sort_exprs)
|
|
{
|
|
int ret = common::OB_SUCCESS;
|
|
const share::schema::ObTableSchema *table_schema = NULL;
|
|
if (OB_FAIL(schema_guard.get_table_schema(ref_table_id, table_schema))) {
|
|
SQL_OPT_LOG(WARN, "failed to get table schema", K(ret), K(ref_table_id));
|
|
} else if (OB_FAIL(init(table_schema, stmt, exec_ctx, filter_exprs, table_id,
|
|
ref_table_id, part_ids, dtc_params, is_dml_table, sort_exprs))) {
|
|
SQL_OPT_LOG(WARN, "failed to init", K(ret), K(ref_table_id));
|
|
}
|
|
return ret;
|
|
}
|
|
int ObTableLocation::init_location(ObSqlSchemaGuard *schema_guard,
|
|
const ObDMLStmt &stmt,
|
|
ObExecContext *exec_ctx,
|
|
const common::ObIArray<ObRawExpr*> &filter_exprs,
|
|
const uint64_t table_id,
|
|
const uint64_t ref_table_id,
|
|
const ObIArray<ObObjectID> *part_ids,
|
|
const common::ObDataTypeCastParams &dtc_params,
|
|
const bool is_dml_table,
|
|
common::ObIArray<ObRawExpr*> *sort_exprs)
|
|
{
|
|
int ret = common::OB_SUCCESS;
|
|
const share::schema::ObTableSchema *table_schema = NULL;
|
|
if (OB_FAIL(schema_guard->get_table_schema(ref_table_id, table_schema))) {
|
|
SQL_OPT_LOG(WARN, "failed to get table schema", K(ret), K(ref_table_id));
|
|
} else if (OB_FAIL(init(table_schema, stmt, exec_ctx, filter_exprs, table_id,
|
|
ref_table_id, part_ids, dtc_params, is_dml_table, sort_exprs))) {
|
|
SQL_OPT_LOG(WARN, "failed to init", K(ret), K(ref_table_id));
|
|
}
|
|
return ret;
|
|
}
|
|
int ObTableLocation::init_table_location(ObExecContext &exec_ctx,
|
|
ObSqlSchemaGuard &schema_guard,
|
|
uint64_t table_id,
|
|
uint64_t ref_table_id,
|
|
const ObDMLStmt &stmt,
|
|
const RowDesc &row_desc,
|
|
const bool is_dml_table, /*whether the ref_table is modified*/
|
|
const ObOrderDirection &direction)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(direction);
|
|
const ObTableSchema *table_schema = NULL;
|
|
const ObRawExpr *part_raw_expr = NULL;
|
|
RowDesc loc_row_desc;
|
|
loc_meta_.table_loc_id_ = table_id;
|
|
loc_meta_.ref_table_id_ = ref_table_id;
|
|
stmt_type_ = stmt.get_stmt_type();
|
|
is_partitioned_ = true;
|
|
if (OB_ISNULL(stmt.get_query_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("stmt query ctx is null");
|
|
} else if (OB_FAIL(schema_guard.get_table_schema(loc_meta_.ref_table_id_, table_schema))) {
|
|
LOG_WARN("get table schema failed", K(loc_meta_.ref_table_id_), K(ret));
|
|
} else if (OB_ISNULL(table_schema)) {
|
|
ret = OB_TABLE_NOT_EXIST;
|
|
LOG_WARN("table not exist", K(loc_meta_.ref_table_id_));
|
|
} else {
|
|
table_type_ = table_schema->get_table_type();
|
|
loc_meta_.is_external_table_ = table_schema->is_external_table();
|
|
loc_meta_.is_external_files_on_disk_ =
|
|
ObSQLUtils::is_external_files_on_local_disk(table_schema->get_external_file_location());
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (PARTITION_LEVEL_ZERO == (part_level_ = table_schema->get_part_level())) {
|
|
is_partitioned_ = false; //Non-partitioned table, do not need to calc partition id
|
|
} else if (PARTITION_LEVEL_ONE != part_level_ && PARTITION_LEVEL_TWO != part_level_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Partition level only support PARTITION_LEVEL_ONE or PARTITION_LEVEL_TWO", K(ret), K(part_level_));
|
|
} else if (FALSE_IT(is_oracle_temp_table_ = table_schema->is_oracle_tmp_table())) {
|
|
} else if (OB_UNLIKELY(PARTITION_FUNC_TYPE_MAX <=
|
|
(part_type_ = table_schema->get_part_option().get_part_func_type()))) {
|
|
ret = OB_SCHEMA_ERROR;
|
|
LOG_WARN("Part func type error", K(ret), K(loc_meta_.ref_table_id_), K(part_type_));
|
|
} else if (OB_UNLIKELY(PARTITION_FUNC_TYPE_MAX <=
|
|
(subpart_type_ = table_schema->get_sub_part_option().get_part_func_type()))) {
|
|
ret = OB_SCHEMA_ERROR;
|
|
LOG_WARN("Part func type error", K(ret), K(loc_meta_.ref_table_id_), K(subpart_type_));
|
|
} else if (OB_FAIL(loc_row_desc.init())) {
|
|
LOG_WARN("init loc row desc failed", K(ret));
|
|
} else if (OB_FAIL(loc_row_desc.assign(row_desc))) {
|
|
LOG_WARN("assign location row desc failed", K(ret));
|
|
} else {
|
|
if (stmt.is_insert_stmt()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("insert needn't call this function", K(ret));
|
|
} else if (OB_ISNULL(part_raw_expr = stmt.get_part_expr(table_id, loc_meta_.ref_table_id_))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("partition expr is null", K(table_id), K(loc_meta_.ref_table_id_));
|
|
} else if ((PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type_ ||
|
|
PARTITION_FUNC_TYPE_INTERVAL == part_type_) &&
|
|
OB_FAIL(can_get_part_by_range_for_range_columns(part_raw_expr, is_valid_range_columns_part_range_))) {
|
|
LOG_WARN("failed ot check can get part by range for range columns", K(ret));
|
|
} else if (OB_FAIL(can_get_part_by_range_for_temporal_column(part_raw_expr, is_valid_temporal_part_range_))) {
|
|
LOG_WARN("failed to check can get part by range for temporal column", K(ret));
|
|
} else if (FALSE_IT(is_col_part_expr_ = part_raw_expr->is_column_ref_expr())) {
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
ObTempExpr *se_temp_expr = NULL;
|
|
OZ(ObStaticEngineExprCG::gen_expr_with_row_desc(part_raw_expr, loc_row_desc,
|
|
exec_ctx.get_allocator(),
|
|
exec_ctx.get_my_session(),
|
|
schema_guard.get_schema_guard(),
|
|
se_temp_expr));
|
|
CK(OB_NOT_NULL(se_temp_expr));
|
|
OX(se_part_expr_ = se_temp_expr);
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type_
|
|
|| PARTITION_FUNC_TYPE_LIST_COLUMNS == part_type_
|
|
|| PARTITION_FUNC_TYPE_INTERVAL == part_type_) {
|
|
if (OB_FAIL(part_projector_.init_part_projector(&exec_ctx,
|
|
part_raw_expr, loc_row_desc))) {
|
|
LOG_WARN("init part projector failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
bool is_weak_read = false;
|
|
if (OB_FAIL(get_is_weak_read(stmt,
|
|
exec_ctx.get_my_session(),
|
|
exec_ctx.get_sql_ctx(),
|
|
is_weak_read))) {
|
|
LOG_WARN("get is weak read failed", K(ret));
|
|
} else if (ObDuplicateScope::DUPLICATE_SCOPE_NONE != table_schema->get_duplicate_scope()) {
|
|
loc_meta_.is_dup_table_ = 1;
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (is_dml_table) {
|
|
loc_meta_.select_leader_ = 1;
|
|
} else if (!is_weak_read) {
|
|
loc_meta_.select_leader_ = loc_meta_.is_dup_table_ ? 0 : 1;
|
|
} else {
|
|
loc_meta_.select_leader_ = 0;
|
|
loc_meta_.is_weak_read_ = 1;
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && PARTITION_LEVEL_TWO == table_schema->get_part_level()) {
|
|
const ObRawExpr *subpart_raw_expr = NULL;
|
|
if (OB_UNLIKELY(NULL == (subpart_raw_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_)))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sub partition expr not in stmt", K(ret), K(loc_meta_));
|
|
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_type_ &&
|
|
OB_FAIL(can_get_part_by_range_for_range_columns(subpart_raw_expr, is_valid_range_columns_subpart_range_))) {
|
|
LOG_WARN("failed to check can get part by range for range columns", K(ret));
|
|
} else if (OB_FAIL(can_get_part_by_range_for_temporal_column(subpart_raw_expr, is_valid_temporal_subpart_range_))) {
|
|
LOG_WARN("failed to check can get part by range for temporal column", K(ret));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
ObTempExpr *se_temp_expr = NULL;
|
|
OZ(ObStaticEngineExprCG::gen_expr_with_row_desc(subpart_raw_expr, loc_row_desc,
|
|
exec_ctx.get_allocator(),
|
|
exec_ctx.get_my_session(),
|
|
schema_guard.get_schema_guard(),
|
|
se_temp_expr));
|
|
CK(OB_NOT_NULL(se_temp_expr));
|
|
OX(se_subpart_expr_ = se_temp_expr);
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_type_
|
|
|| PARTITION_FUNC_TYPE_LIST_COLUMNS == subpart_type_) {
|
|
if (OB_FAIL(
|
|
part_projector_.init_subpart_projector(
|
|
&exec_ctx,
|
|
subpart_raw_expr,
|
|
loc_row_desc))) {
|
|
LOG_WARN("init subpart projector failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
part_projector_.set_column_cnt(loc_row_desc.get_column_num());
|
|
inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::init_table_location_with_rowkey(ObSqlSchemaGuard &schema_guard,
|
|
uint64_t table_id,
|
|
ObExecContext &exec_ctx,
|
|
const bool is_dml_table /*= true*/)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSchemaChecker schema_checker;
|
|
const ObTableSchema *table_schema = NULL;
|
|
ObSQLSessionInfo *session_info = NULL;
|
|
ObArray<uint64_t> column_ids;
|
|
ObSEArray<ObColDesc, 64> column_descs;
|
|
if (OB_FAIL(schema_checker.init(schema_guard))) {
|
|
LOG_WARN("fail to init schema_checker", K(ret));
|
|
} else if (OB_ISNULL(session_info = exec_ctx.get_my_session())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(ret));
|
|
} else if (OB_FAIL(schema_checker.get_table_schema(session_info->get_effective_tenant_id(),
|
|
table_id, table_schema))) {
|
|
LOG_WARN("get table schema failed", K(session_info->get_effective_tenant_id()), K(table_id), K(ret));
|
|
} else if (OB_ISNULL(table_schema)) {
|
|
ret = OB_TABLE_NOT_EXIST;
|
|
LOG_WARN("table not exist", K(table_id));
|
|
} else if (OB_FAIL(table_schema->get_column_ids(column_descs))) {
|
|
LOG_WARN("fail to get column ids", KR(ret));
|
|
} else if (OB_UNLIKELY(column_descs.empty())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected empty column desc", KR(ret));
|
|
}
|
|
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < column_descs.count(); ++i) {
|
|
const ObColumnSchemaV2 *column_schema =
|
|
table_schema->get_column_schema(column_descs.at(i).col_id_);
|
|
int64_t part_key_pos = column_schema->get_part_key_pos();
|
|
int64_t sub_part_key_pos = column_schema->get_subpart_key_pos();
|
|
if (part_key_pos > 0 || sub_part_key_pos > 0) {
|
|
if(OB_FAIL(column_ids.push_back(column_descs.at(i).col_id_))) {
|
|
LOG_WARN("fail to push back column id", KR(ret), K(column_descs.at(i).col_id_), K(column_ids));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(init_table_location_with_column_ids(schema_guard,
|
|
table_id,
|
|
column_ids,
|
|
exec_ctx,
|
|
is_dml_table))) {
|
|
LOG_WARN("init table location with column ids failed", K(ret), K(table_id), K(column_ids));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::init_table_location_with_column_ids(ObSqlSchemaGuard &schema_guard,
|
|
uint64_t table_id,
|
|
const ObIArray<uint64_t> &column_ids,
|
|
ObExecContext &exec_ctx,
|
|
const bool is_dml_table)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSchemaChecker schema_checker;
|
|
const ObTableSchema *table_schema = NULL;
|
|
ObSQLSessionInfo *session_info = NULL;
|
|
if (OB_FAIL(schema_checker.init(schema_guard))) {
|
|
LOG_WARN("fail to init schema_checker", K(ret));
|
|
} else if (OB_ISNULL(session_info = exec_ctx.get_my_session())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(ret));
|
|
} else if (OB_FAIL(schema_checker.get_table_schema(session_info->get_effective_tenant_id(),
|
|
table_id, table_schema))) {
|
|
LOG_WARN("get table schema failed", K(session_info->get_effective_tenant_id()), K(table_id), K(ret));
|
|
} else if (OB_ISNULL(table_schema)) {
|
|
ret = OB_TABLE_NOT_EXIST;
|
|
LOG_WARN("table not exist", K(table_id));
|
|
} else {
|
|
//找到真实的主表id,并且用主表id去解析partition expr
|
|
//由于局部索引本身没有分区信息,局部索引的分区信息跟主表相同,所以这里需要传主表的table_id
|
|
//而全局索引的分区信息跟主表是独立的,所以全局索引应该传递自己的table_id
|
|
uint64_t real_table_id = (table_schema->is_index_local_storage() || table_schema->is_aux_lob_table())
|
|
? table_schema->get_data_table_id() : table_id;
|
|
ObResolverParams resolver_ctx;
|
|
ObRawExprFactory expr_factory(allocator_);
|
|
ObStmtFactory stmt_factory(allocator_);
|
|
TableItem table_item;
|
|
resolver_ctx.allocator_ = &allocator_;
|
|
resolver_ctx.schema_checker_ = &schema_checker;
|
|
resolver_ctx.session_info_ = session_info;
|
|
resolver_ctx.disable_privilege_check_ = PRIV_CHECK_FLAG_DISABLE;
|
|
resolver_ctx.expr_factory_ = &expr_factory;
|
|
resolver_ctx.stmt_factory_ = &stmt_factory;
|
|
resolver_ctx.query_ctx_ = stmt_factory.get_query_ctx();
|
|
table_item.table_id_ = real_table_id;
|
|
table_item.ref_id_ = real_table_id;
|
|
table_item.type_ = TableItem::BASE_TABLE;
|
|
RowDesc row_desc;
|
|
//这里只是为了使用resolver解析partition expr的接口,任何一个语句的resolver都有这种能力
|
|
//用delete resolver的原因是delete resolver最简单
|
|
SMART_VAR (ObDeleteResolver, delete_resolver, resolver_ctx) {
|
|
ObDeleteStmt *delete_stmt = nullptr;
|
|
const ObTableSchema *real_table_schema = table_schema;
|
|
if (OB_ISNULL(resolver_ctx.query_ctx_) ||
|
|
OB_ISNULL(delete_stmt = delete_resolver.create_stmt<ObDeleteStmt>())) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("create query_ctx or delete stmt failed", K_(resolver_ctx.query_ctx), K(delete_stmt));
|
|
} else if (OB_FAIL(delete_stmt->get_table_items().push_back(&table_item))) {
|
|
LOG_WARN("store table item failed", K(ret));
|
|
} else if (OB_FAIL(delete_stmt->set_table_bit_index(real_table_id))) {
|
|
LOG_WARN("set table bit index failed", K(ret), K(real_table_id));
|
|
} else if (OB_UNLIKELY(table_schema->is_index_local_storage() || table_schema->is_aux_lob_table())
|
|
&& OB_FAIL(schema_guard.get_table_schema(real_table_id, real_table_schema))) {
|
|
LOG_WARN("get real table schema failed", K(ret), K(real_table_id));
|
|
//由于局部索引没有自己的partition信息,所以如果是计算索引表的partition信息,需要去主表获取分区规则表达式
|
|
} else if (OB_FAIL(delete_resolver.resolve_table_partition_expr(table_item, *real_table_schema))) {
|
|
LOG_WARN("resolve table partition expr failed", K(ret));
|
|
} else if (OB_FAIL(generate_rowkey_desc(*delete_stmt,
|
|
column_ids,
|
|
real_table_id,
|
|
expr_factory,
|
|
row_desc))) {
|
|
LOG_WARN("generate rowkey desc failed", K(ret), K(real_table_id));
|
|
} else if (OB_FAIL(init_table_location(exec_ctx,
|
|
schema_guard,
|
|
real_table_id,
|
|
real_table_id,
|
|
*delete_stmt,
|
|
row_desc,
|
|
is_dml_table,
|
|
default_asc_direction()))) {
|
|
LOG_WARN("init table location failed", K(ret), K(real_table_id));
|
|
} else if (OB_FAIL(clear_columnlized_in_row_desc(row_desc))) {
|
|
LOG_WARN("Failed to clear columnlized in row desc", K(ret));
|
|
} else {
|
|
loc_meta_.ref_table_id_ = table_id;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_not_partitioned_table_ids(ObExecContext &exec_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ObTabletID, 1> tablet_ids;
|
|
ObSEArray<ObObjectID, 1> partition_ids;
|
|
ObDASTabletMapper tablet_mapper;
|
|
if (OB_FAIL(exec_ctx.get_das_ctx().get_das_tablet_mapper(
|
|
loc_meta_.ref_table_id_, tablet_mapper, &loc_meta_.related_table_ids_))) {
|
|
LOG_WARN("fail to get das tablet mapper", K(ret));
|
|
} 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 if (!(1 == tablet_ids.count() && 1 == partition_ids.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get tablet ids or partition ids size more than 1", K(ret));
|
|
} else {
|
|
tablet_id_ = tablet_ids.at(0);
|
|
object_id_ = partition_ids.at(0);
|
|
DASRelatedTabletMap *related_map = static_cast<DASRelatedTabletMap *>(
|
|
tablet_mapper.get_related_table_info().related_map_);
|
|
if (OB_NOT_NULL(related_map)) {
|
|
related_list_.assign(related_map->get_list());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::init(
|
|
const ObTableSchema *table_schema,
|
|
const ObDMLStmt &stmt,
|
|
ObExecContext *exec_ctx,
|
|
const ObIArray<ObRawExpr*> &filter_exprs,
|
|
const uint64_t table_id,
|
|
const uint64_t ref_table_id,
|
|
const ObIArray<ObObjectID> *part_ids,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const bool is_dml_table, /*whether the ref_table is modified*/
|
|
common::ObIArray<ObRawExpr *> *sort_exprs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session_info = NULL;
|
|
loc_meta_.table_loc_id_ = table_id;
|
|
loc_meta_.ref_table_id_ = ref_table_id;
|
|
stmt_type_ = stmt.get_stmt_type();
|
|
is_partitioned_ = true;
|
|
if (OB_UNLIKELY(inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_ERROR("table location init twice", K(ret));
|
|
} else if (OB_INVALID_ID == table_id
|
|
|| OB_INVALID_ID == ref_table_id
|
|
|| OB_ISNULL(table_schema)
|
|
|| OB_ISNULL(exec_ctx)
|
|
|| OB_ISNULL(session_info = exec_ctx->get_my_session())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Input arguments error", K(table_id), K(ref_table_id), K(session_info), K(ret));
|
|
} else {
|
|
table_type_ = table_schema->get_table_type();
|
|
loc_meta_.is_external_table_ = table_schema->is_external_table();
|
|
loc_meta_.is_external_files_on_disk_ =
|
|
ObSQLUtils::is_external_files_on_local_disk(table_schema->get_external_file_location());
|
|
}
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (PARTITION_LEVEL_ZERO == (part_level_ = table_schema->get_part_level())) {
|
|
is_partitioned_ = false; //Non-partitioned table, do not need to calc partition id
|
|
} else if (PARTITION_LEVEL_ONE != part_level_ && PARTITION_LEVEL_TWO != part_level_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Partition level only support PARTITION_LEVEL_ONE or PARTITION_LEVEL_TWO", K(ret), K(part_level_));
|
|
} else if (FALSE_IT(is_oracle_temp_table_ = table_schema->is_oracle_tmp_table())) {
|
|
} else if (OB_UNLIKELY(PARTITION_FUNC_TYPE_MAX <=
|
|
(part_type_ = table_schema->get_part_option().get_part_func_type()))) {
|
|
ret = OB_SCHEMA_ERROR;
|
|
LOG_WARN("Part func type error", K(ret), K(ref_table_id), K(part_type_));
|
|
} else if (OB_UNLIKELY(PARTITION_FUNC_TYPE_MAX <=
|
|
(subpart_type_ = table_schema->get_sub_part_option().get_part_func_type()))) {
|
|
ret = OB_SCHEMA_ERROR;
|
|
LOG_WARN("Part func type error", K(ret), K(ref_table_id), K(subpart_type_));
|
|
} else if (stmt.is_insert_stmt() && !static_cast<const ObInsertStmt&>(stmt).value_from_select()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("insert needn't call this function", K(ret));
|
|
} else {
|
|
is_in_hit_ = false;
|
|
if (OB_FAIL(record_in_dml_partition_info(stmt, exec_ctx, filter_exprs, is_in_hit_, table_schema))) { //这是一个特殊路径,针对in filter条件
|
|
LOG_WARN("fail to record_in_dml_partition_info", K(ret));
|
|
} else if (!is_in_hit_) {
|
|
bool is_in_range_optimization_enabled = false;
|
|
if (OB_FAIL(ObOptimizerUtil::is_in_range_optimization_enabled(stmt.get_query_ctx()->get_global_hint(),
|
|
session_info,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("failed to check in range optimization enabled", K(ret));
|
|
} else if (OB_FAIL(record_not_insert_dml_partition_info(stmt, exec_ctx, table_schema, filter_exprs, dtc_params,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("Fail to record select or update partition info", K(stmt_type_), K(ret));
|
|
} else if (OB_FAIL(get_not_insert_dml_part_sort_expr(stmt, sort_exprs))) {
|
|
LOG_WARN("Failed to get not insert dml sort key with parts", K(ret));
|
|
} else { }
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && NULL != part_ids && !part_ids->empty()) {
|
|
ret = part_hint_ids_.assign(*part_ids);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_ISNULL(table_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL ptr", K(table_id), K(ref_table_id), K(ret));
|
|
} else {
|
|
inited_ = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
bool is_weak_read = false;
|
|
if (OB_FAIL(get_is_weak_read(stmt, session_info, exec_ctx->get_sql_ctx(), is_weak_read))) {
|
|
LOG_WARN("get is weak read failed", K(ret));
|
|
} else if (ObDuplicateScope::DUPLICATE_SCOPE_NONE != table_schema->get_duplicate_scope()) {
|
|
loc_meta_.is_dup_table_ = 1;
|
|
}
|
|
if (is_dml_table) {
|
|
loc_meta_.select_leader_ = 1;
|
|
} else if (!is_weak_read) {
|
|
loc_meta_.select_leader_ = loc_meta_.is_dup_table_ ? 0 : 1;
|
|
} else {
|
|
loc_meta_.select_leader_ = 0;
|
|
loc_meta_.is_weak_read_ = 1;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_is_weak_read(const ObDMLStmt &dml_stmt,
|
|
const ObSQLSessionInfo *session,
|
|
const ObSqlCtx *sql_ctx,
|
|
bool &is_weak_read)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_weak_read = false;
|
|
if (OB_ISNULL(session) || OB_ISNULL(sql_ctx) || OB_ISNULL(dml_stmt.get_query_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("unexpected null", K(ret), K(session), K(sql_ctx));
|
|
} else if (dml_stmt.get_query_ctx()->has_dml_write_stmt_ ||
|
|
dml_stmt.get_query_ctx()->is_contain_select_for_update_ ||
|
|
dml_stmt.get_query_ctx()->is_contain_inner_table_) {
|
|
is_weak_read = false;
|
|
} else if (share::ObTenantEnv::get_tenant() == nullptr) { //table api can't invoke MTL_TENANT_ROLE_CACHE_IS_PRIMARY_OR_INVALID
|
|
is_weak_read = false;
|
|
} else if (!MTL_TENANT_ROLE_CACHE_IS_PRIMARY_OR_INVALID()) {
|
|
is_weak_read = true;
|
|
} else {
|
|
ObConsistencyLevel consistency_level = INVALID_CONSISTENCY;
|
|
ObTxConsistencyType trans_consistency_type = ObTxConsistencyType::INVALID;
|
|
if (stmt::T_SELECT == dml_stmt.get_stmt_type()) {
|
|
if (sql_ctx->is_protocol_weak_read_) {
|
|
consistency_level = WEAK;
|
|
} else if (OB_UNLIKELY(INVALID_CONSISTENCY
|
|
!= dml_stmt.get_query_ctx()->get_global_hint().read_consistency_)) {
|
|
consistency_level = dml_stmt.get_query_ctx()->get_global_hint().read_consistency_;
|
|
} else {
|
|
consistency_level = session->get_consistency_level();
|
|
}
|
|
} else {
|
|
consistency_level = STRONG;
|
|
}
|
|
if (OB_FAIL(ObSqlTransControl::decide_trans_read_interface_specs(
|
|
consistency_level,
|
|
trans_consistency_type))) {
|
|
LOG_WARN("fail to decide trans read interface specs", K(ret),
|
|
K(dml_stmt.get_stmt_type()),
|
|
// K(dml_stmt.get_literal_stmt_type()),
|
|
K(dml_stmt.get_query_ctx()->is_contain_select_for_update_),
|
|
K(dml_stmt.get_query_ctx()->is_contain_inner_table_),
|
|
K(consistency_level),
|
|
KPC(session));
|
|
} else {
|
|
// 判断是否优先读备副本
|
|
is_weak_read = (ObTxConsistencyType::BOUNDED_STALENESS_READ == trans_consistency_type);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calculate_candi_tablet_locations(
|
|
ObExecContext &exec_ctx,
|
|
const ParamStore ¶ms,
|
|
ObCandiTabletLocIArray &candi_tablet_locs,
|
|
const ObDataTypeCastParams &dtc_params) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ObObjectID, 8> partition_ids;
|
|
ObSEArray<ObObjectID, 8> first_level_part_ids;
|
|
ObSEArray<ObTabletID, 8> tablet_ids;
|
|
if (!inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObTableLocation not inited", K(ret));
|
|
} else if (OB_FAIL(calculate_tablet_ids(exec_ctx,
|
|
params,
|
|
tablet_ids,
|
|
partition_ids,
|
|
first_level_part_ids,
|
|
dtc_params))) {
|
|
LOG_WARN("Failed to calculate partition ids", K(ret));
|
|
} else if (OB_FAIL(get_tablet_locations(exec_ctx.get_das_ctx(),
|
|
tablet_ids,
|
|
partition_ids,
|
|
first_level_part_ids,
|
|
candi_tablet_locs))) {
|
|
LOG_WARN("Failed to set partition locations", K(ret), K(partition_ids), K(tablet_ids));
|
|
} else {}//do nothing
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::init_partition_ids_by_rowkey2(ObExecContext &exec_ctx,
|
|
ObSQLSessionInfo &session_info,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
uint64_t table_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSqlSchemaGuard sql_schema_guard;
|
|
sql_schema_guard.set_schema_guard(&schema_guard);
|
|
exec_ctx.set_my_session(&session_info);
|
|
if (OB_UNLIKELY(is_virtual_table(table_id))) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Calculate virtual table partition id with rowkey");
|
|
} else if (OB_FAIL(init_table_location_with_rowkey(sql_schema_guard, table_id, exec_ctx))) {
|
|
LOG_WARN("implicit init location failed", K(table_id), K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//FIXME
|
|
int ObTableLocation::calculate_partition_ids_by_rows2(ObSQLSessionInfo &session_info,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
uint64_t table_id,
|
|
ObIArray<ObNewRow> &part_rows,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArenaAllocator allocator(ObModIds::OB_SQL_TABLE_LOCATION);
|
|
SMART_VAR(ObExecContext, exec_ctx, allocator) {
|
|
ObSqlSchemaGuard sql_schema_guard;
|
|
ObSqlCtx sql_ctx;
|
|
sql_ctx.schema_guard_ = &schema_guard;
|
|
sql_schema_guard.set_schema_guard(&schema_guard);
|
|
exec_ctx.set_sql_ctx(&sql_ctx);
|
|
exec_ctx.set_my_session(&session_info);
|
|
ObDASTabletMapper tablet_mapper;
|
|
if (OB_UNLIKELY(is_virtual_table(table_id))) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Calculate virtual table partition id with rowkey");
|
|
} else if (!is_partitioned_) {
|
|
ObObjectID object_id = 0;
|
|
ObTabletID tablet_id;
|
|
const ObTableSchema *table_schema = nullptr;
|
|
if (OB_FAIL(sql_schema_guard.get_table_schema(table_id, table_schema))) {
|
|
LOG_WARN("fail to get table schema", K(table_id), KR(ret));
|
|
} else if (OB_FAIL(table_schema->get_tablet_and_object_id(tablet_id, object_id))) {
|
|
LOG_WARN("fail to get tablet and object", KR(ret));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_rows.count(); i ++) {
|
|
if (OB_FAIL(tablet_ids.push_back(tablet_id))) {
|
|
LOG_WARN("fail to push tablet id", KR(ret));
|
|
} else if (OB_FAIL(part_ids.push_back(object_id))) {
|
|
LOG_WARN("fail to push object id", KR(ret));
|
|
}
|
|
}
|
|
}
|
|
} else if (OB_FAIL(exec_ctx.get_das_ctx().get_das_tablet_mapper(table_id,
|
|
tablet_mapper,
|
|
&loc_meta_.related_table_ids_))) {
|
|
LOG_WARN("get das tablet mapper failed", KR(ret), K(table_id));
|
|
} else {//TODO: copied from calc_partition_ids_by_rowkey()
|
|
ObSEArray<ObObjectID, 1> tmp_part_ids;
|
|
ObSEArray<ObTabletID, 1> tmp_tablet_ids;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_rows.count(); ++i) {
|
|
tmp_part_ids.reset();
|
|
tmp_tablet_ids.reset(); //must reset
|
|
ObNewRow &part_row = part_rows.at(i);
|
|
if (PARTITION_LEVEL_ONE == part_level_) {
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx, tablet_mapper, part_row, tmp_tablet_ids, tmp_part_ids))) {
|
|
LOG_WARN("calc partition id by row failed", K(ret));
|
|
}
|
|
} else {
|
|
ObSEArray<ObObjectID, 1> tmp_part_ids2;
|
|
ObSEArray<ObTabletID, 1> tmp_tablet_ids2;
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
part_row,
|
|
tmp_tablet_ids2,
|
|
tmp_part_ids2))) {
|
|
LOG_WARN("calc partition id by row failed", K(ret));
|
|
} else if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
part_row,
|
|
tmp_tablet_ids,
|
|
tmp_part_ids,
|
|
&tmp_part_ids2))) {
|
|
LOG_WARN("calc sub partition id by row failed", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
ObObjectID part_id;
|
|
ObTabletID tablet_id;
|
|
if (OB_UNLIKELY(tmp_tablet_ids.empty() && tmp_part_ids.empty())) {
|
|
part_id = OB_INVALID_PARTITION_ID;
|
|
tablet_id = ObTabletID::INVALID_TABLET_ID;
|
|
} else if (OB_UNLIKELY((tmp_tablet_ids.count() != 1) || (tmp_part_ids.count() != 1))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid tablet ids or partition ids", KR(ret), K(tmp_tablet_ids), K(tmp_part_ids));
|
|
} else {
|
|
part_id = tmp_part_ids.at(0);
|
|
tablet_id = tmp_tablet_ids.at(0);
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(tablet_ids.push_back(tablet_id))) {
|
|
LOG_WARN("fail to push tablet id", KR(ret));
|
|
} else if (OB_FAIL(part_ids.push_back(part_id))) {
|
|
LOG_WARN("fail to push object id", KR(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calculate_partition_ids_by_rowkey(ObSQLSessionInfo &session_info,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
uint64_t table_id,
|
|
const ObIArray<ObRowkey> &rowkeys,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObArenaAllocator allocator(ObModIds::OB_SQL_TABLE_LOCATION);
|
|
SMART_VAR(ObExecContext, exec_ctx, allocator) {
|
|
ObSqlSchemaGuard sql_schema_guard;
|
|
ObSqlCtx sql_ctx;
|
|
sql_ctx.schema_guard_ = &schema_guard;
|
|
sql_schema_guard.set_schema_guard(&schema_guard);
|
|
exec_ctx.set_my_session(&session_info);
|
|
exec_ctx.set_sql_ctx(&sql_ctx);
|
|
ObDASTabletMapper tablet_mapper;
|
|
if (is_non_partition_optimized_ && table_id == loc_meta_.ref_table_id_) {
|
|
tablet_mapper.set_non_partitioned_table_ids(tablet_id_, object_id_, &related_list_);
|
|
}
|
|
if (OB_FAIL(exec_ctx.get_das_ctx().get_das_tablet_mapper(
|
|
table_id, tablet_mapper, &loc_meta_.related_table_ids_))) {
|
|
LOG_WARN("fail to get das tablet mapper", K(ret));
|
|
} else if (OB_UNLIKELY(is_virtual_table(table_id))) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Calculate virtual table partition id with rowkey");
|
|
} else if (OB_UNLIKELY(rowkeys.count() <= 0)) {
|
|
if (PARTITION_LEVEL_ONE == part_level_) {
|
|
if (OB_FAIL(get_all_part_ids(tablet_mapper, tablet_ids, partition_ids))) {
|
|
LOG_WARN("Failed to get all part ids", K(ret));
|
|
}
|
|
} else if (PARTITION_LEVEL_TWO == part_level_) {
|
|
ObSEArray<ObObjectID, 5> tmp_part_ids;
|
|
ObSEArray<ObTabletID, 5> tmp_tablet_ids;
|
|
if (OB_FAIL(get_all_part_ids(tablet_mapper, tmp_tablet_ids, tmp_part_ids))) {
|
|
LOG_WARN("Failed to get all part ids", K(ret));
|
|
} else if (OB_FAIL(get_all_part_ids(tablet_mapper,
|
|
tablet_ids,
|
|
partition_ids,
|
|
&tmp_part_ids))) {
|
|
LOG_WARN("Failed to get all subpart ids", K(ret));
|
|
} else { }
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Unkown part level", K(ret), K(part_level_), K(is_partitioned_));
|
|
}
|
|
} else if (OB_FAIL(init_table_location_with_rowkey(sql_schema_guard, table_id, exec_ctx))) {
|
|
LOG_WARN("implicit init location failed", K(table_id), K(ret));
|
|
} else if (OB_FAIL(calc_partition_ids_by_rowkey(exec_ctx,
|
|
tablet_mapper,
|
|
rowkeys,
|
|
tablet_ids,
|
|
partition_ids))) {
|
|
LOG_WARN("calc parttion ids by rowkey failed", K(ret));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calculate_tablet_id_by_row(ObExecContext &exec_ctx,
|
|
uint64_t table_id,
|
|
const ObIArray<uint64_t> &column_ids,
|
|
ObNewRow &cur_row,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObDASTabletMapper tablet_mapper;
|
|
if (is_non_partition_optimized_ && table_id == loc_meta_.ref_table_id_) {
|
|
tablet_mapper.set_non_partitioned_table_ids(tablet_id_, object_id_, &related_list_);
|
|
}
|
|
if (OB_FAIL(exec_ctx.get_das_ctx().get_das_tablet_mapper(table_id, tablet_mapper,
|
|
&loc_meta_.related_table_ids_))) {
|
|
LOG_WARN("fail to get das tablet mapper", K(ret));
|
|
} else if (!is_partitioned_) {
|
|
if (OB_FAIL(tablet_mapper.get_non_partition_tablet_id(tablet_ids, partition_ids))) {
|
|
LOG_WARN("get non partition tablet id failed", K(ret), K(table_id));
|
|
}
|
|
} else if (PARTITION_LEVEL_ONE == part_level_) {
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
cur_row,
|
|
tablet_ids,
|
|
partition_ids))) {
|
|
LOG_WARN("calc partition id by row failed", K(ret));
|
|
}
|
|
} else {
|
|
ObSEArray<ObTabletID, 1> tmp_tablet_ids;
|
|
ObSEArray<ObObjectID, 1> tmp_partition_ids;
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
cur_row,
|
|
tmp_tablet_ids,
|
|
tmp_partition_ids))) {
|
|
LOG_WARN("calc the first level partition id by row failed", K(ret), K(cur_row));
|
|
} else if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
cur_row,
|
|
tablet_ids,
|
|
partition_ids,
|
|
&tmp_partition_ids))) {
|
|
LOG_WARN("calc the secondary level partition id by row failed", K(ret), K(cur_row));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calculate_tablet_ids(ObExecContext &exec_ctx,
|
|
const ParamStore ¶ms,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
ObIArray<ObObjectID> &first_level_part_ids,
|
|
const ObDataTypeCastParams &dtc_params) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObDASTabletMapper tablet_mapper;
|
|
ObPartitionIdMap partition_id_map;
|
|
if (!inited_) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObTableLocation not inited", K(ret));
|
|
} else if (is_non_partition_optimized_
|
|
&& FALSE_IT(tablet_mapper.set_non_partitioned_table_ids(
|
|
tablet_id_, object_id_, &related_list_))) {
|
|
} else if (OB_FAIL(exec_ctx.get_das_ctx().get_das_tablet_mapper(
|
|
loc_meta_.ref_table_id_, tablet_mapper, &loc_meta_.related_table_ids_))) {
|
|
LOG_WARN("fail to get das tablet mapper", K(ret));
|
|
} else {
|
|
if (is_in_hit_) { //判断是否是in类型
|
|
if (OB_FAIL(calc_partition_ids_by_in_expr(exec_ctx, tablet_mapper, tablet_ids, partition_ids, dtc_params))) {
|
|
LOG_WARN("fail to calc_partition_ids_by_in_expr", K(ret));
|
|
}
|
|
} else {
|
|
if (!is_partitioned_) {
|
|
OZ(tablet_mapper.get_non_partition_tablet_id(tablet_ids, partition_ids));
|
|
} else if (PARTITION_LEVEL_ONE == part_level_) {
|
|
if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params,
|
|
calc_node_, gen_col_node_,
|
|
se_gen_col_expr_,
|
|
part_get_all_, tablet_ids,
|
|
partition_ids, dtc_params))) {
|
|
LOG_WARN("Calc partition ids by calc node error", K_(stmt_type), K(ret));
|
|
}
|
|
} else {
|
|
ObSEArray<ObTabletID, 1> tmp_tablet_ids;
|
|
ObSEArray<ObObjectID, 1> tmp_part_ids;
|
|
if (OB_FAIL(partition_id_map.create(128, "PartitionIdMap", "PartitionIdMap"))) {
|
|
LOG_WARN("failed to create partition id map");
|
|
} else if (OB_FALSE_IT(tablet_mapper.set_partition_id_map(&partition_id_map))) {
|
|
} else if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params,
|
|
calc_node_, gen_col_node_,
|
|
se_gen_col_expr_,
|
|
part_get_all_, tmp_tablet_ids,
|
|
tmp_part_ids, dtc_params))) {
|
|
LOG_WARN("Calc partition ids by calc node error", K_(stmt_type), K(ret));
|
|
} else if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params,
|
|
subcalc_node_, sub_gen_col_node_,
|
|
se_sub_gen_col_expr_, subpart_get_all_,
|
|
tablet_ids, partition_ids,
|
|
dtc_params, &tmp_part_ids))) {
|
|
LOG_WARN("Calc partition ids by calc node error", K_(stmt_type), K(ret));
|
|
} else { }
|
|
}
|
|
}
|
|
|
|
if ( OB_SUCC(ret)
|
|
&& 0 == partition_ids.count()
|
|
&& (stmt::T_INSERT == stmt_type_
|
|
|| stmt::T_REPLACE == stmt_type_
|
|
|| check_no_partiton_)) {
|
|
ret = OB_NO_PARTITION_FOR_GIVEN_VALUE;
|
|
LOG_USER_WARN(OB_NO_PARTITION_FOR_GIVEN_VALUE);
|
|
}
|
|
//deal partition hint
|
|
if (OB_SUCCESS == ret && part_hint_ids_.count() > 0) {
|
|
if (OB_FAIL(deal_partition_selection(tablet_ids, partition_ids))) {
|
|
LOG_WARN("deal partition select failed", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && partition_ids.empty()) {
|
|
ObObjectID default_partition_id = OB_INVALID_ID;
|
|
ObTabletID default_tablet_id;
|
|
if (OB_FAIL(tablet_mapper.get_default_tablet_and_object_id(part_level_,
|
|
part_hint_ids_,
|
|
default_tablet_id,
|
|
default_partition_id))) {
|
|
LOG_WARN("get default tablet and object id failed", K(ret), K(part_hint_ids_));
|
|
} else if (OB_FAIL(partition_ids.push_back(default_partition_id))) {
|
|
LOG_WARN("store default partition id failed", K(ret));
|
|
} else if (OB_FAIL(tablet_ids.push_back(default_tablet_id))) {
|
|
LOG_WARN("store default tablet id failed", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && PARTITION_LEVEL_TWO == part_level_) {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < partition_ids.count(); ++i) {
|
|
ObObjectID first_level_part_id;
|
|
if (OB_FAIL(tablet_mapper.get_partition_id_map(partition_ids.at(i), first_level_part_id))) {
|
|
LOG_WARN("failed to get partition id map", K(i), K(partition_ids.at(i)));
|
|
} else if (OB_FAIL(first_level_part_ids.push_back(first_level_part_id))) {
|
|
LOG_WARN("faield to push back log part id");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG_TRACE("calculate tablet ids end", K(loc_meta_), K(partition_ids), K(tablet_ids));
|
|
NG_TRACE(tl_calc_part_id_end);
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_tablet_locations(ObDASCtx &das_ctx,
|
|
const ObIArray<ObTabletID> &tablet_ids,
|
|
const ObIArray<ObObjectID> &partition_ids,
|
|
const ObIArray<ObObjectID> &first_level_part_ids,
|
|
ObCandiTabletLocIArray &candi_tablet_locs) const
|
|
{
|
|
return das_ctx.get_location_router().nonblock_get_candi_tablet_locations(loc_meta_,
|
|
tablet_ids,
|
|
partition_ids,
|
|
first_level_part_ids,
|
|
candi_tablet_locs);
|
|
}
|
|
|
|
int ObTableLocation::get_part_col_type(const ObRawExpr *expr,
|
|
ObObjType &col_type,
|
|
ObCollationType &collation_type,
|
|
const ObTableSchema *table_schema,
|
|
bool &is_valid)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_valid = true;
|
|
if (OB_ISNULL(expr) || OB_UNLIKELY(!expr->is_column_ref_expr())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("get invalid expr", K(ret), KPC(expr));
|
|
} else {
|
|
const ObColumnRefRawExpr *col = static_cast<const ObColumnRefRawExpr *>(expr);
|
|
const ObColumnSchemaV2 *col_schema = table_schema->get_column_schema(col->get_column_id());
|
|
if (NULL == col_schema) {
|
|
/**
|
|
* there are two sence if part column can't find in index schema
|
|
* 1. part column is generated column
|
|
* 2. local index of heap table doesn't store part key
|
|
*/
|
|
is_valid = false;
|
|
} else {
|
|
col_type = col_schema->get_data_type();
|
|
collation_type = col_schema->get_meta_type().get_collation_type();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableLocation::convert_row_obj_type(const ObNewRow &from,
|
|
ObNewRow &to,
|
|
ObObjType col_type,
|
|
ObCollationType collation_type,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
bool &is_all,
|
|
bool &is_none) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObObj &tmp = from.get_cell(0);
|
|
ObObj &out_obj = to.get_cell(0);
|
|
ObObj tmp_out_obj;
|
|
ObObj tmp_out_obj2;
|
|
ObObjType res_type = ObNullType;
|
|
is_none = false;
|
|
if (ob_obj_type_class(tmp.get_type()) == ob_obj_type_class(col_type) &&
|
|
tmp.get_collation_type() == collation_type) {
|
|
is_all = false;
|
|
out_obj = tmp;
|
|
} else {
|
|
if (OB_FAIL(ObExprResultTypeUtil::get_relational_cmp_type(res_type, col_type, tmp.get_type()))) {
|
|
LOG_WARN("fail to get_relational_cmp_type", K(ret));
|
|
} else {
|
|
bool is_cast_monotonic = false;
|
|
if (OB_FAIL(ObObjCaster::is_cast_monotonic(col_type, res_type, is_cast_monotonic))) {
|
|
LOG_WARN("check is cast monotonic failed", K(ret));
|
|
} else if (is_cast_monotonic) {
|
|
if (OB_FAIL(ObObjCaster::is_cast_monotonic(res_type, col_type, is_cast_monotonic))) {
|
|
LOG_WARN("check is cast monotonic failed", K(ret));
|
|
}
|
|
}
|
|
|
|
int64_t result = 0;
|
|
if (OB_SUCC(ret)) {
|
|
if (is_cast_monotonic) {
|
|
is_all = false;
|
|
ObCastCtx cast_ctx(&allocator_, &dtc_params, CM_NONE, collation_type);
|
|
if (OB_FAIL(ObObjCaster::to_type(res_type, cast_ctx, tmp, tmp_out_obj))) {
|
|
LOG_WARN("fail to cast", K(ret), K(res_type));
|
|
} else if (OB_FAIL(ObObjCaster::to_type(col_type, cast_ctx, tmp_out_obj, tmp_out_obj2))) {
|
|
LOG_WARN("fail to cast", K(ret), K(col_type));
|
|
} else if (OB_FAIL(ObRelationalExprOperator::compare_nullsafe(result, tmp_out_obj, tmp_out_obj2, cast_ctx, res_type, collation_type))) {
|
|
LOG_WARN("fail to cmp", K(ret));
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (result == 0) {
|
|
out_obj = tmp_out_obj2;
|
|
} else {
|
|
is_none = true;
|
|
}
|
|
} else {
|
|
ret = OB_SUCCESS;
|
|
is_all = true;
|
|
}
|
|
} else {
|
|
is_all = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
////考虑in的类型转换,暂时不考虑不行。判断in的value是否能转换成column列要求的类型,如果不能。直接返回所有的partition。
|
|
int ObTableLocation::calc_partition_ids_by_in_expr(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObDataTypeCastParams &dtc_params) const
|
|
{
|
|
UNUSED(dtc_params);
|
|
int ret = OB_SUCCESS;
|
|
if (vies_.count() != sub_vies_.count()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid key/subkey count", K(vies_.count()), K(sub_vies_.count()));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!is_partitioned_) {
|
|
OZ(tablet_mapper.get_non_partition_tablet_id(tablet_ids, partition_ids));
|
|
} else {
|
|
ObArenaAllocator allocator(CURRENT_CONTEXT->get_malloc_allocator());
|
|
allocator.set_label("CalcByInExpr");
|
|
ObExprCtx expr_ctx;
|
|
ObNewRow part_row;
|
|
ObNewRow subpart_row;
|
|
|
|
//init expr ctx
|
|
if (OB_FAIL(ObSQLUtils::wrap_expr_ctx(stmt_type_, exec_ctx, allocator, expr_ctx))) {
|
|
LOG_WARN("Failed to wrap expr ctx", K(ret));
|
|
}
|
|
|
|
//init all ObNewRow
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(init_row(allocator, 1, part_row))) {
|
|
LOG_WARN("Failed to init row", K(ret));
|
|
} { }//do nothing
|
|
|
|
if (PARTITION_LEVEL_TWO == part_level_) {
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(init_row(allocator, 1, subpart_row))) {
|
|
LOG_WARN("Failed to init row", K(ret));
|
|
} else { }//do nothing
|
|
}
|
|
|
|
//calc ObNewRow for calc partition id
|
|
int64_t key_expr_cnt = vies_.count();
|
|
for (int64_t value_idx = 0; OB_SUCC(ret) && value_idx < key_expr_cnt; ++value_idx) {
|
|
OZ(se_calc_value_item_row(expr_ctx, exec_ctx, vies_, 1, value_idx, part_row, part_row));
|
|
OZ(se_calc_value_item_row(expr_ctx, exec_ctx, sub_vies_, 1, value_idx, subpart_row, subpart_row));
|
|
|
|
ObSEArray<ObObjectID, 5> part_ids;
|
|
ObSEArray<ObTabletID, 5> tmp_tablet_ids;
|
|
bool is_all = false;
|
|
bool is_none = false;
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(convert_row_obj_type(part_row, part_row, part_col_type_, part_collation_type_,
|
|
dtc_params, is_all, is_none))) {
|
|
LOG_WARN("fail to convert_row_obj_type", K(ret));
|
|
} else if (!is_none) {
|
|
if (is_all) {
|
|
if (OB_FAIL(get_all_part_ids(tablet_mapper, tmp_tablet_ids, part_ids))) {
|
|
LOG_WARN("Failed to get all part ids", K(ret));
|
|
}
|
|
} else {
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx, tablet_mapper, part_row, tmp_tablet_ids, part_ids))) {
|
|
LOG_WARN("Calc partition id by row error", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(convert_row_obj_type(subpart_row, subpart_row, subpart_col_type_,
|
|
subpart_collation_type_, dtc_params, is_all, is_none))) {
|
|
LOG_WARN("fail to convert_row_obj_type", K(ret));
|
|
} else if (!is_none) {
|
|
if (is_all) {
|
|
if (OB_FAIL(get_all_part_ids(tablet_mapper, tablet_ids, partition_ids, &part_ids))) {
|
|
LOG_WARN("Failed to get all subpart ids", K(ret));
|
|
}
|
|
} else if (OB_FAIL(calc_partition_id_by_row(exec_ctx, tablet_mapper, subpart_row,
|
|
tablet_ids, partition_ids, &part_ids))) {
|
|
LOG_WARN("Calc partitioin id by row error", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::set_location_calc_node(const ObDMLStmt &stmt,
|
|
const ObIArray<ObRawExpr*> &filter_exprs,
|
|
const ObPartitionLevel part_level,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
ObExecContext *exec_ctx,
|
|
ObTempExpr *&se_part_expr,
|
|
ObTempExpr *&se_gen_col_expr,
|
|
bool &is_col_part_expr,
|
|
ObPartLocCalcNode *&calc_node,
|
|
ObPartLocCalcNode *&gen_col_node,
|
|
bool &get_all,
|
|
bool &is_range_get,
|
|
const bool is_in_range_optimization_enabled)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ColumnItem, 5> part_columns;
|
|
ObSEArray<ColumnItem, 3> gen_cols;
|
|
const ObRawExpr *part_raw_expr = NULL;
|
|
if (OB_ISNULL(exec_ctx)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(exec_ctx), K(ret));
|
|
} else if (OB_FAIL(get_partition_column_info(stmt,
|
|
part_level,
|
|
part_columns,
|
|
gen_cols,
|
|
part_raw_expr,
|
|
is_col_part_expr,
|
|
se_part_expr,
|
|
se_gen_col_expr,
|
|
exec_ctx))) {
|
|
LOG_WARN("Failed to get partition column info", K(ret));
|
|
} else if (filter_exprs.empty()) {
|
|
get_all = true;
|
|
} else if (OB_FAIL(get_location_calc_node(part_level,
|
|
part_columns,
|
|
part_raw_expr,
|
|
filter_exprs,
|
|
calc_node,
|
|
get_all,
|
|
is_range_get,
|
|
dtc_params,
|
|
exec_ctx,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("Failed to get location calc node", K(ret));
|
|
} else if (gen_cols.count() > 0) {
|
|
//analyze information with dependented column of generated column
|
|
bool always_true =false;
|
|
if (OB_FAIL(get_query_range_node(part_level,
|
|
gen_cols,
|
|
filter_exprs,
|
|
always_true,
|
|
gen_col_node,
|
|
dtc_params,
|
|
exec_ctx,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("Get query range node error", K(ret));
|
|
} else if (always_true) {
|
|
gen_col_node = NULL;
|
|
} else { }//do nothing
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
T_OP_IN
|
|
-- T_OP_ROW
|
|
--T_REF_COLUMN
|
|
--T_REF_COLUMN
|
|
-- T_OP_ROW
|
|
--T_OP_ROW
|
|
--T_QUESTIONMARK
|
|
--T_QUESTIONMARK
|
|
--T_OP_ROW
|
|
--T_QUESTIONMARK
|
|
--T_QUESTIONMARK
|
|
*/ //in 表达式的结构,下面代码主要按照这个结构在分析
|
|
|
|
int ObTableLocation::record_in_dml_partition_info(const ObDMLStmt &stmt,
|
|
ObExecContext *exec_ctx,
|
|
const ObIArray<ObRawExpr*> &filter_exprs,
|
|
bool &hit,
|
|
const ObTableSchema *table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObRawExpr *filter_expr = NULL;
|
|
ObRawExpr *left_expr = NULL;
|
|
ObRawExpr *right_expr = NULL;
|
|
|
|
hit = true;
|
|
if (PARTITION_LEVEL_TWO != part_level_) {
|
|
hit = false;
|
|
}
|
|
if (hit) {
|
|
if (filter_exprs.count() != 1) {
|
|
hit = false;
|
|
} else {
|
|
filter_expr = filter_exprs.at(0);
|
|
}
|
|
}
|
|
|
|
const ObRawExpr *part_raw_expr = NULL;
|
|
const ObRawExpr *subpart_raw_expr = NULL;
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
part_raw_expr = stmt.get_part_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
|
bool is_valid = true;
|
|
if (OB_ISNULL(part_raw_expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get null part raw expr", K(ret));
|
|
} else if (T_REF_COLUMN != part_raw_expr->get_expr_type()) {
|
|
hit = false;
|
|
} else if (OB_FAIL(get_part_col_type(part_raw_expr,
|
|
part_col_type_,
|
|
part_collation_type_,
|
|
table_schema,
|
|
is_valid))) {
|
|
LOG_WARN("fail to get part col type", K(ret));
|
|
} else if (!is_valid) {
|
|
hit = false;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
subpart_raw_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
|
bool is_valid = true;
|
|
if (OB_ISNULL(subpart_raw_expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get null subpart raw expr", K(ret));
|
|
} else if (T_REF_COLUMN != subpart_raw_expr->get_expr_type()) {
|
|
hit = false;
|
|
} else if (OB_FAIL(get_part_col_type(subpart_raw_expr,
|
|
subpart_col_type_,
|
|
subpart_collation_type_,
|
|
table_schema,
|
|
is_valid))) {
|
|
LOG_WARN("fail to get part col type", K(ret));
|
|
} else if (!is_valid) {
|
|
hit = false;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
if (T_OP_IN != filter_expr->get_expr_type()) {
|
|
hit = false;
|
|
} else {
|
|
ObOpRawExpr *op_raw_expr = static_cast<ObOpRawExpr *>(filter_expr);
|
|
if (2 != op_raw_expr->get_param_count()) {
|
|
hit = false;
|
|
} else {
|
|
left_expr = op_raw_expr->get_param_expr(0);
|
|
right_expr = op_raw_expr->get_param_expr(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
if (T_OP_ROW != left_expr->get_expr_type()) {
|
|
hit = false;
|
|
}
|
|
}
|
|
|
|
int64_t pos1 = -1;
|
|
int64_t pos2 = -1;
|
|
if (OB_SUCC(ret) && hit) {
|
|
ObOpRawExpr *op_left_expr = static_cast<ObOpRawExpr *>(left_expr);
|
|
if (2 > op_left_expr->get_param_count()) {
|
|
hit = false;
|
|
} else {
|
|
for (int64_t i = 0; i < op_left_expr->get_param_count(); i ++) {
|
|
ObRawExpr *tmp = op_left_expr->get_param_expr(i);
|
|
if (tmp->same_as(*part_raw_expr)) {
|
|
pos1 = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int64_t i = 0; i < op_left_expr->get_param_count(); i ++) {
|
|
ObRawExpr *tmp = op_left_expr->get_param_expr(i);
|
|
if (tmp->same_as(*subpart_raw_expr)) {
|
|
pos2 = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pos1 != -1 && pos2 != -1 && pos1 != pos2) {
|
|
hit = true;
|
|
} else {
|
|
hit = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
if (T_OP_ROW != right_expr->get_expr_type()) {
|
|
hit = false;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
ObOpRawExpr *op_left_expr = static_cast<ObOpRawExpr *>(left_expr);
|
|
ObOpRawExpr *op_right_expr = static_cast<ObOpRawExpr *>(right_expr);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < op_right_expr->get_param_count(); i ++) {
|
|
ObRawExpr *tmp = op_right_expr->get_param_expr(i);
|
|
if (T_OP_ROW != tmp->get_expr_type()) {
|
|
hit = false;
|
|
break;
|
|
}
|
|
|
|
ObOpRawExpr *value_expr = static_cast<ObOpRawExpr *>(tmp);
|
|
if (op_left_expr->get_param_count() != value_expr->get_param_count() ||
|
|
OB_ISNULL(value_expr->get_param_expr(pos1)) ||
|
|
OB_ISNULL(value_expr->get_param_expr(pos2)) ||
|
|
OB_UNLIKELY(!value_expr->get_param_expr(pos1)->is_const_expr() ||
|
|
!value_expr->get_param_expr(pos2)->is_const_expr())) {
|
|
hit = false;
|
|
break;
|
|
}
|
|
|
|
RowDesc value_row_desc;
|
|
OZ(add_se_value_expr(value_expr->get_param_expr(pos1),
|
|
value_row_desc, 0, exec_ctx, vies_));
|
|
OZ(add_se_value_expr(value_expr->get_param_expr(pos2),
|
|
value_row_desc, 0, exec_ctx, sub_vies_));
|
|
}
|
|
if (OB_SUCC(ret) && hit) {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < vies_.count(); i++) {
|
|
vies_.at(i).dst_type_ = op_left_expr->get_param_expr(pos1)->get_result_type().get_type();
|
|
vies_.at(i).dst_cs_type_ = op_left_expr->get_param_expr(pos1)
|
|
->get_result_type().get_collation_type();
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < sub_vies_.count(); i++) {
|
|
sub_vies_.at(i).dst_type_ = op_left_expr->get_param_expr(pos2)->get_result_type().get_type();
|
|
sub_vies_.at(i).dst_cs_type_ = op_left_expr->get_param_expr(pos2)
|
|
->get_result_type().get_collation_type();
|
|
}
|
|
}
|
|
}
|
|
|
|
ObSEArray<ColumnItem, 5> part_columns;
|
|
ObSEArray<ColumnItem, 3> gen_cols;
|
|
ObSEArray<ColumnItem, 5> subpart_columns;
|
|
ObSEArray<ColumnItem, 3> sub_gen_cols;
|
|
|
|
if (OB_SUCC(ret) && hit) {
|
|
if (OB_FAIL(get_partition_column_info(stmt, PARTITION_LEVEL_ONE, part_columns, gen_cols,
|
|
part_raw_expr,
|
|
is_col_part_expr_, se_part_expr_,
|
|
se_gen_col_expr_, exec_ctx))) {
|
|
LOG_WARN("Failed to get partition column info", K(ret));
|
|
} else if (OB_FAIL(get_partition_column_info(stmt, PARTITION_LEVEL_TWO, subpart_columns,
|
|
sub_gen_cols, subpart_raw_expr,
|
|
is_col_subpart_expr_,
|
|
se_subpart_expr_, se_sub_gen_col_expr_, exec_ctx))) {
|
|
LOG_WARN("Failed to get sub partition column info", K(ret));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// generate values of insert sql or in expr
|
|
int ObTableLocation::add_se_value_expr(const ObRawExpr *value_expr,
|
|
RowDesc &value_row_desc,
|
|
int64_t expr_idx,
|
|
ObExecContext *exec_ctx,
|
|
ISeValueItemExprs &vies)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ValueItemExpr vie;
|
|
CK(OB_NOT_NULL(value_expr));
|
|
CK(OB_NOT_NULL(exec_ctx));
|
|
CK(OB_NOT_NULL(exec_ctx->get_sql_ctx()));
|
|
if (OB_FAIL(ret)) {
|
|
} else if (IS_DATATYPE_OR_QUESTIONMARK_OP(value_expr->get_expr_type())) { // is const
|
|
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr*>(value_expr);
|
|
if (T_QUESTIONMARK == const_expr->get_expr_type()) {
|
|
vie.idx_ = const_expr->get_value().get_unknown();
|
|
OX(vie.type_ = QUESTMARK_TYPE);
|
|
} else {
|
|
OZ(deep_copy_obj(allocator_, const_expr->get_value(), vie.obj_));
|
|
OX(vie.type_ = CONST_OBJ_TYPE);
|
|
}
|
|
} else { // not const, generate expr
|
|
OX(vie.type_ = CONST_EXPR_TYPE);
|
|
ObTempExpr *se_temp_expr = NULL;
|
|
OZ(ObStaticEngineExprCG::gen_expr_with_row_desc(value_expr, value_row_desc,
|
|
exec_ctx->get_allocator(),
|
|
exec_ctx->get_my_session(),
|
|
exec_ctx->get_sql_ctx()->schema_guard_,
|
|
se_temp_expr));
|
|
CK(OB_NOT_NULL(se_temp_expr));
|
|
OX(vie.expr_ = se_temp_expr);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (0 != value_row_desc.get_column_num()) {
|
|
ObRawExpr *desc_expr = NULL;
|
|
OZ(value_row_desc.get_column(expr_idx, desc_expr));
|
|
CK(OB_NOT_NULL(desc_expr));
|
|
OX(vie.dst_type_ = desc_expr->get_result_type().get_type());
|
|
OX(vie.dst_cs_type_ = desc_expr->get_result_type().get_collation_type());
|
|
if (ob_is_enum_or_set_type(vie.dst_type_)) {
|
|
vie.enum_set_values_cnt_ = desc_expr->get_enum_set_values().count();
|
|
vie.enum_set_values_ = desc_expr->get_enum_set_values().get_data();
|
|
}
|
|
} else {
|
|
// for in expr, and set dest_type after call this function
|
|
vie.dst_type_ = value_expr->get_result_type().get_type();
|
|
vie.dst_cs_type_ = value_expr->get_result_type().get_collation_type();
|
|
if (ob_is_enum_or_set_type(vie.dst_type_)) {
|
|
vie.enum_set_values_cnt_ = value_expr->get_enum_set_values().count();
|
|
vie.enum_set_values_ = value_expr->get_enum_set_values().get_data();
|
|
}
|
|
}
|
|
OZ(vies.push_back(vie));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::record_not_insert_dml_partition_info(
|
|
const ObDMLStmt &stmt,
|
|
ObExecContext *exec_ctx,
|
|
const ObTableSchema *table_schema,
|
|
const ObIArray<ObRawExpr*> &filter_exprs,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const bool is_in_range_optimization_enabled)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(set_location_calc_node(stmt,
|
|
filter_exprs,
|
|
PARTITION_LEVEL_ONE,
|
|
dtc_params,
|
|
exec_ctx,
|
|
se_part_expr_,
|
|
se_gen_col_expr_,
|
|
is_col_part_expr_,
|
|
calc_node_,
|
|
gen_col_node_,
|
|
part_get_all_,
|
|
is_part_range_get_,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("failed to set location calc node for first-level partition", K(ret));
|
|
} else if (PARTITION_LEVEL_TWO == part_level_
|
|
&& OB_FAIL(set_location_calc_node(stmt,
|
|
filter_exprs,
|
|
part_level_,
|
|
dtc_params,
|
|
exec_ctx,
|
|
se_subpart_expr_,
|
|
se_sub_gen_col_expr_,
|
|
is_col_subpart_expr_,
|
|
subcalc_node_,
|
|
sub_gen_col_node_,
|
|
subpart_get_all_,
|
|
is_subpart_range_get_,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("failed to set location calc node for second-level partition", K(ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_not_insert_dml_part_sort_expr(const ObDMLStmt &stmt,
|
|
ObIArray<ObRawExpr*> *sort_exprs) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL != sort_exprs) {
|
|
ObRawExpr *part_expr = NULL;
|
|
//一级column的range分区, range columns.里面的column exprs在partition间是有序的.
|
|
if (PARTITION_LEVEL_ONE == part_level_) {
|
|
if (((PARTITION_FUNC_TYPE_RANGE == part_type_
|
|
|| PARTITION_FUNC_TYPE_INTERVAL == part_type_) && is_col_part_expr_)
|
|
|| (PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type_)) {
|
|
part_expr = stmt.get_part_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
|
}
|
|
} else if (PARTITION_LEVEL_TWO == part_level_
|
|
&& ((PARTITION_FUNC_TYPE_RANGE == subpart_type_ && is_col_subpart_expr_)
|
|
|| PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_type_)) {
|
|
//二级分区,对于subpartition是column的range分区或者range columns。
|
|
//同时一级分区是单值情况,那么各级分区中的column exprs就是在获取的各个partition间有序.
|
|
if (!part_get_all_ && NULL != calc_node_) {
|
|
if (calc_node_->is_column_value_node()) {
|
|
part_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
|
} else if (calc_node_->is_query_range_node()) {
|
|
if (static_cast<ObPLQueryRangeNode*>(calc_node_)->pre_query_range_.is_precise_get()) {
|
|
part_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_);
|
|
}
|
|
} else { }
|
|
}
|
|
} else { }
|
|
|
|
if (NULL != part_expr) {
|
|
// When building local index, the partition by column is not included in select,
|
|
// so we replace the part expr with actual generated column expr.
|
|
// But this breaks the assumption that in oracle mode the partition expr must not be a column ref expr or row expr.
|
|
// So we need to disable this optimization in ddl scenario.
|
|
|
|
bool is_ddl = false;
|
|
if (stmt.get_table_items().count() > 0) {
|
|
const TableItem *insert_table_item = stmt.get_table_item(0);
|
|
is_ddl = insert_table_item->ddl_table_id_ > 0;
|
|
}
|
|
if (is_ddl) {
|
|
} else if (part_expr->is_column_ref_expr()) {
|
|
if (OB_FAIL(sort_exprs->push_back(part_expr))) {
|
|
LOG_WARN("Failed to add sort exprs", K(ret));
|
|
}
|
|
} else if (T_OP_ROW == part_expr->get_expr_type()) {
|
|
int64_t param_num = part_expr->get_param_count();
|
|
ObRawExpr *col_expr = NULL;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < param_num; ++idx) {
|
|
if (OB_ISNULL(col_expr = part_expr->get_param_expr(idx))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Col expr should not be NULL", K(ret));
|
|
} else if (!col_expr->is_column_ref_expr()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Param expr should be column expr", K(ret));
|
|
} else if (OB_FAIL(sort_exprs->push_back(col_expr))) {
|
|
LOG_WARN("Failed to add sort exprs", K(ret));
|
|
} else { }//do nothing
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Part expr should be Column or T_OP_ROW of column", K(ret), KPNAME(part_expr));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_location_calc_node(const ObPartitionLevel part_level,
|
|
ObIArray<ColumnItem> &partition_columns,
|
|
const ObRawExpr *partition_expr,
|
|
const ObIArray<ObRawExpr*> &filter_exprs,
|
|
ObPartLocCalcNode *&res_node,
|
|
bool &get_all,
|
|
bool &is_range_get,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
ObExecContext *exec_ctx,
|
|
const bool is_in_range_optimization_enabled)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t column_id = OB_INVALID_ID;
|
|
get_all = false;
|
|
is_range_get = false;
|
|
bool only_range_node = false;
|
|
|
|
if (partition_expr->is_column_ref_expr() || is_virtual_table(loc_meta_.ref_table_id_)) {
|
|
//partition expr is signle column, only query range needed
|
|
//In future column list is also only query range needed.
|
|
only_range_node = true;
|
|
} else if (partition_columns.count() == 1) {
|
|
column_id = partition_columns.at(0).column_id_;
|
|
//当partition_expr为function,且只有一个column的时候
|
|
//用于处理func(col) = X or col = Y的filter计算
|
|
} else { /*do nothing*/ }
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (only_range_node) {
|
|
bool always_true = false;
|
|
ObPartLocCalcNode *calc_node = NULL;
|
|
if (OB_FAIL(get_query_range_node(part_level,
|
|
partition_columns,
|
|
filter_exprs,
|
|
always_true,
|
|
calc_node,
|
|
dtc_params,
|
|
exec_ctx,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("Get query range node error", K(ret));
|
|
} else if (always_true) {
|
|
get_all = true;
|
|
} else {
|
|
res_node = calc_node;
|
|
if (OB_NOT_NULL(calc_node)) {
|
|
is_range_get = static_cast<ObPLQueryRangeNode*>(calc_node)->pre_query_range_.is_precise_get();
|
|
}
|
|
}
|
|
} else {
|
|
ObSEArray<ObRawExpr *, 5> normal_filters;
|
|
bool func_always_true = true;
|
|
ObPartLocCalcNode *func_node = NULL;
|
|
bool is_func_range_get = false;
|
|
bool is_column_range_get = false;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < filter_exprs.count(); ++idx) {
|
|
bool cnt_func_expr = false;
|
|
bool always_true = false;
|
|
ObPartLocCalcNode *calc_node = NULL;
|
|
if (OB_FAIL(analyze_filter(partition_columns, partition_expr, column_id, filter_exprs.at(idx),
|
|
always_true, calc_node, cnt_func_expr, dtc_params, exec_ctx))) {
|
|
LOG_WARN("Failed to analyze filter", K(ret));
|
|
} else {
|
|
if (!always_true && NULL != calc_node) {
|
|
func_always_true = false;
|
|
}
|
|
if (!cnt_func_expr) {
|
|
if (OB_FAIL(normal_filters.push_back(filter_exprs.at(idx)))) {
|
|
LOG_WARN("Failed to add filter", K(ret));
|
|
}
|
|
} else if (OB_FAIL(add_and_node(calc_node, func_node))) {
|
|
//这里好像用cnt_func_expr来确保calc_node不为NULL。但是真的有这种保证么
|
|
//如果是这种保证这个变量名就不太合适
|
|
LOG_WARN("Failed to add and node", K(ret));
|
|
} else {
|
|
is_func_range_get = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
bool column_always_true = false;
|
|
ObPartLocCalcNode *column_node = NULL;
|
|
if (normal_filters.count() > 0) {
|
|
if (OB_FAIL(get_query_range_node(part_level, partition_columns, filter_exprs, column_always_true,
|
|
column_node, dtc_params, exec_ctx, is_in_range_optimization_enabled))) {
|
|
LOG_WARN("Failed to get query range node", K(ret));
|
|
} else if (OB_NOT_NULL(column_node)) {
|
|
is_column_range_get = static_cast<ObPLQueryRangeNode*>(column_node)->pre_query_range_.is_precise_get();
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (func_always_true && column_always_true) {
|
|
get_all = true;
|
|
} else if (func_always_true) {
|
|
res_node = column_node;
|
|
} else if (column_always_true) {
|
|
res_node = func_node;
|
|
} else if (OB_FAIL(add_and_node(func_node, column_node))) {
|
|
LOG_WARN("Failed to add and node", K(ret));
|
|
} else {
|
|
res_node = column_node;
|
|
}
|
|
is_range_get = is_func_range_get || is_column_range_get;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_query_range_node(const ObPartitionLevel part_level,
|
|
const ColumnIArray &partition_columns,
|
|
const ObIArray<ObRawExpr*> &filter_exprs,
|
|
bool &always_true,
|
|
ObPartLocCalcNode *&calc_node,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
ObExecContext *exec_ctx,
|
|
const bool is_in_range_optimization_enabled)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool phy_rowid_for_table_loc = (part_level == part_level_);
|
|
if (filter_exprs.empty()) {
|
|
always_true = true;
|
|
} else if (OB_ISNULL(calc_node = ObPartLocCalcNode::create_part_calc_node(
|
|
allocator_, calc_nodes_, ObPartLocCalcNode::QUERY_RANGE))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Allocate memory failed", K(ret));
|
|
} else {
|
|
ObPLQueryRangeNode *node = static_cast<ObPLQueryRangeNode*>(calc_node);
|
|
if (OB_FAIL(node->pre_query_range_.preliminary_extract_query_range(partition_columns,
|
|
filter_exprs,
|
|
dtc_params,
|
|
exec_ctx,
|
|
NULL,
|
|
NULL,
|
|
phy_rowid_for_table_loc,
|
|
false,
|
|
is_in_range_optimization_enabled))) {
|
|
LOG_WARN("Failed to pre extract query range", K(ret));
|
|
} else if (node->pre_query_range_.is_precise_whole_range()) {
|
|
//pre query range is whole range, indicate that there are no partition condition in filters,
|
|
//so you need to get all part ids
|
|
always_true = true;
|
|
calc_node = NULL;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::analyze_filter(const ObIArray<ColumnItem> &partition_columns,
|
|
const ObRawExpr *partition_expr,
|
|
uint64_t column_id,
|
|
const ObRawExpr *filter,
|
|
bool &always_true,
|
|
ObPartLocCalcNode *&calc_node,
|
|
bool &cnt_func_expr,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
ObExecContext *exec_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(filter)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Filter should not be NULL", K(ret));
|
|
} else if (T_OP_OR == filter->get_expr_type() || T_OP_AND == filter->get_expr_type()) {
|
|
const ObOpRawExpr *op_expr = static_cast<const ObOpRawExpr *>(filter);
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < op_expr->get_param_count(); ++idx) {
|
|
ObPartLocCalcNode *cur_node = NULL;
|
|
bool f_always_true = false;
|
|
if (OB_FAIL(analyze_filter(partition_columns, partition_expr, column_id, op_expr->get_param_expr(idx),
|
|
f_always_true, cur_node, cnt_func_expr, dtc_params, exec_ctx))) {
|
|
LOG_WARN("Failed to replace sub_expr bool filter", K(ret));
|
|
} else if (T_OP_OR == filter->get_expr_type()) {
|
|
if (f_always_true || NULL == cur_node) {
|
|
always_true = true;
|
|
calc_node = NULL;
|
|
} else if (OB_FAIL(add_or_node(cur_node, calc_node))) {
|
|
LOG_WARN("Failed to add or node", K(ret));
|
|
} else { }
|
|
} else {
|
|
if (f_always_true || NULL == cur_node) {
|
|
//do nothing
|
|
} else if (OB_FAIL(add_and_node(cur_node, calc_node))) {
|
|
LOG_WARN("Failed to add and node", K(ret));
|
|
} else { }
|
|
}
|
|
}
|
|
} else if (T_OP_IN == filter->get_expr_type()) {
|
|
//todo extract_in_op
|
|
} else if (T_OP_EQ == filter->get_expr_type()) {
|
|
const ObRawExpr *l_expr = filter->get_param_expr(0);
|
|
const ObRawExpr *r_expr = filter->get_param_expr(1);
|
|
if (OB_FAIL(extract_eq_op(exec_ctx, l_expr, r_expr, column_id, partition_expr,
|
|
filter->get_result_type(), cnt_func_expr,
|
|
always_true, calc_node))) {
|
|
LOG_WARN("Failed to extract equal expr", K(ret));
|
|
}
|
|
} else { }
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::extract_eq_op(ObExecContext *exec_ctx,
|
|
const ObRawExpr *l_expr,
|
|
const ObRawExpr *r_expr,
|
|
const uint64_t column_id,
|
|
const ObRawExpr *partition_expr,
|
|
const ObExprResType &res_type,
|
|
bool &cnt_func_expr,
|
|
bool &always_true,
|
|
ObPartLocCalcNode *&calc_node)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
always_true = false;
|
|
if (OB_ISNULL(l_expr) || OB_ISNULL(r_expr) || OB_ISNULL(partition_expr)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("expr should not be NULL", K(ret), K(l_expr), K(r_expr), K(partition_expr));
|
|
} else if ((l_expr->has_flag(IS_ROWID) && r_expr->is_const_expr()) ||
|
|
(r_expr->has_flag(IS_ROWID) && l_expr->is_const_expr())) {
|
|
//rowid is meaning to use primary key
|
|
always_true = false;
|
|
cnt_func_expr = false;
|
|
} else if ((l_expr->has_flag(CNT_COLUMN) && !(l_expr->has_flag(IS_COLUMN))
|
|
&& r_expr->is_const_expr())
|
|
|| (r_expr->has_flag(CNT_COLUMN) && !(r_expr->has_flag(IS_COLUMN))
|
|
&& l_expr->is_const_expr())) {
|
|
const ObRawExpr *func_expr = l_expr->has_flag(CNT_COLUMN) ? l_expr : r_expr;
|
|
const ObRawExpr *c_expr = l_expr->is_const_expr() ? l_expr : r_expr;
|
|
// const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr*>(c_expr);
|
|
bool equal = false;
|
|
ObExprEqualCheckContext equal_ctx;
|
|
bool true_false = true;
|
|
if (!ObQueryRange::can_be_extract_range(T_OP_EQ, func_expr->get_result_type(),
|
|
res_type.get_calc_meta(), c_expr->get_result_type().get_type(), true_false)) {
|
|
always_true = true_false;
|
|
} else if (OB_FAIL(check_expr_equal(partition_expr, func_expr, equal, equal_ctx))) {
|
|
LOG_WARN("Failed to check equal expr", K(ret));
|
|
} else if (equal) {
|
|
if (NULL == (calc_node = ObPartLocCalcNode::create_part_calc_node(
|
|
allocator_, calc_nodes_, ObPartLocCalcNode::FUNC_VALUE))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Failed to create expr calc node", K(ret));
|
|
} else {
|
|
ObPLFuncValueNode *node = static_cast<ObPLFuncValueNode*>(calc_node);
|
|
cnt_func_expr = true;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < equal_ctx.param_expr_.count(); ++idx) {
|
|
ObExprEqualCheckContext::ParamExprPair ¶m_pair = equal_ctx.param_expr_.at(idx);
|
|
if (OB_ISNULL(param_pair.expr_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Param expr should not be NULL", K(ret));
|
|
} else if (param_pair.param_idx_ < 0) {
|
|
ret = OB_ERR_ILLEGAL_INDEX;
|
|
LOG_WARN("Wrong index of question mark position", K(ret), "param_idx", param_pair.param_idx_);
|
|
} else if (!param_pair.expr_->is_const_or_param_expr()
|
|
|| T_QUESTIONMARK == param_pair.expr_->get_expr_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Param pair expr should be const and const in expr_to_find should not be T_QUESTIONMARK", K(ret));
|
|
} else {
|
|
const ObObj &expect_val = static_cast<const ObConstRawExpr*>(param_pair.expr_)->get_value();
|
|
ObObj dst;
|
|
if (OB_FAIL(deep_copy_obj(allocator_, expect_val, dst))) {
|
|
LOG_WARN("Failed to deep copy obj", K(ret));
|
|
} else if (OB_FAIL(node->param_value_.push_back(
|
|
ObPLFuncValueNode::ParamValuePair(param_pair.param_idx_, dst)))) {
|
|
LOG_WARN("Failed to add param value pair", K(ret));
|
|
} else { }//do nothing
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(extract_value_item_expr(exec_ctx, c_expr, func_expr, node->vie_))) {
|
|
LOG_WARN("failed to extract value item expr", K(ret));
|
|
}
|
|
}
|
|
} else { }//do nothing
|
|
} else if ((l_expr->has_flag(IS_COLUMN) && r_expr->is_const_expr())
|
|
|| (r_expr->has_flag(IS_COLUMN) && l_expr->is_const_expr())) {
|
|
const ObRawExpr *col_expr = !l_expr->is_const_expr() ? l_expr : r_expr;
|
|
const ObRawExpr *c_expr = l_expr->is_const_expr() ? l_expr : r_expr;
|
|
const ObColumnRefRawExpr *column_expr = static_cast<const ObColumnRefRawExpr*>(col_expr);
|
|
if (column_id == column_expr->get_column_id()) {
|
|
bool true_false = false;
|
|
if (!ObQueryRange::can_be_extract_range(T_OP_EQ, col_expr->get_result_type(),
|
|
res_type.get_calc_meta(), c_expr->get_result_type().get_type(), true_false)) {
|
|
always_true = true_false;
|
|
} else if (NULL == (calc_node = ObPartLocCalcNode::create_part_calc_node(
|
|
allocator_, calc_nodes_, ObPartLocCalcNode::COLUMN_VALUE))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Failed to create expr calc node", K(ret));
|
|
} else {
|
|
ObPLColumnValueNode *node = static_cast<ObPLColumnValueNode*>(calc_node);
|
|
if (OB_FAIL(extract_value_item_expr(exec_ctx, c_expr, col_expr, node->vie_))) {
|
|
LOG_WARN("failed to extract value item expr", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::extract_value_item_expr(ObExecContext *exec_ctx,
|
|
const ObRawExpr *expr,
|
|
const ObRawExpr *dst_expr,
|
|
ValueItemExpr &vie)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(expr) || OB_ISNULL(dst_expr) || OB_ISNULL(exec_ctx) ||
|
|
OB_ISNULL(exec_ctx->get_sql_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(expr), K(exec_ctx));
|
|
} else if (expr->is_const_or_param_expr()) {
|
|
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr*>(expr);
|
|
if (T_QUESTIONMARK == const_expr->get_expr_type()) {
|
|
vie.idx_ = const_expr->get_value().get_unknown();
|
|
vie.type_ = QUESTMARK_TYPE;
|
|
} else {
|
|
if (OB_FAIL(deep_copy_obj(allocator_, const_expr->get_value(), vie.obj_))) {
|
|
LOG_WARN("Failed to deep copy const value", K(ret));
|
|
} else {
|
|
vie.type_ = CONST_OBJ_TYPE;
|
|
}
|
|
}
|
|
} else {
|
|
vie.type_ = CONST_EXPR_TYPE;
|
|
RowDesc row_desc;
|
|
ObTempExpr *temp_expr = NULL;
|
|
if (OB_FAIL(ObStaticEngineExprCG::gen_expr_with_row_desc(expr,
|
|
row_desc,
|
|
exec_ctx->get_allocator(),
|
|
exec_ctx->get_my_session(),
|
|
exec_ctx->get_sql_ctx()->schema_guard_,
|
|
temp_expr))) {
|
|
LOG_WARN("failed to generate expr with row desc", K(ret));
|
|
} else {
|
|
vie.expr_ = temp_expr;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
vie.dst_type_ = dst_expr->get_result_type().get_type();
|
|
vie.dst_cs_type_ = dst_expr->get_result_type().get_collation_type();
|
|
if (ob_is_enum_or_set_type(vie.dst_type_)) {
|
|
vie.enum_set_values_cnt_ = dst_expr->get_enum_set_values().count();
|
|
vie.enum_set_values_ = dst_expr->get_enum_set_values().get_data();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::check_expr_equal(
|
|
const ObRawExpr *partition_expr,
|
|
const ObRawExpr *check_expr,
|
|
bool &equal,
|
|
ObExprEqualCheckContext &equal_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
equal = partition_expr->same_as(*check_expr, &equal_ctx);
|
|
if (OB_SUCCESS != equal_ctx.err_code_) {
|
|
ret = equal_ctx.err_code_;
|
|
LOG_WARN("Failed to check whether expr equal", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//我们要构造的是该索引的rowkey顺序,所以这里的rowkey_info必须要跟被计算的行的rowkey顺序对应
|
|
//而这里的分区信息是依赖分区规则的分区信息,对于local索引,其本身没有分区规则信息,所依赖的是主表的分区规则
|
|
//所以对于全局索引和主表,传递本身的schema,而对于local索引,rowkey传递local index schema的rowkey
|
|
//而partition依赖主表,所以real_table_schema传递主表的schema
|
|
int ObTableLocation::generate_rowkey_desc(const ObDMLStmt &stmt,
|
|
const ObIArray<uint64_t> &column_ids,
|
|
uint64_t data_table_id,
|
|
ObRawExprFactory &expr_factory,
|
|
RowDesc &row_desc)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_FAIL(row_desc.init())) {
|
|
LOG_WARN("Failed to init row desc", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) {
|
|
uint64_t rowkey_id = column_ids.at(i);
|
|
//raw expr中的table_id都是主表的table_id,但是我们要构造索引(包括主键索引)的rowkey顺序,
|
|
//所以这里应该用主表table_id去查raw_expr
|
|
ObColumnRefRawExpr *rowkey_col = stmt.get_column_expr_by_id(data_table_id, rowkey_id);
|
|
if (OB_ISNULL(rowkey_col)) {
|
|
//rowkey在stmt中没有被解析,构造一个临时的rowkey column expr
|
|
if (OB_FAIL(expr_factory.create_raw_expr(T_REF_COLUMN, rowkey_col))) {
|
|
LOG_WARN("create mock rowkey column expr failed", K(ret));
|
|
} else if (OB_FAIL(row_desc.add_column(rowkey_col))) {
|
|
LOG_WARN("add rowkey column expr to row desc failed", K(ret));
|
|
}
|
|
} else if (OB_FAIL(row_desc.add_column(rowkey_col))) {
|
|
LOG_WARN("add rowkey column expr to row desc failed", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_partition_column_info(const ObDMLStmt &stmt,
|
|
const ObPartitionLevel part_level,
|
|
ObIArray<ColumnItem> &partition_columns,
|
|
ObIArray<ColumnItem> &gen_cols,
|
|
const ObRawExpr *&partition_raw_expr,
|
|
bool &is_col_part_expr,
|
|
ObTempExpr *&part_temp_expr,
|
|
ObTempExpr *&gen_col_temp_expr,
|
|
ObExecContext *exec_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
partition_raw_expr = NULL;
|
|
ObRawExpr *gen_col_expr = NULL;
|
|
RowDesc row_desc;
|
|
RowDesc gen_row_desc;
|
|
if (PARTITION_LEVEL_ONE != part_level && PARTITION_LEVEL_TWO != part_level) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("part level should be One or Two", K(ret));
|
|
} else if (PARTITION_LEVEL_ONE == part_level &&
|
|
OB_ISNULL(partition_raw_expr = stmt.get_part_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Partition expr not in stmt", K(ret), K(loc_meta_));
|
|
} else if (PARTITION_LEVEL_TWO == part_level &&
|
|
OB_ISNULL(partition_raw_expr = stmt.get_subpart_expr(loc_meta_.table_loc_id_, loc_meta_.ref_table_id_))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Partition expr not in stmt", K(ret), K(loc_meta_));
|
|
} else if (PARTITION_LEVEL_ONE == part_level &&
|
|
(PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type_ ||
|
|
PARTITION_FUNC_TYPE_INTERVAL == part_type_) &&
|
|
OB_FAIL(can_get_part_by_range_for_range_columns(partition_raw_expr,
|
|
is_valid_range_columns_part_range_))) {
|
|
LOG_WARN("failed ot check can get part by range for range columns", K(ret));
|
|
} else if (PARTITION_LEVEL_TWO == part_level &&
|
|
PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_type_ &&
|
|
OB_FAIL(can_get_part_by_range_for_range_columns(partition_raw_expr,
|
|
is_valid_range_columns_subpart_range_))) {
|
|
LOG_WARN("failed ot check can get part by range for range columns", K(ret));
|
|
} else if (PARTITION_LEVEL_ONE == part_level &&
|
|
OB_FAIL(can_get_part_by_range_for_temporal_column(partition_raw_expr,
|
|
is_valid_temporal_part_range_))) {
|
|
LOG_WARN("failed ot check can get part by range for range columns", K(ret));
|
|
} else if (PARTITION_LEVEL_TWO == part_level &&
|
|
OB_FAIL(can_get_part_by_range_for_temporal_column(partition_raw_expr,
|
|
is_valid_temporal_subpart_range_))) {
|
|
LOG_WARN("failed ot check can get part by range for range columns", K(ret));
|
|
} else if (FALSE_IT(is_col_part_expr = partition_raw_expr->is_column_ref_expr())) {
|
|
} else if (OB_FAIL(row_desc.init())) {
|
|
LOG_WARN("Failed to init row desc", K(ret));
|
|
} else if (OB_FAIL(gen_row_desc.init())) {
|
|
LOG_WARN("Failed to init row desc", K(ret));
|
|
} else if (OB_FAIL(add_partition_columns(stmt, partition_raw_expr, partition_columns,
|
|
gen_cols, gen_col_expr, row_desc, gen_row_desc))) {
|
|
LOG_WARN("Failed to add partitoin column", K(ret));
|
|
} else {
|
|
if (gen_cols.count() > 0) {
|
|
if (partition_columns.count() > 1) {
|
|
gen_cols.reset();
|
|
} else if (OB_ISNULL(exec_ctx) || OB_ISNULL(exec_ctx->get_sql_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", KP(exec_ctx), K(ret));
|
|
} else {
|
|
OZ (ObStaticEngineExprCG::gen_expr_with_row_desc(gen_col_expr,
|
|
gen_row_desc,
|
|
exec_ctx->get_allocator(),
|
|
exec_ctx->get_my_session(),
|
|
exec_ctx->get_sql_ctx()->schema_guard_,
|
|
gen_col_temp_expr));
|
|
}
|
|
}
|
|
//generate partition_expression with partition columns row_desc
|
|
if (OB_SUCC(ret)) {
|
|
ObTempExpr *gen_col_runtime_expr = NULL;
|
|
OZ (ObStaticEngineExprCG::gen_expr_with_row_desc(partition_raw_expr,
|
|
row_desc,
|
|
exec_ctx->get_allocator(),
|
|
exec_ctx->get_my_session(),
|
|
exec_ctx->get_sql_ctx()->schema_guard_,
|
|
part_temp_expr));
|
|
}
|
|
|
|
//clear IS_COLUMNLIZED flag
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(clear_columnlized_in_row_desc(row_desc))) {
|
|
LOG_WARN("Failed to clear columnlized in row desc", K(ret));
|
|
} else if (OB_FAIL(clear_columnlized_in_row_desc(gen_row_desc))) {
|
|
LOG_WARN("Failed to clear columnlized in row desc", K(ret));
|
|
} else { }//do nothing
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::add_partition_columns(const ObDMLStmt &stmt,
|
|
const ObRawExpr *part_expr,
|
|
ObIArray<ColumnItem> &partition_columns,
|
|
ObIArray<ColumnItem> &gen_cols,
|
|
ObRawExpr *&gen_col_expr,
|
|
RowDesc &row_desc,
|
|
RowDesc &gen_row_desc,
|
|
const bool only_gen_cols)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ObRawExpr*, 2> cur_vars;
|
|
if (OB_ISNULL(part_expr)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Part expr is NULL", K(ret));
|
|
} else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(part_expr, cur_vars))) {
|
|
LOG_WARN("get column exprs error", K(ret));
|
|
} else {
|
|
ObRawExpr *var = NULL;
|
|
uint64_t column_id = OB_INVALID_ID;
|
|
uint64_t table_id = OB_INVALID_ID;
|
|
ObColumnRefRawExpr *col_expr = NULL;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < cur_vars.count(); ++idx) {
|
|
if (OB_ISNULL(var = cur_vars.at(idx))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Var should not be NULL in column exprs", K(ret));
|
|
} else if (!var->is_column_ref_expr()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Var should be column", K(ret));
|
|
} else if (FALSE_IT(col_expr = static_cast<ObColumnRefRawExpr*>(var))) {
|
|
} else if (OB_UNLIKELY(OB_INVALID_ID == (column_id = col_expr->get_column_id()))
|
|
|| OB_UNLIKELY(OB_INVALID_ID == (table_id = col_expr->get_table_id()))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Column id should not be OB_INVALID_ID", K(ret));
|
|
} else if (only_gen_cols) {//only deal dependented columns for generated partition column
|
|
if (OB_FAIL(add_partition_column(stmt, table_id, column_id, gen_cols, gen_row_desc))) {
|
|
LOG_WARN("Failed to add partiton column", K(ret));
|
|
}
|
|
} else {
|
|
if (col_expr->is_generated_column()) {
|
|
if (OB_ISNULL(col_expr->get_dependant_expr())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Generated column's dependent expr is NULL", K(ret));
|
|
} else if (cur_vars.count() > 1) {
|
|
//do nothing.Only deal case with one partition column.
|
|
} else {
|
|
gen_col_expr = col_expr->get_dependant_expr();
|
|
bool can_replace = false;
|
|
if (OB_FAIL(check_can_replace(gen_col_expr, col_expr, can_replace))) {
|
|
LOG_WARN("failed to check can replace", K(ret));
|
|
} else if (!can_replace) {
|
|
//do nothing
|
|
} else if (OB_FAIL(add_partition_columns(stmt, col_expr->get_dependant_expr(),
|
|
partition_columns, gen_cols, gen_col_expr,
|
|
row_desc, gen_row_desc, true))) {
|
|
LOG_WARN("Failed to add gen columns", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(add_partition_column(stmt, table_id, column_id,
|
|
partition_columns, row_desc))) {
|
|
LOG_WARN("Failed to add partiton column", K(ret));
|
|
}
|
|
}
|
|
}//end of else
|
|
}//end of for
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::check_can_replace(ObRawExpr *gen_col_expr,
|
|
ObRawExpr *col_expr,
|
|
bool &can_replace)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
can_replace = false;
|
|
ObCollationLevel res_cs_level = CS_LEVEL_INVALID;
|
|
ObCollationType res_cs_type = CS_TYPE_INVALID;
|
|
ObRawExpr* expr = gen_col_expr;
|
|
if (OB_ISNULL(gen_col_expr) || OB_ISNULL(col_expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid parameter", K(ret));
|
|
} else if (!ob_is_string_or_lob_type(gen_col_expr->get_result_type().get_type()) ||
|
|
!ob_is_string_or_lob_type(col_expr->get_result_type().get_type())) {
|
|
can_replace = true;
|
|
} else if (gen_col_expr->get_expr_type() != T_FUN_COLUMN_CONV) {
|
|
can_replace = true;
|
|
} else if (((gen_col_expr->get_param_count() != 5) &&
|
|
(gen_col_expr->get_param_count() != 6)) ||
|
|
OB_ISNULL(expr = gen_col_expr->get_param_expr(4))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected error",K(gen_col_expr->get_param_count()), K(expr), K(ret));
|
|
} else if (expr->has_flag(IS_INNER_ADDED_EXPR)) {
|
|
while (expr->has_flag(IS_INNER_ADDED_EXPR) &&
|
|
(expr->get_param_count() > 0) &&
|
|
(NULL != expr->get_param_expr(0))) {
|
|
expr = expr->get_param_expr(0);
|
|
}
|
|
}
|
|
if (OB_FAIL(ret) || can_replace) {
|
|
//do nothing
|
|
} else if (expr->get_result_type().get_collation_type() != col_expr->get_result_type().get_collation_type()) {
|
|
can_replace = false;
|
|
} else {
|
|
can_replace = true;
|
|
}
|
|
return ret;
|
|
}
|
|
int ObTableLocation::add_partition_column(const ObDMLStmt &stmt,
|
|
const uint64_t table_id,
|
|
const uint64_t column_id,
|
|
ObIArray<ColumnItem> &partition_columns,
|
|
RowDesc &row_desc)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
//去除partition columns中重复的columns
|
|
bool is_different = true;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && is_different && idx < partition_columns.count(); ++idx) {
|
|
if (partition_columns.at(idx).column_id_ == column_id) {
|
|
is_different = false;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (is_different) {
|
|
ColumnItem *column_item = NULL;
|
|
if (OB_ISNULL(column_item = stmt.get_column_item_by_id(table_id, column_id))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Failed to get column item by id", K(table_id), K(column_id), K(ret));
|
|
} else if (OB_ISNULL(column_item->get_expr())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Column item's expr is NULL", K(ret));
|
|
} else if (OB_FAIL(row_desc.add_column(column_item->get_expr()))) {
|
|
LOG_WARN("Failed to add column item to temporary row desc", K(ret));
|
|
} else if (OB_FAIL(partition_columns.push_back(*column_item))) {
|
|
LOG_WARN("Failed to add column item to partition columns", K(ret));
|
|
} else if (OB_FAIL(column_item->get_expr()->add_flag(IS_COLUMNLIZED))) {
|
|
LOG_WARN("failed to add flag IS_COLUMNLIZED", K(ret));
|
|
} else { }
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_ids_by_calc_node(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPartLocCalcNode *calc_node,
|
|
const ObPartLocCalcNode *gen_col_node,
|
|
const ObTempExpr *se_gen_col_expr,
|
|
const bool part_col_get_all,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ObTabletID, 5> gen_tablet_ids;
|
|
ObSEArray<ObObjectID, 5> gen_part_ids;
|
|
bool part_col_all_part = false;
|
|
bool gen_col_all_part = false;
|
|
//get partition ids with information of partition columns
|
|
if (!part_col_get_all) {
|
|
//partition condition is not empty, so you need to calc partition id by partition key
|
|
if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params, calc_node,
|
|
tablet_ids, partition_ids, part_col_all_part,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Failed to calc partitoin ids by calc node", K(ret));
|
|
}
|
|
} else {
|
|
part_col_all_part = true;
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL != gen_col_node && NULL != se_gen_col_expr) {
|
|
//partition key is generated column and dependent column condition is not empty
|
|
//so you need to calc partition id by dependent column condition
|
|
if (!gen_col_node->is_query_range_node()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("column dependented by generated column calc node should be query range node", K(ret));
|
|
} else if (OB_FAIL(calc_query_range_partition_ids(exec_ctx, tablet_mapper, params,
|
|
static_cast<const ObPLQueryRangeNode*>(gen_col_node),
|
|
gen_tablet_ids, gen_part_ids, gen_col_all_part, dtc_params,
|
|
part_ids, se_gen_col_expr))) {
|
|
LOG_WARN("Failed to calcl partition ids by gen col node", K(ret));
|
|
}
|
|
} else {
|
|
gen_col_all_part = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (!part_col_all_part && !gen_col_all_part) {
|
|
//partition key condition is not empty and generated column dependent condition is not empty
|
|
//so you need to intersect partition ids extracted by these two conditions
|
|
OZ (intersect_partition_ids(gen_tablet_ids, tablet_ids));
|
|
OZ (intersect_partition_ids(gen_part_ids, partition_ids));
|
|
} else if (!part_col_all_part && gen_col_all_part) {
|
|
//generated column condition is empty, but partition key condition is not empty,
|
|
//use the partition ids extracted by partition key condition directly, do nothing
|
|
} else if (part_col_all_part && !gen_col_all_part) {
|
|
//generated column condition is not empty, but partition key condition is empty,
|
|
//use the partiiton ids extracted by generated column condition, so append to partition_ids
|
|
OZ (append(tablet_ids, gen_tablet_ids));
|
|
OZ (append(partition_ids, gen_part_ids));
|
|
} else {
|
|
//part_col_all_part=true && gen_col_all_part=true
|
|
//has no any partition condition, get all partition ids in schema
|
|
if (OB_FAIL(get_all_part_ids(tablet_mapper,tablet_ids,
|
|
partition_ids, part_ids))) {
|
|
LOG_WARN("Get all part ids error", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int ObTableLocation::intersect_partition_ids(
|
|
const ObIArray<T> &to_inter_ids,
|
|
ObIArray<T> &partition_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<T, 128> intersect_tmp;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < partition_ids.count(); ++idx) {
|
|
if (has_exist_in_array(to_inter_ids, partition_ids.at(idx), NULL)) {
|
|
if (OB_FAIL(intersect_tmp.push_back(partition_ids.at(idx)))) {
|
|
LOG_WARN("Failed to add partition id", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
partition_ids.reset();
|
|
if (OB_FAIL(partition_ids.assign(intersect_tmp))) {
|
|
LOG_WARN("Failed to assign intersect tmp ids", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_ids_by_calc_node(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPartLocCalcNode *calc_node,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
all_part = false;
|
|
if (OB_UNLIKELY(NULL == calc_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Calc node should not be NULL", K(ret));
|
|
} else if (ObPartLocCalcNode::CALC_AND == calc_node->get_node_type()) {
|
|
if (OB_FAIL(calc_and_partition_ids(exec_ctx, tablet_mapper, params,
|
|
static_cast<const ObPLAndNode*>(calc_node),
|
|
tablet_ids, partition_ids, all_part,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Failed to calc and partition ids", K(ret));
|
|
}
|
|
} else if (ObPartLocCalcNode::CALC_OR == calc_node->get_node_type()) {
|
|
if (OB_FAIL(calc_or_partition_ids(exec_ctx, tablet_mapper, params,
|
|
static_cast<const ObPLOrNode *>(calc_node),
|
|
tablet_ids, partition_ids, all_part,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Failed to calc and partition ids", K(ret));
|
|
}
|
|
} else if (ObPartLocCalcNode::QUERY_RANGE == calc_node->get_node_type()) {
|
|
if (OB_FAIL(calc_query_range_partition_ids(exec_ctx, tablet_mapper, params,
|
|
static_cast<const ObPLQueryRangeNode*>(calc_node),
|
|
tablet_ids, partition_ids, all_part,
|
|
dtc_params, part_ids, NULL))) {
|
|
LOG_WARN("Failed to calc and partition ids", K(ret));
|
|
}
|
|
} else if (ObPartLocCalcNode::FUNC_VALUE == calc_node->get_node_type()) {
|
|
if (OB_FAIL(calc_func_value_partition_ids(exec_ctx, tablet_mapper, params,
|
|
static_cast<const ObPLFuncValueNode*>(calc_node),
|
|
tablet_ids, partition_ids, all_part,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Failed to calc and partition ids", K(ret));
|
|
}
|
|
} else if (ObPartLocCalcNode::COLUMN_VALUE == calc_node->get_node_type()) {
|
|
if (OB_FAIL(calc_column_value_partition_ids(exec_ctx, tablet_mapper, params,
|
|
static_cast<const ObPLColumnValueNode*>(calc_node),
|
|
tablet_ids, partition_ids,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Failed to calc and partition ids", K(ret));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Unknown calc node type", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_and_partition_ids(
|
|
ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPLAndNode *calc_node,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(calc_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Calc node should not be NULL", K(ret));
|
|
} else if (OB_ISNULL(calc_node->left_node_)
|
|
|| OB_ISNULL(calc_node->right_node_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("And node shoul have left and right node", K(ret));
|
|
} else {
|
|
ObSEArray<ObObjectID, 3> left_part_ids;
|
|
ObSEArray<ObTabletID, 3> left_tablet_ids;
|
|
bool left_all = false;
|
|
ObSEArray<ObObjectID, 3> right_part_ids;
|
|
ObSEArray<ObTabletID, 3> right_tablet_ids;
|
|
bool right_all = false;
|
|
if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params, calc_node->left_node_,
|
|
left_tablet_ids, left_part_ids,left_all,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Calc node error", K(ret));
|
|
} else if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params, calc_node->right_node_,
|
|
right_tablet_ids, right_part_ids, right_all,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Calc node error", K(ret));
|
|
} else if (left_all && right_all) {
|
|
all_part = true;
|
|
} else if (left_all) {
|
|
if (OB_FAIL(partition_ids.assign(right_part_ids))) {
|
|
LOG_WARN("Failed to assign part ids", K(ret));
|
|
} else if (OB_FAIL(tablet_ids.assign(right_tablet_ids))) {
|
|
LOG_WARN("Failed to assign tablet ids", K(ret));
|
|
}
|
|
} else if (right_all) {
|
|
if (OB_FAIL(partition_ids.assign(left_part_ids))) {
|
|
LOG_WARN("Failed to assign part ids", K(ret));
|
|
} else if (OB_FAIL(tablet_ids.assign(left_tablet_ids))) {
|
|
LOG_WARN("Failed to assign tablet ids", K(ret));
|
|
}
|
|
} else {
|
|
for (int64_t l_idx = 0; OB_SUCC(ret) && l_idx < left_part_ids.count(); ++l_idx) {
|
|
for (int64_t r_idx = 0; OB_SUCC(ret) && r_idx < right_part_ids.count(); ++r_idx) {
|
|
if (right_part_ids.at(r_idx) == left_part_ids.at(l_idx)) {
|
|
OZ(partition_ids.push_back(left_part_ids.at(l_idx)));
|
|
OZ(tablet_ids.push_back(left_tablet_ids.at(l_idx)));
|
|
}
|
|
}//end of r_idx
|
|
}//end of l_idx
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_or_partition_ids(
|
|
ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPLOrNode *calc_node,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(calc_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Calc node should not be NULL", K(ret));
|
|
} else if (OB_ISNULL(calc_node->left_node_)
|
|
|| OB_ISNULL(calc_node->right_node_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("And node shoul have left and right node", K(ret));
|
|
} else {
|
|
ObSEArray<ObObjectID, 3> left_part_ids;
|
|
ObSEArray<ObTabletID, 3> left_tablet_ids;
|
|
bool left_all = false;
|
|
ObSEArray<ObObjectID, 3> right_part_ids;
|
|
ObSEArray<ObTabletID, 3> right_tablet_ids;
|
|
bool right_all = false;
|
|
if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params, calc_node->left_node_,
|
|
left_tablet_ids, left_part_ids, left_all,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Calc node error", K(ret));
|
|
} else if (OB_FAIL(calc_partition_ids_by_calc_node(exec_ctx, tablet_mapper, params, calc_node->right_node_,
|
|
right_tablet_ids, right_part_ids, right_all,
|
|
dtc_params, part_ids))) {
|
|
LOG_WARN("Calc node error", K(ret));
|
|
} else if (left_all || right_all) {
|
|
all_part = true;
|
|
} else {
|
|
OZ(append_array_no_dup(partition_ids, left_part_ids));
|
|
OZ(append_array_no_dup(partition_ids, right_part_ids));
|
|
OZ(append_array_no_dup(tablet_ids, left_tablet_ids));
|
|
OZ(append_array_no_dup(tablet_ids, right_tablet_ids));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_query_range_partition_ids(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPLQueryRangeNode *calc_node,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids,
|
|
const ObTempExpr *se_gen_col_expr) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(calc_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Calc node should not be NULL", K(ret));
|
|
} else {
|
|
all_part = false;
|
|
ObQueryRangeArray query_ranges;
|
|
ObArenaAllocator allocator(CURRENT_CONTEXT->get_malloc_allocator());
|
|
allocator.set_label("CalcQRPartIds");
|
|
bool is_all_single_value_ranges = true;
|
|
if (OB_FAIL(calc_node->pre_query_range_.get_tablet_ranges(allocator, exec_ctx, query_ranges,
|
|
is_all_single_value_ranges, dtc_params))) {
|
|
LOG_WARN("get tablet ranges failed", K(ret));
|
|
} else if (OB_UNLIKELY(query_ranges.count() == 0)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Query ranges' count should not be 0",
|
|
"query range count", query_ranges.count(), K(ret));
|
|
} else {
|
|
bool is_empty = true;
|
|
if (OB_FAIL(is_all_ranges_empty(query_ranges, is_empty))) {
|
|
LOG_WARN("fail to check all ranges", K(query_ranges));
|
|
} else if (!is_empty) {
|
|
if (OB_FAIL(calc_partition_ids_by_ranges(exec_ctx,
|
|
tablet_mapper,
|
|
query_ranges,
|
|
is_all_single_value_ranges,
|
|
tablet_ids,
|
|
partition_ids,
|
|
all_part,
|
|
part_ids,
|
|
se_gen_col_expr))) {
|
|
LOG_WARN("Failed to get partition ids", K(ret), K(loc_meta_.table_loc_id_));
|
|
}
|
|
} else { } //do nothing. partition ids will be empty
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_func_value_partition_ids(
|
|
ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPLFuncValueNode *calc_node,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(calc_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Calc node should not be NULL", K(ret));
|
|
} else {
|
|
bool value_satisfy = true;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < calc_node->param_value_.count(); ++idx) {
|
|
const ObPLFuncValueNode::ParamValuePair &pair = calc_node->param_value_.at(idx);
|
|
if (pair.param_idx_ < 0 || pair.param_idx_ >= params.count()) {
|
|
ret = OB_INVALID_INDEX;
|
|
LOG_WARN("Param idx error", K(ret), "param idx", pair.param_idx_, "count", params.count());
|
|
} else if (!params.at(pair.param_idx_).is_equal(pair.obj_value_, CS_TYPE_BINARY)) {
|
|
value_satisfy = false;
|
|
break;
|
|
} else { } //do nothing
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (!value_satisfy) {
|
|
all_part = true;
|
|
} else {
|
|
ObObj tmp;
|
|
ObNewRow tmp_row;
|
|
ObArenaAllocator allocator(CURRENT_CONTEXT->get_malloc_allocator());
|
|
allocator.set_label("CalcFVPartIds");
|
|
ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NONE, calc_node->vie_.dst_cs_type_);
|
|
if (OB_FAIL(se_calc_value_item(cast_ctx, exec_ctx, params, calc_node->vie_, tmp_row, tmp))) {
|
|
LOG_WARN("failed to calc value item", K(ret));
|
|
} else if (OB_FAIL(calc_partition_id_by_func_value(tablet_mapper,
|
|
tmp,
|
|
true,
|
|
tablet_ids,
|
|
partition_ids,
|
|
part_ids))) {
|
|
LOG_WARN("Failed to calc partition id by func value", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_column_value_partition_ids(
|
|
ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ParamStore ¶ms,
|
|
const ObPLColumnValueNode *calc_node,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObDataTypeCastParams &dtc_params,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(calc_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Calc node should not be NULL", K(ret));
|
|
} else {
|
|
ObObj tmp;
|
|
ObNewRow tmp_row;
|
|
ObArenaAllocator allocator(CURRENT_CONTEXT->get_malloc_allocator());
|
|
allocator.set_label("CalcCVPartIds");
|
|
ObCastCtx cast_ctx(&allocator, &dtc_params, CM_NONE, calc_node->vie_.dst_cs_type_);
|
|
if (OB_FAIL(se_calc_value_item(cast_ctx, exec_ctx, params, calc_node->vie_, tmp_row, tmp))) {
|
|
LOG_WARN("failed to calc value item", K(ret));
|
|
} else {
|
|
ObNewRow result_row;
|
|
// allocate obj first
|
|
void *ptr = NULL;
|
|
if (NULL == (ptr = allocator.alloc(sizeof(ObObj)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("failed to allocate obj", K(ret));
|
|
} else {
|
|
result_row.cells_ = new (ptr) ObObj();
|
|
result_row.count_ = 1;
|
|
result_row.cells_[0] = tmp;
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
result_row,
|
|
tablet_ids,
|
|
partition_ids,
|
|
part_ids))) {
|
|
LOG_WARN("Calc partition id by row error", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_ids_by_ranges(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ObIArray<ObNewRange*> &ranges,
|
|
const bool is_all_single_value_ranges,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObIArray<ObObjectID> *part_ids,
|
|
const ObTempExpr *se_gen_col_expr) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool get_part_by_range = false;
|
|
bool need_calc_new_range = false;
|
|
bool need_try_split_range = false;
|
|
all_part = false;
|
|
ObSEArray<ObNewRange *, 1> new_ranges;
|
|
ObSEArray<ObNewRange *, 8> splited_ranges;
|
|
ObArenaAllocator allocator_for_range(CURRENT_CONTEXT->get_malloc_allocator());
|
|
allocator_for_range.set_label("CalcByRanges");
|
|
if (NULL != se_gen_col_expr) {
|
|
get_part_by_range = false;
|
|
need_calc_new_range = false;
|
|
all_part = !is_all_single_value_ranges;
|
|
} else if (NULL == part_ids) {//PARTITION_LEVEL_ONE
|
|
if (!is_range_part(part_type_) ||
|
|
is_include_physical_rowid_range(ranges) ||
|
|
((PARTITION_FUNC_TYPE_RANGE == part_type_ || PARTITION_FUNC_TYPE_INTERVAL == part_type_) && !is_col_part_expr_) ||
|
|
(PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type_ && !is_valid_range_columns_part_range_)) {
|
|
if (!is_all_single_value_ranges) {
|
|
if (is_include_physical_rowid_range(ranges)) {
|
|
all_part = true;
|
|
} else if (is_valid_temporal_part_range_) {
|
|
need_calc_new_range = true;
|
|
} else {
|
|
need_try_split_range = true;
|
|
}
|
|
}
|
|
} else {
|
|
get_part_by_range = true;
|
|
}
|
|
} else {//PARTITION_LEVEL_TWO
|
|
if (!is_range_part(subpart_type_) ||
|
|
is_include_physical_rowid_range(ranges) ||
|
|
(PARTITION_FUNC_TYPE_RANGE == subpart_type_ && !is_col_subpart_expr_) ||
|
|
(PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_type_ && !is_valid_range_columns_subpart_range_)) {
|
|
if (!is_all_single_value_ranges) {
|
|
if (is_include_physical_rowid_range(ranges)) {
|
|
all_part = true;
|
|
} else if (is_valid_temporal_subpart_range_) {
|
|
need_calc_new_range = true;
|
|
} else {
|
|
need_try_split_range = true;
|
|
}
|
|
}
|
|
} else {
|
|
get_part_by_range = true;
|
|
}
|
|
}
|
|
// if the part_key/subpart_key is in the form like year(datetime), the non-single-value range
|
|
// may be used to prune partition after calc by part_expr
|
|
if (OB_SUCC(ret) && need_calc_new_range) {
|
|
bool is_all_single_value_new_ranges = false;
|
|
if (OB_FAIL(calc_range_by_part_expr(exec_ctx, ranges, part_ids, allocator_for_range,
|
|
new_ranges, is_all_single_value_new_ranges))) {
|
|
LOG_WARN("fail to calc range by part expr", K(ret));
|
|
} else if ((NULL == part_ids && PARTITION_FUNC_TYPE_RANGE == part_type_) ||
|
|
(NULL != part_ids && PARTITION_FUNC_TYPE_RANGE == subpart_type_)) {
|
|
get_part_by_range = true;
|
|
} else if (!is_all_single_value_new_ranges) {
|
|
all_part = true;
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && need_try_split_range) {
|
|
if (OB_FAIL(try_split_integer_range(ranges, allocator_for_range, splited_ranges, all_part))) {
|
|
LOG_WARN("fail to try split integer range", K(ret));
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret) && !all_part) {
|
|
if (get_part_by_range) {
|
|
if (need_calc_new_range) {
|
|
OZ (get_part_ids_by_ranges(tablet_mapper, new_ranges,
|
|
tablet_ids, partition_ids, part_ids));
|
|
} else if (OB_FAIL(get_part_ids_by_ranges(tablet_mapper, ranges,
|
|
tablet_ids, partition_ids, part_ids))) {
|
|
LOG_WARN("Failed to get part ids by ranges", K(ret));
|
|
}
|
|
} else {
|
|
const ObIArray<ObNewRange*> &single_ranges = need_try_split_range ? splited_ranges : ranges;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !all_part && i < single_ranges.count(); ++i) {
|
|
ObNewRange *range = single_ranges.at(i);
|
|
ObNewRow input_row;
|
|
if (OB_ISNULL(range)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid range", K(ret));
|
|
} else if (range->is_physical_rowid_range_) {
|
|
if (OB_FAIL(get_tablet_and_object_id_with_phy_rowid(*range,
|
|
tablet_mapper,
|
|
tablet_ids,
|
|
partition_ids))) {
|
|
LOG_WARN("failed to get tablet and object id with phy rowid", K(ret));
|
|
} else {/*do nothing*/}
|
|
} else {
|
|
input_row.cells_ = const_cast<ObObj*>(range->start_key_.get_obj_ptr());
|
|
input_row.count_ = (range->start_key_.get_obj_cnt());
|
|
if (NULL != se_gen_col_expr) {
|
|
ObObj gen_col_val;
|
|
if (OB_FAIL(se_gen_col_expr->eval(exec_ctx, input_row, gen_col_val))) {
|
|
LOG_WARN("Failed to get column exprs", K(ret));
|
|
} else {
|
|
ObNewRow result_row;
|
|
result_row.cells_ = &gen_col_val;
|
|
result_row.count_ = 1;
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx, tablet_mapper, result_row,
|
|
tablet_ids, partition_ids, part_ids))) {
|
|
LOG_WARN("Failed to calc partition id by row", K(ret));
|
|
}
|
|
}
|
|
} else if (OB_FAIL(calc_partition_id_by_row(exec_ctx, tablet_mapper, input_row,
|
|
tablet_ids, partition_ids, part_ids))) {
|
|
LOG_WARN("Calc partition id by row error", K(ret));
|
|
} else { }//do nothing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObTableLocation::is_include_physical_rowid_range(const ObIArray<ObNewRange*> &ranges) const
|
|
{
|
|
bool is_included = false;
|
|
for (int64_t i = 0; !is_included && i < ranges.count(); ++i) {
|
|
is_included = ranges.at(i) != NULL && ranges.at(i)->is_physical_rowid_range_;
|
|
}
|
|
return is_included;
|
|
}
|
|
|
|
int ObTableLocation::get_part_ids_by_ranges(ObDASTabletMapper &tablet_mapper,
|
|
const ObIArray<ObNewRange*> &ranges,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL == part_ids) {
|
|
if (OB_FAIL((tablet_mapper.get_tablet_and_object_id(PARTITION_LEVEL_ONE, OB_INVALID_ID,
|
|
ranges, tablet_ids, partition_ids)))) {
|
|
LOG_WARN("fail to get tablet ids", K(ranges), K(ret));
|
|
}
|
|
} else {
|
|
for (int64_t p_idx = 0; OB_SUCC(ret) && p_idx < part_ids->count(); ++p_idx) {
|
|
ObObjectID part_id = part_ids->at(p_idx);
|
|
if (OB_FAIL((tablet_mapper.get_tablet_and_object_id(PARTITION_LEVEL_TWO, part_id,
|
|
ranges, tablet_ids, partition_ids)))) {
|
|
LOG_WARN("fail to get tablet ids", K(ranges), K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_id_by_func_value(
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ObObj &func_value,
|
|
const bool calc_oracle_hash,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObObj result = func_value;
|
|
if (OB_SUCC(ret) && !is_inner_table(loc_meta_.ref_table_id_)) {
|
|
bool hash_type = false;
|
|
if (NULL == part_ids) {
|
|
hash_type = (PARTITION_FUNC_TYPE_HASH == part_type_);
|
|
} else {
|
|
hash_type = (PARTITION_FUNC_TYPE_HASH == subpart_type_);
|
|
}
|
|
if (hash_type) {
|
|
//内部sql运行时始终作为mysql模式, 导致oracle临时表的借助inner sql执行的判断出问题,
|
|
//所以在这里根据table schema直接调用不同的hash计算函数
|
|
if (lib::is_oracle_mode()) {
|
|
if (calc_oracle_hash && OB_FAIL(ObExprFuncPartHash::calc_value_for_oracle(&func_value, 1, result))) {
|
|
LOG_WARN("Failed to calc hash value oracle mode", K(ret));
|
|
}
|
|
} 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_FAIL(ret)) {
|
|
} else {
|
|
if (NULL == part_ids) {
|
|
OZ(tablet_mapper.get_tablet_and_object_id(PARTITION_LEVEL_ONE, OB_INVALID_ID,
|
|
result, tablet_ids, partition_ids));
|
|
} else {
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < part_ids->count(); ++idx) {
|
|
OZ(tablet_mapper.get_tablet_and_object_id(PARTITION_LEVEL_TWO, part_ids->at(idx),
|
|
result, tablet_ids, partition_ids));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_ids_by_rowkey(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ObIArray<ObRowkey> &rowkeys,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRow cur_row;
|
|
ObSEArray<ObObjectID, 1> tmp_part_ids;
|
|
ObSEArray<ObTabletID, 1> tmp_tablet_ids;
|
|
ObNewRow *part_row = NULL;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < rowkeys.count(); ++i) {
|
|
cur_row.cells_ = const_cast<ObObj*>(rowkeys.at(i).get_obj_ptr());
|
|
cur_row.count_ = rowkeys.at(i).get_obj_cnt();
|
|
if (OB_FAIL(part_projector_.calc_part_row(exec_ctx, cur_row, part_row))
|
|
|| OB_ISNULL(part_row)) {
|
|
ret = COVER_SUCC(OB_ERR_UNEXPECTED);
|
|
LOG_WARN("calc part row failed", K(ret));
|
|
} else if (PARTITION_LEVEL_ONE == part_level_) {
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx, tablet_mapper, *part_row, tablet_ids, part_ids))) {
|
|
LOG_WARN("calc partition id by row failed", K(ret));
|
|
}
|
|
} else {
|
|
tmp_part_ids.reuse();
|
|
if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
*part_row,
|
|
tmp_tablet_ids,
|
|
tmp_part_ids))) {
|
|
LOG_WARN("calc partition id by row failed", K(ret));
|
|
} else if (OB_FAIL(calc_partition_id_by_row(exec_ctx,
|
|
tablet_mapper,
|
|
*part_row,
|
|
tablet_ids,
|
|
part_ids,
|
|
&tmp_part_ids))) {
|
|
LOG_WARN("calc sub partition id by row failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
case 1: interval_ym
|
|
diff1 = months_between(const_val - transition_val)
|
|
diff2 = extract(month, interval_val);
|
|
case 2: interval_ds
|
|
diff1 = extract(second from (const_val - transition_val))
|
|
diff2 = extract(second from interval);
|
|
case 3: other
|
|
diff1 = const_val - transition_val;
|
|
diff2 = interval_val;
|
|
|
|
n = trunc(diff1 / diff2) + 1;
|
|
result = transition + n * interval */
|
|
int calc_high_bound_obj_new_engine(
|
|
ObIAllocator &allocator,
|
|
ObSQLSessionInfo *session,
|
|
ObObj &const_val,
|
|
uint64_t exist_parts,
|
|
const ObObj &transition_val,
|
|
const ObObj &interval_val,
|
|
ObObj &out_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObNewRow tmp_row;
|
|
ObRawExpr *result_expr = NULL;
|
|
ObRawExpr *n_part_expr = NULL;
|
|
ParamStore dummy_params;
|
|
ObRawExprFactory expr_factory(allocator);
|
|
ObConstRawExpr *max_parts = NULL;
|
|
ObOpRawExpr *less_than_expr = NULL;
|
|
ObObj cmp_res;
|
|
ObObj max_interval;
|
|
|
|
CK (OB_NOT_NULL(session));
|
|
|
|
OZ (ObRawExprUtils::build_high_bound_raw_expr(expr_factory,
|
|
session,
|
|
const_val,
|
|
transition_val,
|
|
interval_val,
|
|
result_expr,
|
|
n_part_expr));
|
|
CK (OB_NOT_NULL(result_expr));
|
|
OZ (ObSQLUtils::calc_simple_expr_without_row(session,
|
|
result_expr, out_val, &dummy_params, allocator));
|
|
|
|
OX (max_interval.set_uint64(OB_MAX_INTERVAL_PARTITIONS - exist_parts));
|
|
OZ (ObRawExprUtils::build_const_obj_expr(expr_factory, max_interval, max_parts));
|
|
OZ (ObRawExprUtils::build_less_than_expr(expr_factory, n_part_expr, max_parts, less_than_expr));
|
|
OZ (less_than_expr->formalize(session));
|
|
OZ (ObSQLUtils::calc_simple_expr_without_row(session,
|
|
less_than_expr, cmp_res, &dummy_params, allocator));
|
|
if (OB_SUCC(ret) && !cmp_res.get_bool()) {
|
|
ret = OB_ERR_PARTITIONING_KEY_MAPS_TO_A_PARTITION_OUTSIDE_MAXIMUM_PERMITTED_NUMBER_OF_PARTITIONS;
|
|
LOG_WARN("exceed max partition", K(ret), K(const_val), K(exist_parts));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// int calc_high_bound_obj(
|
|
// ObExecContext &exec_ctx,
|
|
// ObObj &const_val,
|
|
// const ObObj &transition_val,
|
|
// const ObObj &interval_val,
|
|
// ObObj &out_val)
|
|
// {
|
|
// int ret = OB_SUCCESS;
|
|
// ParamStore dummy_params;
|
|
// const stmt::StmtType stmt_type = stmt::T_NONE;
|
|
// ObRawExpr *result_expr = NULL;
|
|
// ObRawExprFactory expr_factory(exec_ctx.get_allocator());
|
|
|
|
// OZ (ObRawExprUtils::build_high_bound_raw_expr(expr_factory,
|
|
// exec_ctx.get_my_session(),
|
|
// const_val,
|
|
// transition_val,
|
|
// interval_val,
|
|
// result_expr));
|
|
|
|
// CK (OB_NOT_NULL(result_expr));
|
|
// OZ (ObSQLUtils::calc_simple_expr_without_row(stmt_type, exec_ctx.get_my_session(),
|
|
// result_expr, out_val, &dummy_params, exec_ctx.get_allocator()));
|
|
|
|
// return ret;
|
|
// }
|
|
|
|
/* sync task, need response */
|
|
int ObTableLocation::send_add_interval_partition_rpc(
|
|
ObExecContext &exec_ctx,
|
|
share::schema::ObSchemaGetterGuard *schema_guard,
|
|
ObNewRow &row) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObTableSchema *table_schema = NULL;
|
|
const ObDatabaseSchema *db_schema = NULL;
|
|
ObSqlString sql;
|
|
ObMySQLProxy *sql_proxy = nullptr;
|
|
int64_t affected_rows = 0;
|
|
ObTimeZoneInfo tz_info;
|
|
ObObj result_obj;
|
|
uint64_t range_part_num = 0;
|
|
if (OB_ISNULL(exec_ctx.get_my_session())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret), K(exec_ctx.get_my_session()));
|
|
}
|
|
|
|
if (OB_SUCC(ret) && row.get_cell(0).is_null()) {
|
|
ret = OB_ERR_PARTITIONING_KEY_MAPS_TO_A_PARTITION_OUTSIDE_MAXIMUM_PERMITTED_NUMBER_OF_PARTITIONS;
|
|
LOG_USER_WARN(OB_ERR_PARTITIONING_KEY_MAPS_TO_A_PARTITION_OUTSIDE_MAXIMUM_PERMITTED_NUMBER_OF_PARTITIONS);
|
|
}
|
|
|
|
CK (OB_NOT_NULL(schema_guard));
|
|
OZ (schema_guard->get_table_schema(exec_ctx.get_my_session()->get_effective_tenant_id(),
|
|
loc_meta_.table_loc_id_, table_schema));
|
|
CK (OB_NOT_NULL(table_schema));
|
|
OZ (schema_guard->get_database_schema(table_schema->get_tenant_id(), table_schema->get_database_id(), db_schema));
|
|
CK (OB_NOT_NULL(db_schema));
|
|
|
|
CK (1 <= row.get_count());
|
|
CK (table_schema->get_transition_point().is_valid());
|
|
CK (table_schema->get_interval_range().is_valid());
|
|
CK (1 == table_schema->get_transition_point().get_obj_cnt());
|
|
CK (1 == table_schema->get_interval_range().get_obj_cnt());
|
|
OZ (table_schema->get_interval_parted_range_part_num(range_part_num));
|
|
|
|
OZ (calc_high_bound_obj_new_engine(exec_ctx.get_allocator(),
|
|
exec_ctx.get_my_session(),
|
|
row.get_cell(0),
|
|
range_part_num,
|
|
table_schema->get_transition_point().get_obj_ptr()[0],
|
|
table_schema->get_interval_range().get_obj_ptr()[0],
|
|
result_obj));
|
|
|
|
/* alter table table_name add partition ppp values less than (); */
|
|
if (OB_SUCC(ret)) {
|
|
ObRowkey high_bound_rowkey;
|
|
high_bound_rowkey.assign(&result_obj, 1);
|
|
|
|
|
|
tz_info.set_offset(0);
|
|
OZ (OTTZ_MGR.get_tenant_tz(table_schema->get_tenant_id(), tz_info.get_tz_map_wrap()));
|
|
|
|
SMART_VAR(char[OB_MAX_DEFAULT_VALUE_LENGTH], high_bound_buf) {
|
|
MEMSET(high_bound_buf, 0, OB_MAX_DEFAULT_VALUE_LENGTH);
|
|
int64_t high_bound_buf_pos = 0;
|
|
|
|
bool is_oracle_mode = false;
|
|
OZ (ObPartitionUtils::convert_rowkey_to_sql_literal(is_oracle_mode,
|
|
high_bound_rowkey,
|
|
high_bound_buf,
|
|
OB_MAX_DEFAULT_VALUE_LENGTH,
|
|
high_bound_buf_pos,
|
|
false,
|
|
&tz_info));
|
|
|
|
OZ (sql.assign_fmt("ALTER TABLE \"%.*s\".\"%.*s\" ADD PARTITION P_SYS_%d "
|
|
"VALUES LESS THAN (%.*s);",
|
|
db_schema->get_database_name_str().length(),
|
|
db_schema->get_database_name_str().ptr(),
|
|
table_schema->get_table_name_str().length(),
|
|
table_schema->get_table_name_str().ptr(),
|
|
1,
|
|
static_cast<int>(high_bound_buf_pos), high_bound_buf
|
|
));
|
|
OX (sql_proxy = GCTX.sql_proxy_);
|
|
CK (OB_NOT_NULL(sql_proxy));
|
|
OZ (sql_proxy->write(table_schema->get_tenant_id(), sql.ptr(), affected_rows, ORACLE_MODE));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* sync task, need response */
|
|
int ObTableLocation::send_add_interval_partition_rpc_new_engine(
|
|
ObIAllocator &allocator,
|
|
ObSQLSessionInfo *session,
|
|
ObSchemaGetterGuard *schema_guard,
|
|
const ObTableSchema *table_schema,
|
|
ObNewRow &row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObDatabaseSchema *db_schema = NULL;
|
|
ObSqlString sql;
|
|
ObMySQLProxy *sql_proxy = nullptr;
|
|
int64_t affected_rows = 0;
|
|
ObTimeZoneInfo tz_info;
|
|
ObObj result_obj;
|
|
uint64_t range_part_num = 0;
|
|
|
|
CK (OB_NOT_NULL(schema_guard));
|
|
CK (OB_NOT_NULL(session));
|
|
CK (OB_NOT_NULL(table_schema));
|
|
OZ (schema_guard->get_database_schema(table_schema->get_tenant_id(), table_schema->get_database_id(), db_schema));
|
|
CK (OB_NOT_NULL(db_schema));
|
|
|
|
CK (1 <= row.get_count());
|
|
if (OB_SUCC(ret) && row.get_cell(0).is_null()) {
|
|
ret = OB_ERR_PARTITIONING_KEY_MAPS_TO_A_PARTITION_OUTSIDE_MAXIMUM_PERMITTED_NUMBER_OF_PARTITIONS;
|
|
LOG_USER_WARN(OB_ERR_PARTITIONING_KEY_MAPS_TO_A_PARTITION_OUTSIDE_MAXIMUM_PERMITTED_NUMBER_OF_PARTITIONS);
|
|
}
|
|
CK (table_schema->get_transition_point().is_valid());
|
|
CK (table_schema->get_interval_range().is_valid());
|
|
CK (1 == table_schema->get_transition_point().get_obj_cnt());
|
|
CK (1 == table_schema->get_interval_range().get_obj_cnt());
|
|
OZ (table_schema->get_interval_parted_range_part_num(range_part_num));
|
|
|
|
OZ (calc_high_bound_obj_new_engine(allocator,
|
|
session,
|
|
row.get_cell(0),
|
|
range_part_num,
|
|
table_schema->get_transition_point().get_obj_ptr()[0],
|
|
table_schema->get_interval_range().get_obj_ptr()[0],
|
|
result_obj));
|
|
|
|
/* alter table table_name add partition ppp values less than (); */
|
|
if (OB_SUCC(ret)) {
|
|
ObRowkey high_bound_rowkey;
|
|
high_bound_rowkey.assign(&result_obj, 1);
|
|
|
|
|
|
tz_info.set_offset(0);
|
|
OZ (OTTZ_MGR.get_tenant_tz(table_schema->get_tenant_id(), tz_info.get_tz_map_wrap()));
|
|
|
|
SMART_VAR(char[OB_MAX_DEFAULT_VALUE_LENGTH], high_bound_buf) {
|
|
MEMSET(high_bound_buf, 0, OB_MAX_DEFAULT_VALUE_LENGTH);
|
|
int64_t high_bound_buf_pos = 0;
|
|
|
|
bool is_oracle_mode = false;
|
|
int64_t max_part_id = OB_INVALID_ID;
|
|
OZ (ObPartitionUtils::convert_rowkey_to_sql_literal(is_oracle_mode,
|
|
high_bound_rowkey,
|
|
high_bound_buf,
|
|
OB_MAX_DEFAULT_VALUE_LENGTH,
|
|
high_bound_buf_pos,
|
|
false,
|
|
&tz_info));
|
|
|
|
OZ (table_schema->get_max_part_id(max_part_id));
|
|
OZ (sql.assign_fmt("ALTER TABLE \"%.*s\".\"%.*s\" ADD PARTITION P_SYS_%d "
|
|
"VALUES LESS THAN (%.*s);",
|
|
db_schema->get_database_name_str().length(),
|
|
db_schema->get_database_name_str().ptr(),
|
|
table_schema->get_table_name_str().length(),
|
|
table_schema->get_table_name_str().ptr(),
|
|
static_cast<int>(max_part_id + 1),
|
|
static_cast<int>(high_bound_buf_pos), high_bound_buf
|
|
));
|
|
OX (sql_proxy = GCTX.sql_proxy_);
|
|
CK (OB_NOT_NULL(sql_proxy));
|
|
OZ (sql_proxy->write(table_schema->get_tenant_id(), sql.ptr(), affected_rows, ORACLE_MODE));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_id_by_row(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
ObNewRow &row,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObObj func_result;
|
|
share::schema::ObPartitionLevel calc_range_part_level = part_level_;
|
|
bool range_columns = false;
|
|
if (NULL == part_ids) {
|
|
if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == part_type_
|
|
|| PARTITION_FUNC_TYPE_LIST_COLUMNS == part_type_
|
|
|| PARTITION_FUNC_TYPE_INTERVAL == part_type_
|
|
|| (PARTITION_FUNC_TYPE_LIST == part_type_ && lib::is_oracle_mode())) {
|
|
part_projector_.project_part_row(PARTITION_LEVEL_ONE, row);
|
|
ObObjectID partition_id = OB_INVALID_ID;
|
|
ObTabletID tablet_id(ObTabletID::INVALID_TABLET_ID);
|
|
OZ(tablet_mapper.get_tablet_and_object_id(PARTITION_LEVEL_ONE, OB_INVALID_ID,
|
|
row, tablet_id, partition_id));
|
|
if (OB_INVALID_ID != partition_id) {
|
|
OZ(add_var_to_array_no_dup(partition_ids, partition_id));
|
|
OZ(add_var_to_array_no_dup(tablet_ids, tablet_id));
|
|
}
|
|
range_columns = true;
|
|
} else {
|
|
CK(OB_NOT_NULL(se_part_expr_));
|
|
OZ(se_part_expr_->eval(exec_ctx, row, func_result));
|
|
LOG_DEBUG("part expr func result", K(func_result), K(part_type_));
|
|
}
|
|
} else if (PARTITION_FUNC_TYPE_RANGE_COLUMNS == subpart_type_ || PARTITION_FUNC_TYPE_LIST_COLUMNS == subpart_type_) {
|
|
calc_range_part_level = PARTITION_LEVEL_TWO;
|
|
part_projector_.project_part_row(calc_range_part_level, row);
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < part_ids->count(); ++idx) {
|
|
ObObjectID partition_id = OB_INVALID_ID;
|
|
ObTabletID tablet_id(ObTabletID::INVALID_TABLET_ID);
|
|
OZ(tablet_mapper.get_tablet_and_object_id(PARTITION_LEVEL_TWO, part_ids->at(idx),
|
|
row, tablet_id, partition_id));
|
|
if (OB_INVALID_ID != partition_id) {
|
|
OZ(add_var_to_array_no_dup(partition_ids, partition_id));
|
|
OZ(add_var_to_array_no_dup(tablet_ids, tablet_id));
|
|
}
|
|
}
|
|
range_columns = true;
|
|
} else {
|
|
CK(OB_NOT_NULL(se_subpart_expr_));
|
|
OZ(se_subpart_expr_->eval(exec_ctx, row, func_result));
|
|
}
|
|
if (OB_FAIL(ret) || range_columns) {
|
|
} else if (OB_FAIL(calc_partition_id_by_func_value(tablet_mapper, func_result, false,
|
|
tablet_ids, partition_ids, part_ids))) {
|
|
LOG_WARN("Failed to calc partiton id by func value", K(ret));
|
|
}
|
|
if (0 == partition_ids.count() && PARTITION_LEVEL_ONE == calc_range_part_level) {
|
|
bool is_interval = false;
|
|
if (OB_ISNULL(tablet_mapper.get_table_schema())) {
|
|
// virtual table, do nothing
|
|
} else if (tablet_mapper.get_table_schema()->is_interval_part()) {
|
|
if (OB_FAIL(send_add_interval_partition_rpc(exec_ctx,
|
|
exec_ctx.get_sql_ctx()->schema_guard_,
|
|
row))) {
|
|
/* to do: already added, do same thing as add success */
|
|
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 {
|
|
/* change error */
|
|
set_interval_partition_insert_error(ret);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_all_part_ids(
|
|
ObDASTabletMapper &tablet_mapper,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObIArray<ObObjectID> *part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!is_partitioned_) {
|
|
OZ (tablet_mapper.get_non_partition_tablet_id(tablet_ids, partition_ids));
|
|
} else {
|
|
if (NULL == part_ids) {
|
|
if (OB_FAIL(tablet_mapper.get_all_tablet_and_object_id(
|
|
PARTITION_LEVEL_ONE, OB_INVALID_ID,
|
|
tablet_ids, partition_ids))) {
|
|
LOG_WARN("fail to get tablet ids", K(ret));
|
|
}
|
|
} else {
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < part_ids->count(); ++idx) {
|
|
ObObjectID part_id = part_ids->at(idx);
|
|
if (OB_FAIL(tablet_mapper.get_all_tablet_and_object_id(
|
|
PARTITION_LEVEL_TWO, part_id,
|
|
tablet_ids, partition_ids))) {
|
|
LOG_WARN("fail to get tablet ids", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::deal_dml_partition_selection(ObObjectID part_id) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!part_hint_ids_.empty()) {
|
|
bool found = false;
|
|
for (int j = 0; !found && j < part_hint_ids_.count(); j++) {
|
|
if (part_id == part_hint_ids_.at(j)) {
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
ret = OB_PARTITION_NOT_MATCH;
|
|
LOG_DEBUG("Partition not match", K(ret), K(part_id));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::deal_partition_selection(ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSEArray<ObObjectID, 16> tmp_part_ids;
|
|
ObSEArray<ObTabletID, 16> tmp_tablet_ids;
|
|
for (int i = 0; OB_SUCC(ret) && i < part_ids.count(); i++) {
|
|
OZ(tmp_part_ids.push_back(part_ids.at(i)));
|
|
OZ(tmp_tablet_ids.push_back(tablet_ids.at(i)));
|
|
}
|
|
part_ids.reset();
|
|
tablet_ids.reset();
|
|
bool found = false;
|
|
for (int tmp_idx = 0; OB_SUCC(ret) && tmp_idx < tmp_part_ids.count(); tmp_idx++) {
|
|
found = false;
|
|
for (int hint_idx = 0; !found && hint_idx < part_hint_ids_.count(); hint_idx++) {
|
|
if (tmp_part_ids.at(tmp_idx) == part_hint_ids_.at(hint_idx)) {
|
|
found = true;
|
|
}
|
|
}
|
|
if (found ) {
|
|
OZ(part_ids.push_back(tmp_part_ids.at(tmp_idx)));
|
|
OZ(tablet_ids.push_back(tmp_tablet_ids.at(tmp_idx)));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::add_and_node(
|
|
ObPartLocCalcNode *l_node,
|
|
ObPartLocCalcNode *&r_node)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (NULL == l_node
|
|
&& NULL == r_node) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("l_node and r_node should not both be NULL", K(ret));
|
|
} else if (NULL == l_node
|
|
|| NULL == r_node) {
|
|
r_node = (NULL == l_node) ? r_node : l_node;
|
|
} else {
|
|
ObPLAndNode *and_node = NULL;
|
|
if (NULL == (and_node = static_cast<ObPLAndNode*>(ObPartLocCalcNode::create_part_calc_node(
|
|
allocator_, calc_nodes_, ObPartLocCalcNode::CALC_AND)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Failed to allocate part calc node", K(ret));
|
|
} else {
|
|
and_node->left_node_ = l_node;
|
|
and_node->right_node_ = r_node;
|
|
r_node = and_node;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::add_or_node(
|
|
ObPartLocCalcNode *l_node,
|
|
ObPartLocCalcNode *&r_node)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(l_node)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("l_node should not be NULL", K(ret));
|
|
} else if (NULL == r_node) {
|
|
r_node = l_node;
|
|
} else {
|
|
ObPLOrNode *or_node = NULL;
|
|
if (NULL == (or_node = static_cast<ObPLOrNode*>(ObPartLocCalcNode::create_part_calc_node(
|
|
allocator_, calc_nodes_, ObPartLocCalcNode::CALC_OR)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("Failed to allocate part calc node", K(ret));
|
|
} else {
|
|
or_node->left_node_ = l_node;
|
|
or_node->right_node_ = r_node;
|
|
r_node = or_node;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::clear_columnlized_in_row_desc(RowDesc &row_desc)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t row_desc_count = row_desc.get_column_num();
|
|
ObRawExpr *expr = NULL;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < row_desc_count; ++idx) {
|
|
if (OB_ISNULL(expr = row_desc.get_column(idx))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Expr in row desc should not be NULL", K(ret));
|
|
} else if (OB_FAIL(expr->clear_flag(IS_COLUMNLIZED))) {
|
|
LOG_WARN("Failed to clear IS_COLUMNLIZED flag", K(ret));
|
|
} else { }//do nothing
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::init_row(
|
|
ObIAllocator &allocator,
|
|
const int64_t column_num,
|
|
ObNewRow &row) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
void *ptr = NULL;
|
|
if (column_num <= 0) {
|
|
} else if (OB_ISNULL(ptr = allocator.alloc(sizeof(ObObj) * column_num))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("failed to allocate pkey values", K(ret), K(column_num));
|
|
} else {
|
|
row.cells_ = new (ptr) ObObj[column_num];
|
|
row.count_ = column_num;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableLocation::se_calc_value_item(ObCastCtx cast_ctx,
|
|
ObExecContext &exec_ctx,
|
|
const ParamStore ¶ms,
|
|
const ValueItemExpr &vie,
|
|
ObNewRow &input_row,
|
|
ObObj &value) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (QUESTMARK_TYPE == vie.type_) {
|
|
if (vie.idx_ < 0 || vie.idx_ >= params.count()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid param idx", K(vie.idx_), K(ret));
|
|
} else {
|
|
value = params.at(vie.idx_);
|
|
}
|
|
} else if (CONST_OBJ_TYPE == vie.type_) {
|
|
value = vie.obj_;
|
|
} else if (CONST_EXPR_TYPE == vie.type_) {
|
|
if (OB_ISNULL(vie.expr_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("expr is null", K(ret));
|
|
} else if (OB_FAIL(vie.expr_->eval(exec_ctx, input_row, value))) {
|
|
LOG_WARN("failed to eval expr", K(ret));
|
|
}
|
|
}
|
|
// implicit cast values to value desc column type
|
|
if (OB_SUCC(ret)) {
|
|
if (vie.dst_type_ != value.get_type() || vie.dst_cs_type_ != value.get_collation_type()) {
|
|
if (ob_is_enum_or_set_type(vie.dst_type_)) {
|
|
ObExpectType expect_type;
|
|
expect_type.set_type(vie.dst_type_);
|
|
expect_type.set_collation_type(vie.dst_cs_type_);
|
|
ObSEArray<ObString, 8> type_infos;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < vie.enum_set_values_cnt_; ++i) {
|
|
OZ(type_infos.push_back(vie.enum_set_values_[i]));
|
|
}
|
|
expect_type.set_type_infos(&type_infos);
|
|
OZ(ObObjCaster::to_type(expect_type, cast_ctx, value, value));
|
|
} else {
|
|
OZ(ObObjCaster::to_type(vie.dst_type_, vie.dst_cs_type_, cast_ctx, value, value));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//calc row use new static type engine expr
|
|
int ObTableLocation::se_calc_value_item_row(common::ObExprCtx &expr_ctx,
|
|
ObExecContext &exec_ctx,
|
|
const ISeValueItemExprs &vies,
|
|
const int64_t key_count,
|
|
const int64_t value_idx,
|
|
ObNewRow &input_row,
|
|
ObNewRow &output_row) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (key_count <= 0) {
|
|
//do nothing
|
|
} else if (OB_ISNULL(output_row.cells_) || output_row.count_ < key_count
|
|
|| OB_ISNULL(exec_ctx.get_physical_plan_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("output_row row not init correct with key_count",
|
|
K(ret), K(key_count), K(output_row), K(exec_ctx.get_physical_plan_ctx()));
|
|
} else {
|
|
const int64_t start_pos = value_idx * key_count;
|
|
const auto ¶m_store = exec_ctx.get_physical_plan_ctx()->get_param_store();
|
|
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
|
|
for (int64_t key_idx = 0; OB_SUCC(ret) && key_idx < key_count; ++key_idx) {
|
|
ValueItemExpr vie;
|
|
OZ(vies.at(key_idx + start_pos, vie));
|
|
if (QUESTMARK_TYPE == vie.type_) {
|
|
output_row.cells_[key_idx] = param_store.at(vie.idx_);
|
|
} else if (CONST_OBJ_TYPE == vie.type_) {
|
|
output_row.cells_[key_idx] = vie.obj_;
|
|
} else if (CONST_EXPR_TYPE == vie.type_) {
|
|
CK(OB_NOT_NULL(vie.expr_));
|
|
OZ(vie.expr_->eval(exec_ctx, input_row, output_row.cells_[key_idx]));
|
|
}
|
|
// implicit cast values to value desc column type
|
|
if (OB_SUCC(ret)) {
|
|
if (vie.dst_type_ != output_row.cells_[key_idx].get_type()
|
|
|| vie.dst_cs_type_ != output_row.cells_[key_idx].get_collation_type()) {
|
|
if (ob_is_enum_or_set_type(vie.dst_type_)) {
|
|
ObExpectType expect_type;
|
|
expect_type.set_type(vie.dst_type_);
|
|
expect_type.set_collation_type(vie.dst_cs_type_);
|
|
ObSEArray<ObString, 8> type_infos;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < vie.enum_set_values_cnt_; ++i) {
|
|
OZ(type_infos.push_back(vie.enum_set_values_[i]));
|
|
}
|
|
expect_type.set_type_infos(&type_infos);
|
|
OZ(ObObjCaster::to_type(expect_type, cast_ctx,
|
|
output_row.cells_[key_idx], output_row.cells_[key_idx]));
|
|
} else {
|
|
OZ(ObObjCaster::to_type(vie.dst_type_, vie.dst_cs_type_, cast_ctx,
|
|
output_row.cells_[key_idx], output_row.cells_[key_idx]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::replace_ref_table_id(const uint64_t ref_table_id, ObExecContext &exec_ctx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
LOG_DEBUG("set log op infos", K(ref_table_id), K(loc_meta_));
|
|
//replace the partition hint ids with local index object id
|
|
ObDASTabletMapper tablet_mapper;
|
|
if (is_non_partition_optimized_) {
|
|
tablet_mapper.set_non_partitioned_table_ids(tablet_id_, object_id_, &related_list_);
|
|
}
|
|
if (OB_FAIL(DAS_CTX(exec_ctx).get_das_tablet_mapper(loc_meta_.ref_table_id_, tablet_mapper))) {
|
|
LOG_WARN("get das tablet mapper failed", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_hint_ids_.count(); ++i) {
|
|
ObObjectID dst_object_id;
|
|
if (OB_FAIL(tablet_mapper.get_related_partition_id(loc_meta_.ref_table_id_,
|
|
part_hint_ids_.at(i),
|
|
ref_table_id,
|
|
dst_object_id))) {
|
|
LOG_WARN("get related partition id failed", K(ret), K(loc_meta_),
|
|
K(ref_table_id), K(part_hint_ids_.at(i)), K(i));
|
|
} else {
|
|
part_hint_ids_.at(i) = dst_object_id;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
//replace the ref table id finally
|
|
loc_meta_.ref_table_id_ = ref_table_id;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPartIdRowMapManager::add_row_for_part(int64_t part_idx, int64_t row_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
//linear search right now. maybe, we can run binary search even interpolation search to get a better perf.
|
|
//if you are free, please do not be shy to improve this.
|
|
if (OB_UNLIKELY(part_idx < 0) || OB_UNLIKELY(part_idx > manager_.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("part idx is invalid", K(part_idx), K(manager_.count()), K(ret));
|
|
} else if (OB_LIKELY(part_idx < manager_.count())) {
|
|
if (OB_FAIL(manager_.at(part_idx).list_.push_back(row_id))) {
|
|
LOG_WARN("push row id to manager failed", K(ret));
|
|
}
|
|
} else {
|
|
MapEntry entry;
|
|
if (OB_FAIL(entry.list_.push_back(row_id))) {
|
|
LOG_WARN("push row id failed", K(ret), K(part_idx), K(row_id));
|
|
} else if (OB_FAIL(manager_.push_back(entry))) {
|
|
LOG_WARN("push entry failed", K(ret), K(part_idx), K(row_id));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
const ObPartIdRowMapManager::ObRowIdList* ObPartIdRowMapManager::get_row_id_list(int64_t part_index)
|
|
{
|
|
const ObPartIdRowMapManager::ObRowIdList* ret = NULL;
|
|
//linear search right now. maybe, we can run binary search even interpolation search to get a better perf.
|
|
//if you are free, please do not be shy to improve this.
|
|
if (part_index >= 0 && part_index < manager_.count()) {
|
|
ret = &(manager_.at(part_index).list_);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPartIdRowMapManager::MapEntry::assign(const ObPartIdRowMapManager::MapEntry &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (this != &other) {
|
|
if (OB_FAIL(list_.assign(other.list_))) {
|
|
LOG_WARN("copy list failed", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPartIdRowMapManager::assign(const ObPartIdRowMapManager &other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ARRAY_FOREACH(other.manager_, i) {
|
|
MapEntry map_entry;
|
|
if (OB_FAIL(map_entry.assign(other.manager_.at(i)))) {
|
|
LOG_WARN("assign manager entry failed", K(ret), K(i));
|
|
} else if (OB_FAIL(manager_.push_back(map_entry))) {
|
|
LOG_WARN("store map entry failed", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE(ObPLAndNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool has_child = false;
|
|
if (OB_NOT_NULL(left_node_) && OB_NOT_NULL(right_node_)) {
|
|
has_child = true;
|
|
} else if (OB_ISNULL(left_node_) && OB_ISNULL(right_node_)) {
|
|
has_child = false;
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("child node count is unexpected", K(ret));
|
|
}
|
|
BASE_SER(ObPartLocCalcNode);
|
|
OB_UNIS_ENCODE(has_child);
|
|
if (OB_SUCC(ret) && has_child) {
|
|
OB_UNIS_ENCODE(left_node_->node_type_);
|
|
OB_UNIS_ENCODE(right_node_->node_type_);
|
|
if (OB_FAIL(left_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize left node", K(ret));
|
|
} else if (OB_FAIL(right_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize right node", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObPLAndNode)
|
|
{
|
|
int64_t len = 0;
|
|
bool has_child = false;
|
|
if (OB_NOT_NULL(left_node_) && OB_NOT_NULL(right_node_)) {
|
|
has_child = true;
|
|
} else if (OB_ISNULL(left_node_) && OB_ISNULL(right_node_)) {
|
|
has_child = false;
|
|
}
|
|
BASE_ADD_LEN(ObPartLocCalcNode);
|
|
OB_UNIS_ADD_LEN(has_child);
|
|
if (has_child) {
|
|
OB_UNIS_ADD_LEN(left_node_->node_type_);
|
|
OB_UNIS_ADD_LEN(right_node_->node_type_);
|
|
len += left_node_->get_serialize_size();
|
|
len += right_node_->get_serialize_size();
|
|
}
|
|
return len;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObPLAndNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool has_child = false;
|
|
BASE_DESER(ObPartLocCalcNode);
|
|
OB_UNIS_DECODE(has_child);
|
|
if (has_child) {
|
|
NodeType left_child_type = INVALID;
|
|
NodeType right_child_type = INVALID;
|
|
OB_UNIS_DECODE(left_child_type);
|
|
OB_UNIS_DECODE(right_child_type);
|
|
ObPartLocCalcNode *left_child = NULL;
|
|
ObPartLocCalcNode *right_child = NULL;
|
|
if (OB_FAIL(create_part_calc_node(allocator_, left_child_type, left_child))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(create_part_calc_node(allocator_, right_child_type, right_child))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(left_child->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to do deserialize", K(ret));
|
|
} else if (OB_FAIL(right_child->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to do deserialize", K(ret));
|
|
} else {
|
|
left_node_ = left_child;
|
|
right_node_ = right_child;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE(ObPLOrNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool has_child = false;
|
|
if (OB_NOT_NULL(left_node_) && OB_NOT_NULL(right_node_)) {
|
|
has_child = true;
|
|
} else if (OB_ISNULL(left_node_) && OB_ISNULL(right_node_)) {
|
|
has_child = false;
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("child node count is unexpected", K(ret));
|
|
}
|
|
BASE_SER(ObPartLocCalcNode);
|
|
OB_UNIS_ENCODE(has_child);
|
|
if (OB_SUCC(ret) && has_child) {
|
|
OB_UNIS_ENCODE(left_node_->node_type_);
|
|
OB_UNIS_ENCODE(right_node_->node_type_);
|
|
if (OB_FAIL(left_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize left node", K(ret));
|
|
} else if (OB_FAIL(right_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize right node", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObPLOrNode)
|
|
{
|
|
int64_t len = 0;
|
|
bool has_child = false;
|
|
if (OB_NOT_NULL(left_node_) && OB_NOT_NULL(right_node_)) {
|
|
has_child = true;
|
|
} else if (OB_ISNULL(left_node_) && OB_ISNULL(right_node_)) {
|
|
has_child = false;
|
|
}
|
|
BASE_ADD_LEN(ObPartLocCalcNode);
|
|
OB_UNIS_ADD_LEN(has_child);
|
|
if (has_child) {
|
|
OB_UNIS_ADD_LEN(left_node_->node_type_);
|
|
OB_UNIS_ADD_LEN(right_node_->node_type_);
|
|
len += left_node_->get_serialize_size();
|
|
len += right_node_->get_serialize_size();
|
|
}
|
|
return len;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObPLOrNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool has_child = false;
|
|
BASE_DESER(ObPartLocCalcNode);
|
|
OB_UNIS_DECODE(has_child);
|
|
if (has_child) {
|
|
NodeType left_child_type = INVALID;
|
|
NodeType right_child_type = INVALID;
|
|
OB_UNIS_DECODE(left_child_type);
|
|
OB_UNIS_DECODE(right_child_type);
|
|
ObPartLocCalcNode *left_child = NULL;
|
|
ObPartLocCalcNode *right_child = NULL;
|
|
if (OB_FAIL(create_part_calc_node(allocator_, left_child_type, left_child))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(create_part_calc_node(allocator_, right_child_type, right_child))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(left_child->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to do deserialize", K(ret));
|
|
} else if (OB_FAIL(right_child->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to do deserialize", K(ret));
|
|
} else {
|
|
left_node_ = left_child;
|
|
right_node_ = right_child;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
OB_SERIALIZE_MEMBER(ObPLFuncValueNode::ParamValuePair, param_idx_, obj_value_);
|
|
OB_SERIALIZE_MEMBER(ObPartLocCalcNode, node_type_);
|
|
OB_SERIALIZE_MEMBER((ObPLQueryRangeNode, ObPartLocCalcNode), pre_query_range_);
|
|
|
|
OB_DEF_SERIALIZE(ObPLFuncValueNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
BASE_SER(ObPartLocCalcNode);
|
|
LST_DO_CODE(OB_UNIS_ENCODE,
|
|
vie_,
|
|
param_value_);
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObPLFuncValueNode)
|
|
{
|
|
int64_t len = 0;
|
|
BASE_ADD_LEN(ObPartLocCalcNode);
|
|
LST_DO_CODE(OB_UNIS_ADD_LEN,
|
|
vie_,
|
|
param_value_);
|
|
return len;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObPLFuncValueNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
BASE_DESER(ObPartLocCalcNode);
|
|
OZ (vie_.deserialize(allocator_, buf, data_len, pos));
|
|
OB_UNIS_DECODE(param_value_);
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE(ObPLColumnValueNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
BASE_SER(ObPartLocCalcNode);
|
|
OB_UNIS_ENCODE(vie_);
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObPLColumnValueNode)
|
|
{
|
|
int64_t len = 0;
|
|
BASE_ADD_LEN(ObPartLocCalcNode);
|
|
OB_UNIS_ADD_LEN(vie_);
|
|
return len;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObPLColumnValueNode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
BASE_DESER(ObPartLocCalcNode);
|
|
OZ (vie_.deserialize(allocator_, buf, data_len, pos));
|
|
return ret;
|
|
}
|
|
|
|
int ValueItemExpr::serialize(char *buf, const int64_t buf_len, int64_t &pos) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
OB_UNIS_ENCODE(type_);
|
|
if (CONST_OBJ_TYPE == type_) {
|
|
OB_UNIS_ENCODE(obj_);
|
|
} else if (CONST_EXPR_TYPE == type_) {
|
|
OB_UNIS_ENCODE(*expr_);
|
|
} else if (QUESTMARK_TYPE == type_) {
|
|
OB_UNIS_ENCODE(idx_);
|
|
}
|
|
OB_UNIS_ENCODE(dst_type_);
|
|
if (ob_is_enum_or_set_type(dst_type_)) {
|
|
CK(OB_NOT_NULL(enum_set_values_));
|
|
OB_UNIS_ENCODE_ARRAY(enum_set_values_, enum_set_values_cnt_);
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
int64_t ValueItemExpr::get_serialize_size() const
|
|
{
|
|
int64_t len = 0;
|
|
OB_UNIS_ADD_LEN(type_);
|
|
if (CONST_OBJ_TYPE == type_) {
|
|
OB_UNIS_ADD_LEN(obj_);
|
|
} else if (CONST_EXPR_TYPE == type_) {
|
|
OB_UNIS_ADD_LEN(*expr_);
|
|
} else if (QUESTMARK_TYPE == type_) {
|
|
OB_UNIS_ADD_LEN(idx_);
|
|
}
|
|
OB_UNIS_ADD_LEN(dst_type_);
|
|
if (ob_is_enum_or_set_type(dst_type_)) {
|
|
OB_UNIS_ADD_LEN_ARRAY(enum_set_values_, enum_set_values_cnt_);
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
int ValueItemExpr::deserialize(common::ObIAllocator &allocator, const char *buf,
|
|
const int64_t data_len, int64_t &pos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
OB_UNIS_DECODE(type_);
|
|
if (CONST_OBJ_TYPE == type_) {
|
|
OB_UNIS_DECODE(obj_);
|
|
} else if (CONST_EXPR_TYPE == type_) {
|
|
char *mem = static_cast<char *>(allocator.alloc(sizeof(ObTempExpr)));
|
|
CK(OB_NOT_NULL(mem));
|
|
OX(expr_ = new(mem)ObTempExpr(allocator));
|
|
OB_UNIS_DECODE(*expr_);
|
|
} else if (QUESTMARK_TYPE == type_) {
|
|
OB_UNIS_DECODE(idx_);
|
|
}
|
|
OB_UNIS_DECODE(dst_type_);
|
|
if (ob_is_enum_or_set_type(dst_type_)) {
|
|
OB_UNIS_DECODE(enum_set_values_cnt_);
|
|
if (enum_set_values_cnt_ > 0) {
|
|
enum_set_values_ =
|
|
static_cast<ObString *>(allocator.alloc(sizeof(ObString) * enum_set_values_cnt_));
|
|
CK(OB_NOT_NULL(enum_set_values_));
|
|
OB_UNIS_DECODE_ARRAY(enum_set_values_, enum_set_values_cnt_)
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ValueItemExpr::deep_copy(ObIAllocator &allocator, ValueItemExpr &dst) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
dst = *this;
|
|
if (CONST_OBJ_TYPE == type_) {
|
|
OZ(deep_copy_obj(allocator, obj_, dst.obj_));
|
|
} else if (CONST_EXPR_TYPE == type_) {
|
|
OZ(expr_->deep_copy(allocator, dst.expr_));
|
|
}
|
|
dst.dst_type_ = dst_type_;
|
|
if (ob_is_enum_or_set_type(dst_type_)) {
|
|
dst.enum_set_values_cnt_ = enum_set_values_cnt_;
|
|
dst.enum_set_values_ =
|
|
static_cast<ObString *>(allocator.alloc(sizeof(ObString) * enum_set_values_cnt_));
|
|
CK(OB_NOT_NULL(dst.enum_set_values_));
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < enum_set_values_cnt_; ++i) {
|
|
OZ(ob_write_string(allocator, enum_set_values_[i], dst.enum_set_values_[i]));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE(ObTableLocation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool has_part_expr = (se_part_expr_ != NULL);
|
|
bool has_subpart_expr = (se_subpart_expr_ != NULL);
|
|
bool has_calc_node = (calc_node_ != NULL);
|
|
bool has_gen_col_node = (gen_col_node_ != NULL);
|
|
bool has_subcalc_node = (subcalc_node_ != NULL);
|
|
bool has_sub_gen_col_node = (sub_gen_col_node_ != NULL);
|
|
bool has_gen_col_expr = (NULL != gen_col_node_ || NULL != se_gen_col_expr_);
|
|
bool has_sub_gen_col_expr = (NULL != sub_gen_col_node_ || NULL != se_sub_gen_col_expr_);
|
|
LST_DO_CODE(OB_UNIS_ENCODE,
|
|
loc_meta_,
|
|
stmt_type_,
|
|
is_partitioned_,
|
|
part_level_,
|
|
part_type_,
|
|
subpart_type_,
|
|
has_part_expr,
|
|
has_subpart_expr,
|
|
part_projector_,
|
|
inited_);
|
|
if (OB_SUCC(ret)) {
|
|
LST_DO_CODE(OB_UNIS_ENCODE, is_oracle_temp_table_);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
LST_DO_CODE(OB_UNIS_ENCODE,
|
|
part_get_all_,
|
|
subpart_get_all_,
|
|
is_valid_range_columns_part_range_,
|
|
is_valid_range_columns_subpart_range_,
|
|
has_dynamic_exec_param_,
|
|
has_calc_node,
|
|
has_gen_col_node,
|
|
has_subcalc_node,
|
|
has_sub_gen_col_node);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_calc_node) {
|
|
OB_UNIS_ENCODE(calc_node_->node_type_);
|
|
if (OB_FAIL(calc_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_gen_col_node) {
|
|
OB_UNIS_ENCODE(gen_col_node_->node_type_);
|
|
if (OB_FAIL(gen_col_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_subcalc_node) {
|
|
OB_UNIS_ENCODE(subcalc_node_->node_type_);
|
|
if (OB_FAIL(subcalc_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_sub_gen_col_node) {
|
|
OB_UNIS_ENCODE(sub_gen_col_node_->node_type_);
|
|
if (OB_FAIL(sub_gen_col_node_->serialize(buf, buf_len, pos))) {
|
|
LOG_WARN("fail to serialize calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
OB_UNIS_ENCODE(has_gen_col_expr);
|
|
OB_UNIS_ENCODE(has_sub_gen_col_expr);
|
|
if (has_part_expr) { OB_UNIS_ENCODE(*se_part_expr_);}
|
|
if (has_subpart_expr) { OB_UNIS_ENCODE(*se_subpart_expr_); }
|
|
if (has_gen_col_expr) { OB_UNIS_ENCODE(*se_gen_col_expr_)}
|
|
if (has_sub_gen_col_expr) { OB_UNIS_ENCODE(*se_sub_gen_col_expr_)}
|
|
OB_UNIS_ENCODE(vies_.count());
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < vies_.count(); i++) {
|
|
OZ(vies_.at(i).serialize(buf, buf_len, pos));
|
|
}
|
|
OB_UNIS_ENCODE(sub_vies_.count());
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < vies_.count(); i++) {
|
|
OZ(sub_vies_.at(i).serialize(buf, buf_len, pos));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
OB_UNIS_ENCODE(part_hint_ids_.count());
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_hint_ids_.count(); i++) {
|
|
OB_UNIS_ENCODE(part_hint_ids_.at(i));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
LST_DO_CODE(OB_UNIS_ENCODE,
|
|
is_part_range_get_,
|
|
is_subpart_range_get_);
|
|
}
|
|
OB_UNIS_ENCODE(is_non_partition_optimized_);
|
|
OB_UNIS_ENCODE(tablet_id_);
|
|
OB_UNIS_ENCODE(object_id_);
|
|
OB_UNIS_ENCODE(related_list_);
|
|
OB_UNIS_ENCODE(table_type_);
|
|
OB_UNIS_ENCODE(check_no_partiton_);
|
|
return ret;
|
|
}
|
|
|
|
OB_DEF_SERIALIZE_SIZE(ObTableLocation)
|
|
{
|
|
int64_t len = 0;
|
|
bool has_part_expr = (se_part_expr_ != NULL);
|
|
bool has_subpart_expr = (se_subpart_expr_ != NULL);
|
|
bool has_calc_node = (calc_node_ != NULL);
|
|
bool has_gen_col_node = (gen_col_node_ != NULL);
|
|
bool has_subcalc_node = (subcalc_node_ != NULL);
|
|
bool has_sub_gen_col_node = (sub_gen_col_node_ != NULL);
|
|
bool has_gen_col_expr = (NULL != gen_col_node_ || NULL != se_gen_col_expr_);
|
|
bool has_sub_gen_col_expr = (NULL != sub_gen_col_node_ || NULL != se_sub_gen_col_expr_);
|
|
LST_DO_CODE(OB_UNIS_ADD_LEN,
|
|
loc_meta_,
|
|
stmt_type_,
|
|
is_partitioned_,
|
|
part_level_,
|
|
part_type_,
|
|
subpart_type_,
|
|
has_part_expr,
|
|
has_subpart_expr,
|
|
part_projector_,
|
|
inited_,
|
|
is_oracle_temp_table_,
|
|
part_get_all_,
|
|
subpart_get_all_,
|
|
is_valid_range_columns_part_range_,
|
|
is_valid_range_columns_subpart_range_,
|
|
has_dynamic_exec_param_,
|
|
has_calc_node,
|
|
has_gen_col_node,
|
|
has_subcalc_node,
|
|
has_sub_gen_col_node);
|
|
if (has_calc_node) {
|
|
OB_UNIS_ADD_LEN(calc_node_->node_type_);
|
|
len += calc_node_->get_serialize_size();
|
|
}
|
|
if (has_gen_col_node) {
|
|
OB_UNIS_ADD_LEN(gen_col_node_->node_type_);
|
|
len += gen_col_node_->get_serialize_size();
|
|
}
|
|
if (has_subcalc_node) {
|
|
OB_UNIS_ADD_LEN(subcalc_node_->node_type_);
|
|
len += subcalc_node_->get_serialize_size();
|
|
}
|
|
if (has_sub_gen_col_node) {
|
|
OB_UNIS_ADD_LEN(sub_gen_col_node_->node_type_);
|
|
len += sub_gen_col_node_->get_serialize_size();
|
|
}
|
|
OB_UNIS_ADD_LEN(has_gen_col_expr);
|
|
OB_UNIS_ADD_LEN(has_sub_gen_col_expr);
|
|
if (has_part_expr) { OB_UNIS_ADD_LEN(*se_part_expr_); }
|
|
if (has_subpart_expr) { OB_UNIS_ADD_LEN(*se_subpart_expr_); }
|
|
if (has_gen_col_expr) { OB_UNIS_ADD_LEN(*se_gen_col_expr_); }
|
|
if (has_sub_gen_col_expr) { OB_UNIS_ADD_LEN(*se_sub_gen_col_expr_); }
|
|
OB_UNIS_ADD_LEN(vies_.count());
|
|
for (int64_t i = 0; i < vies_.count(); i++) {
|
|
len += vies_.at(i).get_serialize_size();
|
|
}
|
|
OB_UNIS_ADD_LEN(sub_vies_.count());
|
|
for (int64_t i = 0; i < vies_.count(); i++) {
|
|
len += sub_vies_.at(i).get_serialize_size();
|
|
}
|
|
OB_UNIS_ADD_LEN(part_hint_ids_.count());
|
|
for (int64_t i = 0; i < part_hint_ids_.count(); i++) {
|
|
OB_UNIS_ADD_LEN(part_hint_ids_.at(i));
|
|
}
|
|
LST_DO_CODE(OB_UNIS_ADD_LEN,
|
|
is_part_range_get_,
|
|
is_subpart_range_get_);
|
|
OB_UNIS_ADD_LEN(is_non_partition_optimized_);
|
|
OB_UNIS_ADD_LEN(tablet_id_);
|
|
OB_UNIS_ADD_LEN(object_id_);
|
|
OB_UNIS_ADD_LEN(related_list_);
|
|
OB_UNIS_ADD_LEN(table_type_);
|
|
OB_UNIS_ADD_LEN(check_no_partiton_);
|
|
return len;
|
|
}
|
|
|
|
OB_DEF_DESERIALIZE(ObTableLocation)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool has_part_expr = false;
|
|
bool has_subpart_expr = false;
|
|
bool has_gen_col_expr = false;
|
|
bool has_sub_gen_col_expr = false;
|
|
bool has_calc_node = (calc_node_ != NULL);
|
|
bool has_gen_col_node = (gen_col_node_ != NULL);
|
|
bool has_subcalc_node = (subcalc_node_ != NULL);
|
|
bool has_sub_gen_col_node = (sub_gen_col_node_ != NULL);
|
|
LST_DO_CODE(OB_UNIS_DECODE,
|
|
loc_meta_,
|
|
stmt_type_,
|
|
is_partitioned_,
|
|
part_level_,
|
|
part_type_,
|
|
subpart_type_,
|
|
has_part_expr,
|
|
has_subpart_expr,
|
|
part_projector_,
|
|
inited_);
|
|
if (OB_SUCC(ret)) {
|
|
LST_DO_CODE(OB_UNIS_DECODE, is_oracle_temp_table_);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
LST_DO_CODE(OB_UNIS_DECODE,
|
|
part_get_all_,
|
|
subpart_get_all_,
|
|
is_valid_range_columns_part_range_,
|
|
is_valid_range_columns_subpart_range_,
|
|
has_dynamic_exec_param_,
|
|
has_calc_node,
|
|
has_gen_col_node,
|
|
has_subcalc_node,
|
|
has_sub_gen_col_node);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
calc_nodes_.reset();
|
|
if (has_calc_node) {
|
|
ObPartLocCalcNode::NodeType calc_node_type = ObPartLocCalcNode::INVALID;
|
|
OB_UNIS_DECODE(calc_node_type);
|
|
if (OB_FAIL(ObPartLocCalcNode::create_part_calc_node(allocator_, calc_node_type, calc_node_))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(calc_node_->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to deserialize calc node", K(ret));
|
|
} else if (OB_FAIL(calc_node_->add_part_calc_node(calc_nodes_))) {
|
|
LOG_WARN("fail to add calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_gen_col_node) {
|
|
ObPartLocCalcNode::NodeType gen_col_node_type = ObPartLocCalcNode::INVALID;
|
|
OB_UNIS_DECODE(gen_col_node_type);
|
|
if (OB_FAIL(ObPartLocCalcNode::create_part_calc_node(allocator_, gen_col_node_type, gen_col_node_))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(gen_col_node_->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to deserialize calc node", K(ret));
|
|
} else if (OB_FAIL(gen_col_node_->add_part_calc_node(calc_nodes_))) {
|
|
LOG_WARN("fail to add calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_subcalc_node) {
|
|
ObPartLocCalcNode::NodeType subcalc_node_type = ObPartLocCalcNode::INVALID;
|
|
OB_UNIS_DECODE(subcalc_node_type);
|
|
if (OB_FAIL(ObPartLocCalcNode::create_part_calc_node(allocator_, subcalc_node_type, subcalc_node_))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(subcalc_node_->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to deserialize calc node", K(ret));
|
|
} else if (OB_FAIL(subcalc_node_->add_part_calc_node(calc_nodes_))) {
|
|
LOG_WARN("fail to add calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (has_sub_gen_col_node) {
|
|
ObPartLocCalcNode::NodeType sub_gen_node_type = ObPartLocCalcNode::INVALID;
|
|
OB_UNIS_DECODE(sub_gen_node_type);
|
|
if (OB_FAIL(ObPartLocCalcNode::create_part_calc_node(allocator_, sub_gen_node_type, sub_gen_col_node_))) {
|
|
LOG_WARN("fail to create part calc node", K(ret));
|
|
} else if (OB_FAIL(sub_gen_col_node_->deserialize(buf, data_len, pos))) {
|
|
LOG_WARN("fail to deserialize calc node", K(ret));
|
|
} else if (OB_FAIL(sub_gen_col_node_->add_part_calc_node(calc_nodes_))) {
|
|
LOG_WARN("fail to add calc node", K(ret));
|
|
}
|
|
}
|
|
}
|
|
OB_UNIS_DECODE(has_gen_col_expr);
|
|
OB_UNIS_DECODE(has_sub_gen_col_expr);
|
|
if (OB_SUCC(ret)) {
|
|
if (has_part_expr) {
|
|
char *mem = static_cast<char *>(allocator_.alloc(sizeof(ObTempExpr)));
|
|
CK(OB_NOT_NULL(mem));
|
|
OX(se_part_expr_ = new(mem)ObTempExpr(allocator_));
|
|
OB_UNIS_DECODE(*se_part_expr_);
|
|
}
|
|
if (OB_SUCC(ret) && has_subpart_expr) {
|
|
char *mem = static_cast<char *>(allocator_.alloc(sizeof(ObTempExpr)));
|
|
CK(OB_NOT_NULL(mem));
|
|
OX(se_subpart_expr_ = new(mem)ObTempExpr(allocator_));
|
|
OB_UNIS_DECODE(*se_subpart_expr_);
|
|
}
|
|
if (OB_SUCC(ret) && has_gen_col_expr) {
|
|
char *mem = static_cast<char *>(allocator_.alloc(sizeof(ObTempExpr)));
|
|
CK(OB_NOT_NULL(mem));
|
|
OX(se_gen_col_expr_ = new(mem)ObTempExpr(allocator_));
|
|
OB_UNIS_DECODE(*se_gen_col_expr_);
|
|
}
|
|
if (OB_SUCC(ret) && has_sub_gen_col_expr) {
|
|
char *mem = static_cast<char *>(allocator_.alloc(sizeof(ObTempExpr)));
|
|
CK(OB_NOT_NULL(mem));
|
|
OX(se_sub_gen_col_expr_ = new(mem)ObTempExpr(allocator_));
|
|
OB_UNIS_DECODE(*se_sub_gen_col_expr_);
|
|
}
|
|
int64_t vie_count = 0;
|
|
OB_UNIS_DECODE(vie_count);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < vie_count; i++) {
|
|
ValueItemExpr vie;
|
|
OZ(vie.deserialize(allocator_, buf, data_len, pos));
|
|
OZ(vies_.push_back(vie));
|
|
}
|
|
int64_t sub_vie_count = 0;
|
|
OB_UNIS_DECODE(sub_vie_count);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < sub_vie_count; i++) {
|
|
ValueItemExpr vie;
|
|
OZ(vie.deserialize(allocator_, buf, data_len, pos));
|
|
OZ(sub_vies_.push_back(vie));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
int64_t part_hint_ids_count = 0;
|
|
OB_UNIS_DECODE(part_hint_ids_count);
|
|
OZ(part_hint_ids_.init(part_hint_ids_count));
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_hint_ids_count; i++) {
|
|
ObObjectID part_hint_id;
|
|
OB_UNIS_DECODE(part_hint_id);
|
|
OZ(part_hint_ids_.push_back(part_hint_id));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
LST_DO_CODE(OB_UNIS_DECODE,
|
|
is_part_range_get_,
|
|
is_subpart_range_get_);
|
|
}
|
|
OB_UNIS_DECODE(is_non_partition_optimized_);
|
|
OB_UNIS_DECODE(tablet_id_);
|
|
OB_UNIS_DECODE(object_id_);
|
|
OB_UNIS_DECODE(related_list_);
|
|
OB_UNIS_DECODE(table_type_);
|
|
OB_UNIS_DECODE(check_no_partiton_);
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_partition_ids_by_range(ObExecContext &exec_ctx,
|
|
const ObNewRange *part_range,
|
|
const ObNewRange *gen_range,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
const ObIArray<ObObjectID> *level_one_part_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPartLocCalcNode *gen_col_node = NULL == level_one_part_ids ? gen_col_node_ : sub_gen_col_node_;
|
|
ObTempExpr *se_gen_col_expr = NULL;
|
|
se_gen_col_expr = NULL == level_one_part_ids ? se_gen_col_expr_: se_sub_gen_col_expr_;
|
|
ObSEArray<ObObjectID, 5> gen_part_ids;
|
|
ObSEArray<ObTabletID, 5> gen_tablet_ids;
|
|
bool all_part_by_part_range = false; // 通过part range计算出的partition ids是表的全部partition
|
|
bool all_part_by_gen_range = false; // 通过gen range计算出的partition ids是表的全部partition
|
|
ObDASTabletMapper tablet_mapper;
|
|
if (OB_UNLIKELY(!inited_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("ObTableLocation not inited", K(ret));
|
|
} else if (is_non_partition_optimized_
|
|
&& FALSE_IT(tablet_mapper.set_non_partitioned_table_ids(
|
|
tablet_id_, object_id_, &related_list_))) {
|
|
} else if (OB_FAIL(exec_ctx.get_das_ctx().get_das_tablet_mapper(
|
|
loc_meta_.ref_table_id_, tablet_mapper, &loc_meta_.related_table_ids_))) {
|
|
LOG_WARN("fail to get das tablet mapper", K(ret));
|
|
} else if (!is_partitioned_) {
|
|
OZ (tablet_mapper.get_non_partition_tablet_id(tablet_ids, partition_ids));
|
|
} else {
|
|
// 计算part range涉及到的partition ids
|
|
if (NULL == part_range) {
|
|
all_part_by_part_range = true;
|
|
} else if (OB_FAIL(calc_partition_ids_by_range(exec_ctx, tablet_mapper, part_range,
|
|
tablet_ids, partition_ids,
|
|
all_part_by_part_range, level_one_part_ids,
|
|
NULL))) {
|
|
LOG_WARN("Failed to calc partitoin ids by calc node", K(ret));
|
|
}
|
|
// 计算gen range涉及到的partition ids
|
|
if (OB_SUCC(ret)) {
|
|
if (NULL == gen_range || OB_ISNULL(gen_col_node)
|
|
|| OB_ISNULL(se_gen_col_expr)) {
|
|
all_part_by_gen_range = true;
|
|
} else if (OB_FAIL(calc_partition_ids_by_range(exec_ctx, tablet_mapper, gen_range,
|
|
gen_tablet_ids, gen_part_ids,
|
|
all_part_by_gen_range, level_one_part_ids,
|
|
se_gen_col_expr))) {
|
|
LOG_WARN("Failed to calcl partition ids by gen col node", K(ret));
|
|
}
|
|
}
|
|
|
|
// 通过part range和gen range分别计算出了两组partition ids, 取两者的交集
|
|
if (OB_SUCC(ret)) {
|
|
if (!all_part_by_part_range && !all_part_by_gen_range) {
|
|
OZ (intersect_partition_ids(gen_part_ids, partition_ids));
|
|
OZ (intersect_partition_ids(gen_tablet_ids, tablet_ids));
|
|
} else if (!all_part_by_part_range && all_part_by_gen_range) {
|
|
// do nothing
|
|
} else if (all_part_by_part_range && !all_part_by_gen_range) {
|
|
OZ (append(partition_ids, gen_part_ids));
|
|
OZ (append(tablet_ids, gen_tablet_ids));
|
|
} else if (OB_FAIL(get_all_part_ids(tablet_mapper, tablet_ids,
|
|
partition_ids, level_one_part_ids))) {
|
|
LOG_WARN("Get all part ids error", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_partition_ids_by_range(ObExecContext &exec_ctx,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
const ObNewRange *range,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids,
|
|
bool &all_part,
|
|
const ObIArray<ObObjectID> *part_ids,
|
|
const ObTempExpr *se_gen_col_expr) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
all_part = false;
|
|
ObSEArray<ObNewRange *, 1> dummy_query_ranges;
|
|
if (OB_ISNULL(range)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get null ObNewRange", K(ret));
|
|
} else if (range->empty()) {
|
|
//do nothing. partition ids will be empty
|
|
} else if (OB_FAIL(dummy_query_ranges.push_back(const_cast<ObNewRange *>(range)))) {
|
|
LOG_WARN("failed to push back query range", K(ret));
|
|
} else if (OB_FAIL(calc_partition_ids_by_ranges(exec_ctx,
|
|
tablet_mapper,
|
|
dummy_query_ranges,
|
|
range->is_single_rowkey(),
|
|
tablet_ids,
|
|
partition_ids,
|
|
all_part,
|
|
part_ids,
|
|
se_gen_col_expr))) {
|
|
LOG_WARN("Failed to get partition ids", K(ret), K(loc_meta_));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableLocation::generate_row_desc_from_row_desc(const ObDMLStmt &stmt,
|
|
const uint64_t data_table_id,
|
|
ObRawExprFactory &expr_factory,
|
|
const RowDesc &input_row_desc,
|
|
RowDesc &row_desc)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObColumnRefRawExpr *col_expr = NULL;
|
|
if (OB_FAIL(row_desc.init())) {
|
|
LOG_WARN("Failed to init row desc", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < input_row_desc.get_column_num(); ++i) {
|
|
ObRawExpr *expr = input_row_desc.get_column(i);
|
|
if (OB_ISNULL(expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get null expr", K(ret));
|
|
} else if (OB_LIKELY(expr->is_column_ref_expr())) {
|
|
uint64_t column_id = static_cast<ObColumnRefRawExpr *>(expr)->get_column_id();
|
|
col_expr = stmt.get_column_expr_by_id(data_table_id, column_id);
|
|
if (OB_ISNULL(col_expr)) {
|
|
// 没有用到的column, 计算part expr时一定用不到, mock一个column expr占位
|
|
if (OB_FAIL(expr_factory.create_raw_expr(T_REF_COLUMN, col_expr))) {
|
|
LOG_WARN("create mock rowkey column expr failed", K(ret));
|
|
} else if (OB_FAIL(row_desc.add_column(col_expr))) {
|
|
LOG_WARN("add rowkey column expr to row desc failed", K(ret));
|
|
}
|
|
} else if (OB_FAIL(row_desc.add_column(col_expr))) {
|
|
LOG_WARN("add rowkey column expr to row desc failed", K(ret));
|
|
}
|
|
} else {
|
|
// 不是column expr, 计算part expr时一定用不到, mock一个column expr占位
|
|
if (OB_FAIL(expr_factory.create_raw_expr(T_REF_COLUMN, col_expr))) {
|
|
LOG_WARN("create mock rowkey column expr failed", K(ret));
|
|
} else if (OB_FAIL(row_desc.add_column(col_expr))) {
|
|
LOG_WARN("add rowkey column expr to row desc failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::can_get_part_by_range_for_range_columns(const ObRawExpr *part_expr,
|
|
bool &is_valid) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_valid = false;
|
|
if (OB_ISNULL(part_expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret));
|
|
} else if (part_expr->is_column_ref_expr()) {
|
|
is_valid = true;
|
|
} else if (T_OP_ROW == part_expr->get_expr_type()) {
|
|
const ObRawExpr *col_expr = NULL;
|
|
is_valid = true;
|
|
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < part_expr->get_param_count(); ++i) {
|
|
if (OB_ISNULL(col_expr = part_expr->get_param_expr(i))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret));
|
|
} else if (!col_expr->is_column_ref_expr()) {
|
|
is_valid = false;
|
|
}
|
|
}
|
|
} else {
|
|
is_valid = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int ObTableLocation::can_get_part_by_range_for_temporal_column(const ObRawExpr *part_expr,
|
|
bool &is_valid) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
is_valid = false;
|
|
if (OB_ISNULL(part_expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret));
|
|
} else if (lib::is_oracle_mode()) {
|
|
// do nothing
|
|
} else {
|
|
switch (part_expr->get_expr_type()) {
|
|
case T_FUN_SYS_TO_DAYS:
|
|
case T_FUN_SYS_TO_SECONDS:
|
|
case T_FUN_SYS_YEAR: {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_expr->get_param_count(); ++i) {
|
|
const ObRawExpr *sub_expr = part_expr->get_param_expr(i);
|
|
const ObRawExpr *real_sub_expr = NULL;
|
|
if (OB_FAIL(ObRawExprUtils::get_real_expr_without_cast(sub_expr, real_sub_expr))) {
|
|
LOG_WARN("fail to get real expr", K(ret));
|
|
} else if (real_sub_expr->is_column_ref_expr() &&
|
|
(ObDateType == real_sub_expr->get_result_type().get_type() ||
|
|
ObDateTimeType == real_sub_expr->get_result_type().get_type())) {
|
|
is_valid = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case T_FUN_SYS_UNIX_TIMESTAMP: {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < part_expr->get_param_count(); ++i) {
|
|
const ObRawExpr *sub_expr = part_expr->get_param_expr(i);
|
|
const ObRawExpr *real_sub_expr = NULL;
|
|
if (OB_FAIL(ObRawExprUtils::get_real_expr_without_cast(sub_expr, real_sub_expr))) {
|
|
LOG_WARN("fail to get real expr", K(ret));
|
|
} else if (real_sub_expr->is_column_ref_expr() &&
|
|
ObTimestampType == real_sub_expr->get_result_type().get_type()) {
|
|
is_valid = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
is_valid = false;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::calc_range_by_part_expr(ObExecContext &exec_ctx,
|
|
const ObIArray<ObNewRange*> &ranges,
|
|
const ObIArray<ObObjectID> *part_ids,
|
|
ObIAllocator &allocator,
|
|
ObIArray<ObNewRange*> &new_ranges,
|
|
bool &is_all_single_value_ranges) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObTempExpr *se_expr = NULL;
|
|
se_expr = NULL == part_ids ? se_part_expr_ : se_subpart_expr_;
|
|
is_all_single_value_ranges = true;
|
|
for (int64 i = 0; OB_SUCC(ret) && i < ranges.count(); ++i) {
|
|
ObNewRange *range = ranges.at(i);
|
|
ObNewRange *new_range = NULL;
|
|
if (OB_ISNULL(range)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid range", K(ret));
|
|
} else if (OB_ISNULL(new_range = static_cast<ObNewRange *>(allocator.alloc(sizeof(ObNewRange))))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("alloc memory failed", K(ret));
|
|
} else {
|
|
new(new_range) ObNewRange();
|
|
new_range->table_id_ = range->table_id_;
|
|
// the range after calc is always close even though the original range is open
|
|
new_range->border_flag_.set_inclusive_start();
|
|
new_range->border_flag_.set_inclusive_end();
|
|
if (range->start_key_.is_min_row()) {
|
|
new_range->start_key_.set_min_row();
|
|
} else {
|
|
ObNewRow input_row;
|
|
ObObj *func_result = NULL;
|
|
input_row.cells_ = const_cast<ObObj *>(range->start_key_.get_obj_ptr());
|
|
input_row.count_ = (range->start_key_.get_obj_cnt());
|
|
OV (OB_NOT_NULL(func_result = static_cast<ObObj *>(allocator.alloc(sizeof(ObObj)))),
|
|
OB_ALLOCATE_MEMORY_FAILED);
|
|
OZ(se_expr->eval(exec_ctx, input_row, *func_result), input_row, loc_meta_);
|
|
OX(new_range->start_key_.assign(func_result, 1));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (range->end_key_.is_max_row()) {
|
|
new_range->end_key_.set_max_row();
|
|
} else {
|
|
ObNewRow input_row;
|
|
ObObj *func_result = NULL;
|
|
input_row.cells_ = const_cast<ObObj *>(range->end_key_.get_obj_ptr());
|
|
input_row.count_ = (range->end_key_.get_obj_cnt());
|
|
OV (OB_NOT_NULL(func_result = static_cast<ObObj *>(allocator.alloc(sizeof(ObObj)))),
|
|
OB_ALLOCATE_MEMORY_FAILED);
|
|
OZ(se_expr->eval(exec_ctx, input_row, *func_result), input_row, loc_meta_);
|
|
OX(new_range->end_key_.assign(func_result, 1));
|
|
}
|
|
OZ(new_ranges.push_back(new_range));
|
|
if (OB_SUCC(ret) && is_all_single_value_ranges) {
|
|
is_all_single_value_ranges = is_all_single_value_ranges && new_range->is_single_rowkey();
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::pruning_single_partition(int64_t partition_id,
|
|
ObExecContext &exec_ctx,
|
|
bool &pruning,
|
|
common::ObIArray<int64_t> &partition_ids)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(partition_id);
|
|
UNUSED(exec_ctx);
|
|
UNUSED(partition_ids);
|
|
pruning = false;
|
|
// ObTaskExecutorCtx &task_exec_ctx = exec_ctx.get_task_exec_ctx();
|
|
// ObMultiVersionSchemaService *schema_service = NULL;
|
|
// ObPhysicalPlanCtx *plan_ctx = NULL;
|
|
// ObSchemaGetterGuard schema_guard;
|
|
// partition_ids.reset();
|
|
// if (OB_ISNULL(exec_ctx.get_my_session())) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("session is null", K(ret));
|
|
// } else if (OB_ISNULL(schema_service = task_exec_ctx.schema_service_)) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("schema_service is null", K(ret));
|
|
// } else if (OB_FAIL(schema_service->get_tenant_schema_guard(
|
|
// exec_ctx.get_my_session()->get_effective_tenant_id(),
|
|
// schema_guard))) {
|
|
// LOG_WARN("failed to get schema guard", K(ret));
|
|
// } else if (OB_ISNULL(plan_ctx = exec_ctx.get_physical_plan_ctx())) {
|
|
// ret = OB_ERR_UNEXPECTED;
|
|
// LOG_WARN("plan_ctx is null", K(ret));
|
|
// } else {
|
|
// ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(exec_ctx.get_my_session());
|
|
// if (OB_FAIL(calculate_partition_ids(exec_ctx, &schema_guard, plan_ctx->get_param_store(),
|
|
// partition_ids, dtc_params))) {
|
|
// LOG_WARN("fail to calculate_partition_ids", K(ret));
|
|
// } else {
|
|
// pruning = true;
|
|
// for (int i = 0; i < partition_ids.count() && OB_SUCC(ret); ++i) {
|
|
// if (partition_ids.at(i) == partition_id) {
|
|
// pruning = false;
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::try_split_integer_range(const common::ObIArray<common::ObNewRange*> &ranges,
|
|
common::ObIAllocator &allocator,
|
|
common::ObIArray<common::ObNewRange*> &new_ranges,
|
|
bool &all_part) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const static int64_t MAX_INTEGER_RANGE_SPLITE_COUNT = 32;
|
|
uint64_t table_id = OB_INVALID_ID;
|
|
ObObjType obj_type = ObMaxType;
|
|
ObSEArray<std::pair<int64_t, int64_t>, 2> int_ranges;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !all_part && i < ranges.count(); ++i) {
|
|
ObNewRange *range = ranges.at(i);
|
|
if (OB_ISNULL(range)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid range", K(ret));
|
|
} else if (OB_UNLIKELY(!range->start_key_.is_valid())
|
|
|| OB_UNLIKELY(!range->end_key_.is_valid())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid rowkey");
|
|
} else if (range->start_key_.is_min_row() || range->end_key_.is_max_row()) {
|
|
all_part = true;
|
|
} else if (range->start_key_.get_obj_cnt() != 1 || range->end_key_.get_obj_cnt() != 1) {
|
|
all_part = true;
|
|
} else {
|
|
ObObj &start_obj = range->start_key_.get_obj_ptr()[0];
|
|
ObObj &end_obj = range->end_key_.get_obj_ptr()[0];
|
|
table_id = range->table_id_;
|
|
if (!start_obj.is_integer_type() || !end_obj.is_integer_type()) {
|
|
all_part = true;
|
|
} else {
|
|
int64_t start_val = start_obj.get_int();
|
|
int64_t end_val = end_obj.get_int();
|
|
obj_type = start_obj.get_type();
|
|
if (!range->border_flag_.inclusive_start()) {
|
|
start_val++;
|
|
}
|
|
if (!range->border_flag_.inclusive_end()) {
|
|
end_val--;
|
|
}
|
|
if (end_val - start_val >= MAX_INTEGER_RANGE_SPLITE_COUNT || end_val - start_val < 0) {
|
|
all_part = true;
|
|
} else if (OB_FAIL(int_ranges.push_back(std::pair<int64_t, int64_t>(start_val, end_val)))) {
|
|
LOG_WARN("fail to push back integer range", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && !all_part && i < int_ranges.count(); ++i) {
|
|
int64_t start_val = int_ranges.at(i).first;
|
|
int64_t end_val = int_ranges.at(i).second;
|
|
for (int64_t obj_val = start_val; OB_SUCC(ret) && obj_val <= end_val; ++obj_val) {
|
|
ObNewRange *new_range = static_cast<ObNewRange *>(allocator.alloc(sizeof(ObNewRange)));
|
|
ObObj *obj = NULL;
|
|
if (OB_ISNULL(new_range)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("alloc memory failed", K(ret));
|
|
} else if (OB_ISNULL(obj = static_cast<ObObj *>(allocator.alloc(sizeof(ObObj))))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_ERROR("alloc memory failed", K(ret));
|
|
} else {
|
|
new(new_range) ObNewRange();
|
|
obj->set_type(obj_type);
|
|
obj->set_int_value(obj_val);
|
|
new_range->table_id_ = table_id;
|
|
new_range->border_flag_.set_inclusive_start();
|
|
new_range->border_flag_.set_inclusive_end();
|
|
new_range->start_key_.assign(obj, 1);
|
|
new_range->end_key_.assign(obj, 1);
|
|
OZ(new_ranges.push_back(new_range));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_full_leader_table_loc(ObDASLocationRouter &loc_router,
|
|
ObIAllocator &allocator,
|
|
uint64_t tenant_id,
|
|
uint64_t table_id,
|
|
uint64_t ref_table_id,
|
|
ObDASTableLoc *&table_loc)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObTableSchema *table_schema = NULL;
|
|
ObSEArray<ObTabletID, 4> tablet_ids;
|
|
ObSEArray<ObObjectID, 4> partition_ids;
|
|
ObSEArray<ObObjectID, 4> first_level_part_ids;
|
|
ObSchemaGetterGuard schema_guard;
|
|
OZ(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, schema_guard));
|
|
OZ(schema_guard.get_table_schema(tenant_id, ref_table_id, table_schema));
|
|
if (OB_ISNULL(table_schema)) {
|
|
ret = OB_SCHEMA_ERROR;
|
|
LOG_WARN("table schema is null", K(ret), K(table_id), K(tenant_id), K(ref_table_id));
|
|
} else {
|
|
OZ(table_schema->get_all_tablet_and_object_ids(tablet_ids, partition_ids, &first_level_part_ids));
|
|
CK(table_schema->has_tablet());
|
|
CK(tablet_ids.count() == partition_ids.count() && tablet_ids.count() == first_level_part_ids.count());
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
ObDASTableLocMeta *loc_meta = NULL;
|
|
char *table_buf = static_cast<char*>(allocator.alloc(sizeof(ObDASTableLoc)
|
|
+ sizeof(ObDASTableLocMeta)));
|
|
if (OB_ISNULL(table_buf)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("fail to alloc memory", K(ret));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
table_loc = new(table_buf) ObDASTableLoc(allocator);
|
|
loc_meta = new(table_buf+sizeof(ObDASTableLoc)) ObDASTableLocMeta(allocator);
|
|
loc_meta->table_loc_id_ = table_id;
|
|
loc_meta->ref_table_id_ = ref_table_id;
|
|
loc_meta->select_leader_ = true;
|
|
table_loc->loc_meta_ = loc_meta;
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < tablet_ids.count(); i++) {
|
|
ObDASTabletLoc *tablet_loc = NULL;
|
|
void *tablet_buf = allocator.alloc(sizeof(ObDASTabletLoc));
|
|
if (OB_ISNULL(tablet_buf)) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("fail to alloc memory", K(ret));
|
|
}
|
|
OX(tablet_loc = new(tablet_buf) ObDASTabletLoc());
|
|
OX(tablet_loc->loc_meta_ = loc_meta);
|
|
OX(tablet_loc->partition_id_ = partition_ids.at(i));
|
|
OX(tablet_loc->first_level_part_id_ = first_level_part_ids.at(i));
|
|
OZ(loc_router.nonblock_get_leader(tenant_id, tablet_ids.at(i), *tablet_loc));
|
|
OZ(table_loc->add_tablet_loc(tablet_loc));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::get_tablet_and_object_id_with_phy_rowid(ObNewRange &range,
|
|
ObDASTabletMapper &tablet_mapper,
|
|
ObIArray<ObTabletID> &tablet_ids,
|
|
ObIArray<ObObjectID> &partition_ids) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObTableSchema *table_schema = NULL;
|
|
if (OB_ISNULL(table_schema = tablet_mapper.get_table_schema()) ||
|
|
OB_UNLIKELY(!range.is_physical_rowid_range_ || range.start_key_.get_obj_cnt() < 1)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected error", K(ret), K(range), K(range.start_key_.get_obj_cnt()),
|
|
K(range.is_physical_rowid_range_), K(table_schema),
|
|
K(range.start_key_.get_obj_ptr()));
|
|
} else if (range.start_key_.get_obj_ptr()[0].is_null()) {
|
|
//do nothing
|
|
} else if (OB_UNLIKELY(!range.start_key_.get_obj_ptr()[0].get_urowid().is_physical_rowid())) {
|
|
ret = OB_INVALID_ROWID;
|
|
LOG_WARN("get invalid rowid", K(range.start_key_.get_obj_ptr()[0].get_urowid()), K(ret));
|
|
} else {
|
|
ObTabletID tablet_id;
|
|
ObSEArray<ObTabletID, 4> all_tablet_ids;
|
|
ObSEArray<ObTabletID, 4> all_index_tablet_ids;
|
|
ObSEArray<ObObjectID, 4> all_partition_ids;
|
|
ObSEArray<ObObjectID, 4> all_first_level_part_ids;
|
|
ObSEArray<ObObjectID, 4> all_index_partition_ids;
|
|
ObSEArray<ObObjectID, 4> all_index_first_level_part_ids;
|
|
bool is_index_table = table_schema->is_index_table();
|
|
ObURowIDData urowid_data = range.start_key_.get_obj_ptr()[0].get_urowid();
|
|
if (OB_FAIL(urowid_data.get_tablet_id_for_heap_organized_table(tablet_id))) {
|
|
LOG_WARN("failed to get tablet id from rowid", K(ret));
|
|
} else if (is_index_table) {
|
|
const ObTableSchema *data_table_schema = NULL;
|
|
ObSchemaGetterGuard *guard = tablet_mapper.get_related_table_info().guard_;
|
|
if (OB_ISNULL(guard)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected error", K(guard), K(ret));
|
|
} else if (OB_FAIL(guard->get_table_schema(table_schema->get_tenant_id(),
|
|
table_schema->get_data_table_id(),
|
|
data_table_schema))) {
|
|
LOG_WARN("fail to get simple table schema", KR(ret), K(table_schema->get_data_table_id()));
|
|
} else if (OB_ISNULL(data_table_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected error", K(ret), K(table_schema->get_data_table_id()));
|
|
} else if (OB_FAIL(data_table_schema->get_all_tablet_and_object_ids(all_tablet_ids,
|
|
all_partition_ids,
|
|
&all_first_level_part_ids))) {
|
|
LOG_WARN("failed to get all tablet and object ids", K(ret));
|
|
} else if (OB_FAIL(table_schema->get_all_tablet_and_object_ids(all_index_tablet_ids,
|
|
all_index_partition_ids,
|
|
&all_index_first_level_part_ids))) {
|
|
LOG_WARN("failed to get all tablet and object ids", K(ret));
|
|
} else {/*do nothing*/}
|
|
} else if (OB_FAIL(table_schema->get_all_tablet_and_object_ids(all_tablet_ids,
|
|
all_partition_ids,
|
|
&all_first_level_part_ids))) {
|
|
LOG_WARN("failed to get all tablet and object ids", K(ret));
|
|
} else {/*do nothing*/}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_UNLIKELY(all_tablet_ids.count() != all_partition_ids.count() ||
|
|
all_tablet_ids.count() != all_first_level_part_ids.count() ||
|
|
all_index_tablet_ids.count() != all_index_partition_ids.count() ||
|
|
all_index_tablet_ids.count() != all_index_first_level_part_ids.count() ||
|
|
(is_index_table && all_tablet_ids.count() != all_index_tablet_ids.count()))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected error", K(ret), K(all_tablet_ids), K(all_partition_ids),
|
|
K(is_index_table), K(all_index_tablet_ids), K(all_index_partition_ids));
|
|
} else {
|
|
bool find_it = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !find_it && i < all_tablet_ids.count(); ++i) {
|
|
if (tablet_id == all_tablet_ids.at(i)) {
|
|
ObObjectID partition_id = !is_index_table ? all_partition_ids.at(i) : all_index_partition_ids.at(i);
|
|
ObObjectID first_level_part_id = !is_index_table ? all_first_level_part_ids.at(i) : all_index_first_level_part_ids.at(i);
|
|
if (OB_FAIL(tablet_ids.push_back(!is_index_table ? all_tablet_ids.at(i) : all_index_tablet_ids.at(i)))) {
|
|
LOG_WARN("failed to add tablet id", K(ret), K(all_tablet_ids.at(i)));
|
|
} else if (OB_FAIL(partition_ids.push_back(partition_id))) {
|
|
LOG_WARN("failed to push back", K(ret), K(all_partition_ids.at(i)));
|
|
} else if (PARTITION_LEVEL_TWO == part_level_ &&
|
|
OB_FAIL(tablet_mapper.set_partition_id_map(first_level_part_id, partition_id))) {
|
|
LOG_WARN("failed to set partition id map", K(first_level_part_id), K(partition_id));
|
|
} else if (OB_FAIL(fill_related_tablet_and_object_ids(tablet_mapper,
|
|
table_schema->get_tenant_id(),
|
|
!is_index_table ? all_tablet_ids.at(i) : all_index_tablet_ids.at(i),
|
|
i))) {
|
|
LOG_WARN("failed to fill related tablet and object ids", K(ret));
|
|
} else {
|
|
find_it = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LOG_TRACE("get tablet and object id with phy rowid", K(range), K(tablet_id), K(all_tablet_ids),
|
|
K(all_partition_ids), K(all_index_tablet_ids), K(all_index_partition_ids), K(is_index_table),
|
|
K(tablet_ids), K(partition_ids));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObTableLocation::fill_related_tablet_and_object_ids(ObDASTabletMapper &tablet_mapper,
|
|
const uint64_t tenant_id,
|
|
ObTabletID src_tablet_id,
|
|
const int64_t idx) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
share::schema::RelatedTableInfo &related_table = tablet_mapper.get_related_table_info();
|
|
if (related_table.related_tids_ != NULL && !related_table.related_tids_->empty()) {
|
|
ObSchemaGetterGuard *guard = related_table.guard_;
|
|
if (OB_ISNULL(guard) || OB_ISNULL(related_table.related_map_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret), K(guard), K(related_table.related_map_));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < related_table.related_tids_->count(); i++) {
|
|
const uint64_t related_table_id = related_table.related_tids_->at(i);
|
|
ObSEArray<ObTabletID, 4> all_related_tablet_ids;
|
|
ObSEArray<ObObjectID, 4> all_partition_ids;
|
|
ObSEArray<ObObjectID, 4> all_first_level_part_ids;
|
|
const ObTableSchema *related_schema = NULL;
|
|
if (OB_FAIL(guard->get_table_schema(tenant_id, related_table_id, related_schema))) {
|
|
LOG_WARN("fail to get simple table schema", KR(ret), K(tenant_id), K(related_table_id));
|
|
} else if (OB_ISNULL(related_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected error", K(ret), K(tenant_id), K(related_table_id));
|
|
} else if (OB_FAIL(related_schema->get_all_tablet_and_object_ids(all_related_tablet_ids,
|
|
all_partition_ids,
|
|
&all_first_level_part_ids))) {
|
|
LOG_WARN("failed to get all tablet and object ids", K(ret));
|
|
} else if (OB_UNLIKELY(idx < 0 || idx >= all_related_tablet_ids.count() ||
|
|
all_related_tablet_ids.count() != all_partition_ids.count() ||
|
|
all_related_tablet_ids.count() != all_first_level_part_ids.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected error", K(idx), K(all_related_tablet_ids),
|
|
K(all_partition_ids), K(all_first_level_part_ids));
|
|
} else if (OB_FAIL(related_table.related_map_->add_related_tablet_id(src_tablet_id,
|
|
related_table_id,
|
|
all_related_tablet_ids.at(idx),
|
|
all_partition_ids.at(idx),
|
|
all_first_level_part_ids.at(idx)))) {
|
|
LOG_WARN("fail to add related tablet info", K(ret), K(src_tablet_id), K(related_table_id),
|
|
K(all_related_tablet_ids.at(idx)), K(all_partition_ids.at(idx)), K(all_first_level_part_ids.at(idx)));
|
|
} else {
|
|
LOG_TRACE("succ to add related tablet info", K(ret), K(src_tablet_id), K(related_table_id),
|
|
K(all_related_tablet_ids.at(idx)), K(all_partition_ids.at(idx)), K(all_first_level_part_ids.at(idx)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|