patch 4.0
This commit is contained in:
198
src/sql/engine/basic/ob_function_table_op.cpp
Normal file
198
src/sql/engine/basic/ob_function_table_op.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
|
||||
#include "sql/engine/basic/ob_function_table_op.h"
|
||||
#include "share/object/ob_obj_cast.h"
|
||||
#include "common/sql_mode/ob_sql_mode_utils.h"
|
||||
#include "sql/ob_sql_utils.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/ob_physical_plan.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "pl/ob_pl_user_type.h"
|
||||
#include "sql/engine/expr/ob_expr.h"
|
||||
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
OB_SERIALIZE_MEMBER((ObFunctionTableSpec, ObOpSpec), value_expr_, column_exprs_, has_correlated_expr_);
|
||||
|
||||
int ObFunctionTableOp::inner_open()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
node_idx_ = 0;
|
||||
already_calc_ = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFunctionTableOp::inner_rescan()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(ObOperator::inner_rescan())) {
|
||||
LOG_WARN("failed to inner rescan", K(ret));
|
||||
} else {
|
||||
node_idx_ = 0;
|
||||
if (MY_SPEC.has_correlated_expr_) {
|
||||
row_count_ = 0;
|
||||
col_count_ = 0;
|
||||
value_table_ = NULL;
|
||||
already_calc_ = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFunctionTableOp::inner_close()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
node_idx_ = 0;
|
||||
row_count_ = 0;
|
||||
col_count_ = 0;
|
||||
value_table_ = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ObFunctionTableOp has its own switch_iterator
|
||||
int ObFunctionTableOp::switch_iterator()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(ObOperator::inner_switch_iterator())) {
|
||||
LOG_WARN("failed to switch iterator", K(ret));
|
||||
} else if (OB_ISNULL(ctx_.get_my_session())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to get session", K(ret));
|
||||
} else if (NULL == ctx_.get_my_session()->get_pl_implicit_cursor()
|
||||
|| !ctx_.get_my_session()->get_pl_implicit_cursor()->get_in_forall()) {
|
||||
ret = OB_ITER_END;
|
||||
} else {
|
||||
node_idx_ = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObFunctionTableOp::destroy()
|
||||
{
|
||||
ObOperator::destroy();
|
||||
}
|
||||
|
||||
|
||||
int ObFunctionTableOp::get_current_result(ObObj &result)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
void *data = NULL;
|
||||
CK (already_calc_);
|
||||
if (node_idx_ < 0 || node_idx_ >= row_count_ * col_count_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get current result in table function",
|
||||
K(node_idx_), K(row_count_), K(col_count_));
|
||||
}
|
||||
CK (node_idx_ >= 0 && node_idx_ < row_count_ * col_count_);
|
||||
CK (OB_NOT_NULL(value_table_));
|
||||
OX (data = value_table_->get_data());
|
||||
CK (OB_NOT_NULL(data));
|
||||
OX (result = (static_cast<ObObj*>(data))[node_idx_++]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObFunctionTableOp::inner_get_next_row()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPhysicalPlanCtx *plan_ctx = nullptr;
|
||||
clear_evaluated_flag();
|
||||
if (OB_ISNULL(plan_ctx = ctx_.get_physical_plan_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to get plan ctx", K(ret), K(plan_ctx));
|
||||
} else if (OB_ISNULL(MY_SPEC.value_expr_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("value expr is not init", K(ret));
|
||||
} else if (ObExtendType != MY_SPEC.value_expr_->datum_meta_.type_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected value", K(ret), K(MY_SPEC.value_expr_->datum_meta_.type_));
|
||||
} else if (FALSE_IT(plan_ctx->set_autoinc_id_tmp(0))) {
|
||||
} else if (OB_FAIL(ctx_.check_status())) {
|
||||
LOG_WARN("failed to check status ", K(ret));
|
||||
} else {
|
||||
ObDatum *value = nullptr;
|
||||
if (!already_calc_) {
|
||||
if (OB_FAIL(MY_SPEC.value_expr_->eval(eval_ctx_, value))) {
|
||||
LOG_WARN("failed to eval value expr", K(ret));
|
||||
} else if (value->is_null()) {
|
||||
//do nothing
|
||||
} else if (OB_ISNULL(value_table_
|
||||
= reinterpret_cast<pl::ObPLCollection*>(value->get_ext()))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to get value table", K(ret));
|
||||
} else {
|
||||
row_count_ = value_table_->is_inited() ? value_table_->get_count() : 0;
|
||||
col_count_ = value_table_->get_column_count();
|
||||
}
|
||||
already_calc_ = true;
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_UNLIKELY(node_idx_ >= row_count_)) {
|
||||
ret = OB_ITER_END;
|
||||
}
|
||||
CK (MY_SPEC.column_exprs_.count() >= col_count_);
|
||||
ObObj obj_stack[col_count_];
|
||||
if (OB_SUCC(ret)) {
|
||||
if (nullptr != value_table_
|
||||
&& ObExtendType == value_table_->get_element_type().get_obj_type()) {
|
||||
pl::ObPLComposite *composite = NULL;
|
||||
pl::ObPLRecord *record = NULL;
|
||||
ObObj record_obj;
|
||||
OZ (get_current_result(record_obj));
|
||||
if (OB_SUCC(ret) && record_obj.is_pl_extend()) {
|
||||
CK (OB_NOT_NULL(composite = reinterpret_cast<pl::ObPLComposite*>(record_obj.get_ext())));
|
||||
CK (composite->is_record());
|
||||
OX (record = static_cast<pl::ObPLRecord*>(composite));
|
||||
CK (record->get_count() == col_count_);
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < col_count_; ++i) {
|
||||
OZ (record->get_element(i, obj_stack[i]));
|
||||
}
|
||||
} else {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("unexpected here", K(ret), K(record_obj), K(record_obj.meta_));
|
||||
}
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < col_count_; ++i) {
|
||||
if (OB_FAIL(get_current_result(obj_stack[i]))) {
|
||||
LOG_WARN("failed to get current result", K(ret), K(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < col_count_; ++i) {
|
||||
if (obj_stack[i].is_null()) {
|
||||
MY_SPEC.column_exprs_.at(i)->locate_datum_for_write(eval_ctx_).set_null();
|
||||
} else {
|
||||
const ObObjDatumMapType &datum_map = MY_SPEC.column_exprs_.at(i)->obj_datum_map_;
|
||||
if (OB_FAIL(MY_SPEC.column_exprs_.at(i)->locate_datum_for_write(eval_ctx_)
|
||||
.from_obj(obj_stack[i], datum_map))) {
|
||||
LOG_WARN("failed to convert datum", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
MY_SPEC.column_exprs_.at(i)->set_evaluated_projected(eval_ctx_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace sql
|
||||
} // end namespace oceanbase
|
||||
Reference in New Issue
Block a user