patch 4.0
This commit is contained in:
@ -15,18 +15,20 @@
|
||||
#include "sql/engine/basic/ob_expr_values_op.h"
|
||||
#include "sql/engine/expr/ob_expr_column_conv.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "sql/engine/ob_phy_operator.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr_util.h"
|
||||
#include "sql/engine/expr/ob_expr_type_to_str.h"
|
||||
#include "sql/engine/px/ob_dfo.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql {
|
||||
namespace sql
|
||||
{
|
||||
|
||||
OB_SERIALIZE_MEMBER(ObExprValuesOpInput, partition_id_values_);
|
||||
|
||||
int ObExprValuesSpec::serialize(char* buf, int64_t buf_len, int64_t& pos, ObPhyOpSeriCtx& seri_ctx) const
|
||||
int ObExprValuesSpec::serialize(char *buf,
|
||||
int64_t buf_len,
|
||||
int64_t &pos,
|
||||
ObPhyOpSeriCtx &seri_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t len = get_serialize_size_(seri_ctx);
|
||||
@ -36,14 +38,14 @@ int ObExprValuesSpec::serialize(char* buf, int64_t buf_len, int64_t& pos, ObPhyO
|
||||
if (OB_FAIL(ObOpSpec::serialize(buf, buf_len, pos))) {
|
||||
LOG_WARN("serialize physical operator failed", K(ret));
|
||||
} else {
|
||||
const ObIArray<int64_t>* row_id_list = static_cast<const ObIArray<int64_t>*>(seri_ctx.row_id_list_);
|
||||
const ObIArray<int64_t> *row_id_list = static_cast<const ObIArray<int64_t> *>(
|
||||
seri_ctx.row_id_list_);
|
||||
int64_t col_num = get_output_count();
|
||||
if (row_id_list != NULL) {
|
||||
int64_t value_count = col_num * row_id_list->count();
|
||||
OB_UNIS_ENCODE(value_count);
|
||||
if (OB_SUCC(ret)) {
|
||||
ARRAY_FOREACH(*row_id_list, idx)
|
||||
{
|
||||
ARRAY_FOREACH(*row_id_list, idx) {
|
||||
int64_t start_idx = row_id_list->at(idx) * col_num;
|
||||
int64_t end_idx = start_idx + col_num;
|
||||
for (int64_t i = start_idx; OB_SUCC(ret) && i < end_idx; ++i) {
|
||||
@ -51,17 +53,18 @@ int ObExprValuesSpec::serialize(char* buf, int64_t buf_len, int64_t& pos, ObPhyO
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (OB_NOT_NULL(seri_ctx.exec_ctx_) && !seri_ctx.exec_ctx_->get_row_id_list_array().empty()) {
|
||||
} else if (OB_NOT_NULL(seri_ctx.exec_ctx_) &&
|
||||
!seri_ctx.exec_ctx_->get_row_id_list_array().empty()) {
|
||||
int64_t value_count = seri_ctx.exec_ctx_->get_row_id_list_total_count() * col_num;
|
||||
OB_UNIS_ENCODE(value_count);
|
||||
for (int array_idx = 0; OB_SUCC(ret) && array_idx < seri_ctx.exec_ctx_->get_row_id_list_array().count();
|
||||
++array_idx) {
|
||||
for (int array_idx = 0; OB_SUCC(ret) &&
|
||||
array_idx < seri_ctx.exec_ctx_->get_row_id_list_array().count();
|
||||
++array_idx) {
|
||||
if (OB_ISNULL(row_id_list = seri_ctx.exec_ctx_->get_row_id_list_array().at(array_idx))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("row id list is null", K(ret));
|
||||
} else {
|
||||
ARRAY_FOREACH(*row_id_list, idx)
|
||||
{
|
||||
ARRAY_FOREACH(*row_id_list, idx) {
|
||||
int64_t start_idx = row_id_list->at(idx) * col_num;
|
||||
int64_t end_idx = start_idx + col_num;
|
||||
for (int64_t i = start_idx; OB_SUCC(ret) && i < end_idx; ++i) {
|
||||
@ -74,13 +77,16 @@ int ObExprValuesSpec::serialize(char* buf, int64_t buf_len, int64_t& pos, ObPhyO
|
||||
OB_UNIS_ENCODE(values_);
|
||||
}
|
||||
OB_UNIS_ENCODE(str_values_array_);
|
||||
OB_UNIS_ENCODE(err_log_ct_def_);
|
||||
OB_UNIS_ENCODE(contain_ab_param_);
|
||||
OB_UNIS_ENCODE(ins_values_batch_opt_);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t ObExprValuesSpec::get_serialize_size(const ObPhyOpSeriCtx& seri_ctx) const
|
||||
int64_t ObExprValuesSpec::get_serialize_size(const ObPhyOpSeriCtx &seri_ctx) const
|
||||
{
|
||||
int64_t len = get_serialize_size_(seri_ctx);
|
||||
OB_UNIS_ADD_LEN(len);
|
||||
@ -94,6 +100,9 @@ OB_DEF_SERIALIZE_SIZE(ObExprValuesSpec)
|
||||
BASE_ADD_LEN((ObExprValuesSpec, ObOpSpec));
|
||||
OB_UNIS_ADD_LEN(values_);
|
||||
OB_UNIS_ADD_LEN(str_values_array_);
|
||||
OB_UNIS_ADD_LEN(err_log_ct_def_);
|
||||
OB_UNIS_ADD_LEN(contain_ab_param_);
|
||||
OB_UNIS_ADD_LEN(ins_values_batch_opt_);
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -103,6 +112,9 @@ OB_DEF_SERIALIZE(ObExprValuesSpec)
|
||||
BASE_SER((ObExprValuesSpec, ObOpSpec));
|
||||
OB_UNIS_ENCODE(values_);
|
||||
OB_UNIS_ENCODE(str_values_array_);
|
||||
OB_UNIS_ENCODE(err_log_ct_def_);
|
||||
OB_UNIS_ENCODE(contain_ab_param_);
|
||||
OB_UNIS_ENCODE(ins_values_batch_opt_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -112,31 +124,36 @@ OB_DEF_DESERIALIZE(ObExprValuesSpec)
|
||||
BASE_DESER((ObExprValuesSpec, ObOpSpec));
|
||||
OB_UNIS_DECODE(values_);
|
||||
OB_UNIS_DECODE(str_values_array_);
|
||||
|
||||
OB_UNIS_DECODE(err_log_ct_def_);
|
||||
OB_UNIS_DECODE(contain_ab_param_);
|
||||
OB_UNIS_DECODE(ins_values_batch_opt_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t ObExprValuesSpec::get_serialize_size_(const ObPhyOpSeriCtx& seri_ctx) const
|
||||
int64_t ObExprValuesSpec::get_serialize_size_(const ObPhyOpSeriCtx &seri_ctx) const
|
||||
{
|
||||
int64_t len = 0;
|
||||
const ObIArray<int64_t>* row_id_list = static_cast<const ObIArray<int64_t>*>(seri_ctx.row_id_list_);
|
||||
const ObIArray<int64_t> *row_id_list = static_cast<const ObIArray<int64_t> *>(
|
||||
seri_ctx.row_id_list_);
|
||||
len += ObOpSpec::get_serialize_size();
|
||||
int64_t col_num = get_output_count();
|
||||
if (row_id_list != NULL) {
|
||||
int64_t value_size = col_num * row_id_list->count();
|
||||
OB_UNIS_ADD_LEN(value_size);
|
||||
ARRAY_FOREACH_NORET(*row_id_list, idx)
|
||||
{
|
||||
ARRAY_FOREACH_NORET(*row_id_list, idx) {
|
||||
int64_t start_idx = row_id_list->at(idx) * col_num;
|
||||
int64_t end_idx = start_idx + col_num;
|
||||
for (int64_t i = start_idx; i < end_idx; ++i) {
|
||||
OB_UNIS_ADD_LEN(values_.at(i));
|
||||
}
|
||||
}
|
||||
} else if (OB_NOT_NULL(seri_ctx.exec_ctx_) && !seri_ctx.exec_ctx_->get_row_id_list_array().empty()) {
|
||||
} else if (OB_NOT_NULL(seri_ctx.exec_ctx_) &&
|
||||
!seri_ctx.exec_ctx_->get_row_id_list_array().empty()) {
|
||||
int64_t value_count = seri_ctx.exec_ctx_->get_row_id_list_total_count() * col_num;
|
||||
OB_UNIS_ADD_LEN(value_count);
|
||||
for (int array_idx = 0; array_idx < seri_ctx.exec_ctx_->get_row_id_list_array().count(); ++array_idx) {
|
||||
for (int array_idx = 0;
|
||||
array_idx < seri_ctx.exec_ctx_->get_row_id_list_array().count();
|
||||
++array_idx) {
|
||||
if (OB_ISNULL(row_id_list = seri_ctx.exec_ctx_->get_row_id_list_array().at(array_idx))) {
|
||||
LOG_WARN("row id list is null");
|
||||
} else {
|
||||
@ -153,19 +170,26 @@ int64_t ObExprValuesSpec::get_serialize_size_(const ObPhyOpSeriCtx& seri_ctx) co
|
||||
OB_UNIS_ADD_LEN(values_);
|
||||
}
|
||||
OB_UNIS_ADD_LEN(str_values_array_);
|
||||
OB_UNIS_ADD_LEN(err_log_ct_def_);
|
||||
OB_UNIS_ADD_LEN(contain_ab_param_);
|
||||
OB_UNIS_ADD_LEN(ins_values_batch_opt_);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ObExprValuesOp::ObExprValuesOp(ObExecContext& exec_ctx, const ObOpSpec& spec, ObOpInput* input)
|
||||
: ObOperator(exec_ctx, spec, input),
|
||||
node_idx_(0),
|
||||
vector_index_(0),
|
||||
datum_caster_(),
|
||||
cm_(CM_NONE),
|
||||
value_count_(0),
|
||||
switch_value_(false)
|
||||
{}
|
||||
ObExprValuesOp::ObExprValuesOp(ObExecContext &exec_ctx,
|
||||
const ObOpSpec &spec,
|
||||
ObOpInput *input)
|
||||
: ObOperator(exec_ctx, spec, input),
|
||||
node_idx_(0),
|
||||
vector_index_(0),
|
||||
datum_caster_(),
|
||||
cm_(CM_NONE),
|
||||
err_log_service_(get_eval_ctx()),
|
||||
err_log_rt_def_(),
|
||||
has_sequence_(false)
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprValuesOp::inner_open()
|
||||
{
|
||||
@ -175,12 +199,12 @@ int ObExprValuesOp::inner_open()
|
||||
const int32_t result_flag = 0;
|
||||
if (OB_FAIL(datum_caster_.init(eval_ctx_.exec_ctx_))) {
|
||||
LOG_WARN("fail to init datum_caster", K(ret));
|
||||
} else if (OB_FAIL(ObSQLUtils::get_default_cast_mode(is_explicit_cast, result_flag, ctx_.get_my_session(), cm_))) {
|
||||
} else if (OB_FAIL(ObSQLUtils::get_default_cast_mode(is_explicit_cast, result_flag,
|
||||
ctx_.get_my_session(), cm_))) {
|
||||
LOG_WARN("fail to get_default_cast_mode", K(ret));
|
||||
} else {
|
||||
switch_value_ = true;
|
||||
// see ObSQLUtils::wrap_column_convert_ctx(), add CM_WARN_ON_FAIL for INSERT IGNORE.
|
||||
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
cm_ = cm_ | CM_COLUMN_CONVERT;
|
||||
if (plan_ctx->is_ignore_stmt()) {
|
||||
// CM_CHARSET_CONVERT_IGNORE_ERR is will give '?' when do string_string convert.
|
||||
@ -188,200 +212,319 @@ int ObExprValuesOp::inner_open()
|
||||
cm_ = cm_ | CM_WARN_ON_FAIL | CM_CHARSET_CONVERT_IGNORE_ERR;
|
||||
LOG_TRACE("is ignore, set CM_WARN_ON_FAIL and CM_CHARSET_CONVERT_IGNORE_ERR", K(cm_));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValuesOp::get_value_count()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (MY_INPUT.partition_id_values_ != 0) {
|
||||
common::ObIArray<ObPxSqcMeta::PartitionIdValue>* pid_values =
|
||||
reinterpret_cast<common::ObIArray<ObPxSqcMeta::PartitionIdValue>*>(MY_INPUT.partition_id_values_);
|
||||
int64_t partition_id = ctx_.get_expr_partition_id();
|
||||
bool find = false;
|
||||
int64_t col_num = MY_SPEC.get_output_count();
|
||||
CK(partition_id != OB_INVALID_ID);
|
||||
for (int i = 0; OB_SUCC(ret) && i < pid_values->count() && !find; ++i) {
|
||||
if (partition_id == pid_values->at(i).partition_id_) {
|
||||
node_idx_ = pid_values->at(i).value_begin_idx_ * col_num;
|
||||
value_count_ = node_idx_ + pid_values->at(i).value_count_ * col_num;
|
||||
if (OB_FAIL(value_count_ > MY_SPEC.values_.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected value count", K(ret), K(value_count_), K(MY_SPEC.values_.count()));
|
||||
}
|
||||
find = true;
|
||||
}
|
||||
if (0 == child_cnt_) {
|
||||
} else if (1 == child_cnt_) {
|
||||
CK (PHY_SEQUENCE == left_->get_spec().get_type());
|
||||
has_sequence_ = true;
|
||||
} else {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected child cnt", K(child_cnt_), K(ret));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (!find) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected partition id", K(partition_id));
|
||||
} else {
|
||||
switch_value_ = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
value_count_ = MY_SPEC.values_.count();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValuesOp::rescan()
|
||||
int ObExprValuesOp::inner_rescan()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (MY_INPUT.partition_id_values_ != 0 && ctx_.is_gi_restart()) {
|
||||
switch_value_ = true;
|
||||
if (OB_FAIL(ObOperator::inner_rescan())) {
|
||||
LOG_WARN("failed to do inner rescan", K(ret));
|
||||
} else {
|
||||
node_idx_ = 0;
|
||||
}
|
||||
OZ(ObOperator::rescan());
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ObExprValuesOp has its own switch iterator
|
||||
int ObExprValuesOp::switch_iterator()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
node_idx_ = 0;
|
||||
if (plan_ctx->get_bind_array_idx() >= plan_ctx->get_bind_array_count() - 1) {
|
||||
ret = OB_ITER_END;
|
||||
int ret = ObOperator::inner_switch_iterator();
|
||||
if (OB_SUCC(ret)) {
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
node_idx_ = 0;
|
||||
if (plan_ctx->get_bind_array_idx() >= plan_ctx->get_bind_array_count() - 1) {
|
||||
ret = OB_ITER_END;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
OX(OB_ASSERT(false == brs_.end_));
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValuesOp::inner_get_next_row()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
clear_evaluated_flag();
|
||||
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
ObSQLSessionInfo *session = GET_MY_SESSION(ctx_);
|
||||
if (OB_SUCC(ret)) {
|
||||
plan_ctx->set_autoinc_id_tmp(0);
|
||||
if (OB_FAIL(try_check_status())) {
|
||||
LOG_WARN("check physical plan status failed", K(ret));
|
||||
LOG_WARN("check physical plan status faild", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (switch_value_ && OB_FAIL(get_value_count())) {
|
||||
LOG_WARN("fail to get value count", K(ret));
|
||||
} else if (OB_FAIL(calc_next_row())) {
|
||||
if (OB_ITER_END != ret) {
|
||||
LOG_WARN("get next row from row store failed", K(ret));
|
||||
do {
|
||||
clear_evaluated_flag();
|
||||
err_log_rt_def_.reset();
|
||||
if (OB_FAIL(calc_next_row())) {
|
||||
if(OB_ITER_END != ret) {
|
||||
LOG_WARN("get next row from row store failed", K(ret));
|
||||
}
|
||||
} else if (MY_SPEC.err_log_ct_def_.is_error_logging_ && OB_SUCCESS != err_log_rt_def_.first_err_ret_) {
|
||||
// only if error_logging is true then first_err_ret_ could be set values
|
||||
if (OB_FAIL(err_log_service_.insert_err_log_record(session,
|
||||
MY_SPEC.err_log_ct_def_,
|
||||
err_log_rt_def_,
|
||||
ObDASOpType::DAS_OP_TABLE_INSERT))) {
|
||||
LOG_WARN("insert_err_log_record failed", K(ret), K(err_log_rt_def_.first_err_ret_));
|
||||
} else {
|
||||
err_log_rt_def_.curr_err_log_record_num_++;
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("output row", "row", ROWEXPR2STR(eval_ctx_, MY_SPEC.output_));
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("output row", "row", ROWEXPR2STR(eval_ctx_, MY_SPEC.output_));
|
||||
}
|
||||
} while (OB_SUCC(ret) &&
|
||||
MY_SPEC.err_log_ct_def_.is_error_logging_ &&
|
||||
OB_SUCCESS != err_log_rt_def_.first_err_ret_);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObExprValuesOp::update_src_meta(ObDatumMeta &src_meta, const ObObjMeta &src_obj_meta, const ObAccuracy &src_obj_acc)
|
||||
{
|
||||
src_meta.type_ = src_obj_meta.get_type();
|
||||
src_meta.cs_type_ = src_obj_meta.get_collation_type();
|
||||
src_meta.scale_ = src_obj_acc.get_scale();
|
||||
src_meta.precision_ = src_obj_acc.get_precision();
|
||||
}
|
||||
|
||||
int ObExprValuesOp::get_real_batch_obj_type(ObDatumMeta &src_meta,
|
||||
ObObjMeta &src_obj_meta,
|
||||
ObExpr *src_expr,
|
||||
int64_t group_idx)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (MY_SPEC.ins_values_batch_opt_
|
||||
&& T_QUESTIONMARK == src_expr->type_
|
||||
&& (src_expr->frame_idx_
|
||||
< spec_.plan_->get_expr_frame_info().const_frame_.count()
|
||||
+ spec_.plan_->get_expr_frame_info().param_frame_.count())) {
|
||||
int64_t param_idx = src_expr->extra_;
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
const ObSqlArrayObj *array_obj = NULL;
|
||||
if (param_idx < 0 || param_idx >= plan_ctx->get_param_store().count()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param idx", K(ret), K(param_idx));
|
||||
} else if (plan_ctx->get_param_store().at(param_idx).is_ext_sql_array()) {
|
||||
// 如果是is_ext_sql_array的参数
|
||||
if (OB_ISNULL(array_obj =
|
||||
reinterpret_cast<const ObSqlArrayObj*>(plan_ctx->get_param_store().at(param_idx).get_ext()))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected nullptr", K(ret), K(param_idx), K(plan_ctx->get_param_store()));
|
||||
} else if (array_obj->count_ <= group_idx) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected group_idx", K(ret), K(array_obj->count_),
|
||||
K(group_idx), K(param_idx), K(plan_ctx->get_param_store()));
|
||||
} else {
|
||||
src_obj_meta = array_obj->data_[group_idx].meta_;
|
||||
const ObAccuracy &src_obj_acc = array_obj->data_[group_idx].get_accuracy();
|
||||
update_src_meta(src_meta, src_obj_meta, src_obj_acc);
|
||||
}
|
||||
} else {
|
||||
// 如果不是is_ext_sql_array的参数
|
||||
src_obj_meta = plan_ctx->get_param_store().at(param_idx).meta_;
|
||||
const ObAccuracy &src_obj_acc = plan_ctx->get_param_store().at(param_idx).get_accuracy();
|
||||
update_src_meta(src_meta, src_obj_meta, src_obj_acc);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
OB_INLINE int ObExprValuesOp::calc_next_row()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
NG_TRACE_TIMES(2, value_start_calc_row);
|
||||
ObSQLSessionInfo* session = ctx_.get_my_session();
|
||||
ObSQLSessionInfo *session = ctx_.get_my_session();
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
int64_t col_num = MY_SPEC.get_output_count();
|
||||
int64_t col_idx = 0;
|
||||
if (node_idx_ == value_count_) {
|
||||
ctx_.get_sql_ctx()->multi_stmt_item_.get_batched_stmt_cnt();
|
||||
int64_t value_group = (MY_SPEC.contain_ab_param_ ? ctx_.get_sql_ctx()->multi_stmt_item_.get_batched_stmt_cnt() : 1);
|
||||
int64_t real_value_cnt = MY_SPEC.get_value_count() * value_group;
|
||||
if (node_idx_ == real_value_cnt) {
|
||||
// there is no values any more
|
||||
ret = OB_ITER_END;
|
||||
} else {
|
||||
bool is_break = false;
|
||||
ObDatum* datum = NULL;
|
||||
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
while (OB_SUCC(ret) && node_idx_ < value_count_ && !is_break) {
|
||||
ObExpr* src_expr = MY_SPEC.values_.at(node_idx_);
|
||||
ObExpr* dst_expr = MY_SPEC.output_.at(col_idx);
|
||||
ObDatumMeta src_meta = src_expr->datum_meta_;
|
||||
ObObjMeta src_obj_meta = src_expr->obj_meta_;
|
||||
if (T_QUESTIONMARK == src_expr->type_ &&
|
||||
(src_expr->frame_idx_ < spec_.plan_->get_expr_frame_info().const_frame_.count() +
|
||||
spec_.plan_->get_expr_frame_info().param_frame_.count())) {
|
||||
/*
|
||||
* the 2nd condition with frame_idx is used to support subquery in values,
|
||||
* in this case the subquery expr will be replaced to question mark, we can
|
||||
* get its meta info from expr directly, not from param_store.
|
||||
*/
|
||||
int64_t param_idx = src_expr->extra_;
|
||||
ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
if (param_idx < 0 || param_idx >= plan_ctx->get_param_store().count()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param idx", K(ret), K(param_idx));
|
||||
} else {
|
||||
src_obj_meta = plan_ctx->get_param_store().at(param_idx).meta_;
|
||||
src_meta.type_ = src_obj_meta.get_type();
|
||||
src_meta.cs_type_ = src_obj_meta.get_collation_type();
|
||||
const ObAccuracy& src_obj_acc = plan_ctx->get_param_store().at(param_idx).get_accuracy();
|
||||
src_meta.scale_ = src_obj_acc.get_scale();
|
||||
src_meta.precision_ = src_obj_acc.get_precision();
|
||||
ObDatum *datum = NULL;
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
int64_t group_idx = 0;
|
||||
if (MY_SPEC.contain_ab_param_) {
|
||||
group_idx = node_idx_ / MY_SPEC.get_value_count();
|
||||
if (OB_FAIL(plan_ctx->replace_batch_param_datum(group_idx))) {
|
||||
LOG_WARN("replace batch param datum failed", K(ret), K(group_idx));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && has_sequence_) {
|
||||
if (OB_FAIL(left_->get_next_row())) {
|
||||
if (OB_ITER_END != ret) {
|
||||
LOG_WARN("failed to calc next row", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
while (OB_SUCC(ret) && node_idx_ < real_value_cnt && !is_break) {
|
||||
int64_t real_node_idx = node_idx_ % MY_SPEC.get_value_count();
|
||||
ObExpr *src_expr = MY_SPEC.values_.at(real_node_idx);
|
||||
ObExpr *dst_expr = MY_SPEC.output_.at(col_idx);
|
||||
ObDatumMeta src_meta = src_expr->datum_meta_;
|
||||
ObObjMeta src_obj_meta = src_expr->obj_meta_;
|
||||
if (MY_SPEC.contain_ab_param_) {
|
||||
if (OB_FAIL(get_real_batch_obj_type(src_meta, src_obj_meta, src_expr, group_idx))) {
|
||||
LOG_WARN("fail to get real batch obj type info", K(ret), K(real_node_idx), K(group_idx), KPC(src_expr));
|
||||
}
|
||||
} else {
|
||||
if (T_QUESTIONMARK == src_expr->type_
|
||||
&& (src_expr->frame_idx_
|
||||
< spec_.plan_->get_expr_frame_info().const_frame_.count()
|
||||
+ spec_.plan_->get_expr_frame_info().param_frame_.count())) {
|
||||
/*
|
||||
* the 2nd condition with frame_idx is used to support subquery in values,
|
||||
* in this case the subquery expr will be replaced to question mark, we can
|
||||
* get its meta info from expr directly, not from param_store.
|
||||
*/
|
||||
int64_t param_idx = src_expr->extra_;
|
||||
ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_);
|
||||
if (param_idx < 0 || param_idx >= plan_ctx->get_param_store().count()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param idx", K(ret), K(param_idx));
|
||||
} else {
|
||||
src_obj_meta = plan_ctx->get_param_store().at(param_idx).meta_;
|
||||
const ObAccuracy &src_obj_acc =
|
||||
plan_ctx->get_param_store().at(param_idx).get_accuracy();
|
||||
update_src_meta(src_meta, src_obj_meta, src_obj_acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (T_PSEUDO_STMT_ID == src_expr->type_) {
|
||||
src_expr->locate_datum_for_write(eval_ctx_).set_int(group_idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
// do nothing
|
||||
} else if (src_expr == dst_expr) {
|
||||
// do nothing
|
||||
} else if (src_meta.type_ == dst_expr->datum_meta_.type_ && src_meta.cs_type_ == dst_expr->datum_meta_.cs_type_) {
|
||||
// 处理select 1, 2, 3; 这种情况, values_和output中表达式指针相同,
|
||||
// 不需要进行动态cast, 后面直接计算output就可以;
|
||||
//
|
||||
// 如果这里也进行了动态cast, 动态构造的cast表达式指向的expr datum为output expr
|
||||
// 指向的expr datum, 也就是与value expr指向的相同的expr datum内存区域;
|
||||
// 构造的cast表达式进行eval计算时, 如果发现datum中ptr执行的内存不为reserve内存,
|
||||
// 则会将ptr指向reserve内存, 而在参数化情况下,value expr和output expr均为
|
||||
// T_QUESTIONMARK的表达式, 该表达式是没有reserve内存的,因此会导致ptr指向非预期
|
||||
// 内存, 可能出现结果不对
|
||||
} else if (src_meta.type_ == dst_expr->datum_meta_.type_
|
||||
&& src_meta.cs_type_ == dst_expr->datum_meta_.cs_type_) {
|
||||
// 将values中数据copy到output中
|
||||
if (OB_FAIL(src_expr->eval(eval_ctx_, datum))) {
|
||||
LOG_WARN("fail to cast values", K(ret), K(*src_expr));
|
||||
// catch err and print log later
|
||||
} else {
|
||||
dst_expr->locate_datum_for_write(eval_ctx_) = *datum;
|
||||
dst_expr->get_eval_info(eval_ctx_).evaluated_ = true;
|
||||
dst_expr->set_evaluated_projected(eval_ctx_);
|
||||
}
|
||||
} else {
|
||||
// 需要动态cast原因:
|
||||
// 对于以下场景:
|
||||
// create table t1(c1 int primary key);
|
||||
// sql_1: insert into t1 values(null);
|
||||
// sql_2: insert into t1 values('1');
|
||||
// sql_1和sql_2会命中相同的执行计划, 但sql_1中values类型是null类型,
|
||||
// sql_2中values类型为varchar类型, 最终output均为int类型, 为了在新引擎下
|
||||
// 对于不同类型输入(values值), 能够最终转化为相同数据类型输出(output),
|
||||
// 因此引入了动态cast; 根据不同values值类型, 动态确定cast 函数, 并将结果
|
||||
// 存入output中;
|
||||
// 对于不同values值类型, 如果是参数化场景, 不能直接使用plan中values expr
|
||||
// 的meta信息, 该meta信息存放的是第一次生成计划时对应sql的值的meta信息,
|
||||
// 需要根据param store中实际值确定values类型, 然后获取动态cast函数
|
||||
ObExpr real_src_expr = *src_expr;
|
||||
real_src_expr.datum_meta_ = src_meta;
|
||||
real_src_expr.obj_meta_ = src_obj_meta;
|
||||
real_src_expr.obj_datum_map_ = ObDatum::get_obj_datum_map_type(src_meta.type_);
|
||||
// for table modify in oracle mode, we ignore charset convert failed
|
||||
if (lib::is_oracle_mode()) {
|
||||
cm_ = cm_ | CM_CHARSET_CONVERT_IGNORE_ERR;
|
||||
}
|
||||
if (dst_expr->obj_meta_.is_enum_or_set()) {
|
||||
if (OB_UNLIKELY(col_idx < 0 || col_idx >= MY_SPEC.str_values_array_.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("col_idx is out of size", K(ret), K(col_idx), K(MY_SPEC.str_values_array_.count()));
|
||||
LOG_WARN("col_idx is out of size", K(ret), K(col_idx),
|
||||
K(MY_SPEC.str_values_array_.count()));
|
||||
} else {
|
||||
const ObIArray<ObString>& str_values = MY_SPEC.str_values_array_.at(col_idx);
|
||||
if (OB_FAIL(datum_caster_.to_type(dst_expr->datum_meta_, str_values, real_src_expr, cm_, datum))) {
|
||||
const ObIArray<ObString> &str_values = MY_SPEC.str_values_array_.at(col_idx);
|
||||
if (OB_FAIL(datum_caster_.to_type(dst_expr->datum_meta_, str_values,
|
||||
real_src_expr, cm_, datum))) {
|
||||
LOG_WARN("fail to do to_type", K(ret), K(*dst_expr), K(real_src_expr));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(datum_caster_.to_type(dst_expr->datum_meta_, real_src_expr, cm_, datum))) {
|
||||
LOG_WARN("fail to do to_type", K(ret), K(*dst_expr), K(real_src_expr));
|
||||
if (OB_FAIL(datum_caster_.to_type(dst_expr->datum_meta_, real_src_expr,
|
||||
cm_, datum))) {
|
||||
LOG_WARN("fail to dynamic cast", K(dst_expr->datum_meta_),
|
||||
K(real_src_expr), K(cm_), K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObDatum& dst_datum = dst_expr->locate_datum_for_write(eval_ctx_);
|
||||
if (ObObjDatumMapType::OBJ_DATUM_STRING == dst_expr->obj_datum_map_ ||
|
||||
OBJ_DATUM_LOB_LOCATOR == dst_expr->obj_datum_map_) {
|
||||
ObDatum &dst_datum = dst_expr->locate_datum_for_write(eval_ctx_);
|
||||
if (ObObjDatumMapType::OBJ_DATUM_STRING == dst_expr->obj_datum_map_) {
|
||||
ObExprStrResAlloc res_alloc(*dst_expr, eval_ctx_);
|
||||
if (OB_FAIL(dst_datum.deep_copy(*datum, res_alloc))) {
|
||||
LOG_WARN("fail to deep copy datum from cast res datum", K(ret), K(*datum));
|
||||
}
|
||||
} else {
|
||||
ObDataBuffer res_alloc(const_cast<char*>(dst_datum.ptr_), dst_expr->res_buf_len_);
|
||||
ObDataBuffer res_alloc(const_cast<char*>(dst_datum.ptr_),
|
||||
dst_expr->res_buf_len_);
|
||||
if (OB_FAIL(dst_datum.deep_copy(*datum, res_alloc))) {
|
||||
LOG_WARN("fail to deep copy datum from cast res datum", K(ret), K(*datum));
|
||||
}
|
||||
}
|
||||
dst_expr->get_eval_info(eval_ctx_).evaluated_ = true;
|
||||
dst_expr->set_evaluated_projected(eval_ctx_);
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
if (MY_SPEC.err_log_ct_def_.is_error_logging_ && should_catch_err(ret)) {
|
||||
if (OB_SUCCESS == err_log_rt_def_.first_err_ret_) {
|
||||
err_log_rt_def_.first_err_ret_ = ret;
|
||||
}
|
||||
dst_expr->locate_datum_for_write(eval_ctx_).set_null();
|
||||
dst_expr->set_evaluated_projected(eval_ctx_);
|
||||
ret = OB_SUCCESS;
|
||||
} else {
|
||||
LOG_WARN("fail to do to_type and not need to catch err", K(ret), KPC(dst_expr), KPC(src_expr));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
LOG_DEBUG("expr values row columns", K(node_idx_), K(col_idx), K(*datum));
|
||||
LOG_DEBUG("expr values row columns", K(node_idx_), K(real_node_idx),
|
||||
K(col_idx), KPC(datum), K(datum), KPC(src_expr), KPC(dst_expr));
|
||||
++node_idx_;
|
||||
if (col_idx == col_num - 1) {
|
||||
// last cell values resolved, output row now
|
||||
//last cell values resolved, output row now
|
||||
is_break = true;
|
||||
} else {
|
||||
col_idx = (col_idx + 1) % col_num;
|
||||
}
|
||||
}
|
||||
} // while end
|
||||
} // while end
|
||||
|
||||
}
|
||||
NG_TRACE_TIMES(2, value_after_calc_row);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -395,6 +538,5 @@ int ObExprValuesOp::inner_close()
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
|
||||
Reference in New Issue
Block a user