patch 4.0

This commit is contained in:
wangzelin.wzl
2022-10-24 10:34:53 +08:00
parent 4ad6e00ec3
commit 93a1074b0c
10533 changed files with 2588271 additions and 2299373 deletions

View File

@ -15,42 +15,209 @@
#include "sql/engine/subquery/ob_subplan_filter_op.h"
#include "common/row/ob_row_iterator.h"
#include "sql/engine/ob_exec_context.h"
#include "pl/ob_pl_stmt.h"
#include "pl/ob_pl_user_type.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/ob_spi.h"
#include "sql/engine/subquery/ob_subplan_filter_op.h"
namespace oceanbase {
namespace oceanbase
{
using namespace common;
namespace sql {
OB_SERIALIZE_MEMBER(
(ObExprSubQueryRef, ObExprOperator), result_is_scalar_, scalar_result_type_, subquery_idx_, row_desc_);
namespace sql
{
OB_SERIALIZE_MEMBER(ObExprSubQueryRef::ExtraInfo,
is_cursor_,
scalar_result_type_,
row_desc_);
ObExprSubQueryRef::ObExprSubQueryRef(ObIAllocator& alloc)
: ObExprOperator(alloc, T_REF_QUERY, N_REF_QUERY, 0, NOT_ROW_DIMENSION),
result_is_scalar_(false),
scalar_result_type_(alloc),
subquery_idx_(OB_INVALID_INDEX),
row_desc_(alloc)
{}
ObExprSubQueryRef::~ObExprSubQueryRef()
{}
int ObExprSubQueryRef::assign(const ObExprOperator& other)
int ObExprSubQueryRef::Extra::assign(const Extra &other)
{
int ret = OB_SUCCESS;
const ObExprSubQueryRef* tmp_other = dynamic_cast<const ObExprSubQueryRef*>(&other);
op_id_ = other.op_id_;
iter_idx_ = other.iter_idx_;
is_scalar_ = other.is_scalar_;
return ret;
}
void ObExprSubQueryRef::ExtraInfo::reset()
{
is_cursor_ = 0;
row_desc_.reset();
scalar_result_type_.reset();
}
int ObExprSubQueryRef::ExtraInfo::assign(const ExtraInfo &other)
{
int ret = OB_SUCCESS;
is_cursor_ = other.is_cursor_;
OZ (scalar_result_type_.assign(other.scalar_result_type_));
OZ (row_desc_.assign(other.row_desc_));
return ret;
}
int ObExprSubQueryRef::ExtraInfo::init_cursor_info(ObIAllocator *allocator,
const ObQueryRefRawExpr &expr,
const ObExprOperatorType type,
ObExpr &rt_expr)
{
int ret = OB_SUCCESS;
ExtraInfo *cursor_info = NULL;
void *buf = NULL;
if (OB_ISNULL(allocator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("allocator is null", K(ret), K(allocator));
} else if (OB_ISNULL(buf = allocator->alloc(sizeof(ExtraInfo)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc memory", K(ret));
} else {
cursor_info = new(buf) ExtraInfo(*allocator, type);
bool result_is_scalar = (expr.get_output_column() == 1 && !expr.is_set());
if (result_is_scalar) {
cursor_info->scalar_result_type_ = expr.get_result_type();
}
Extra::get_info(rt_expr).is_scalar_ = result_is_scalar;
Extra::get_info(rt_expr).iter_idx_ = expr.get_ref_id() - 1;
cursor_info->is_cursor_ = expr.is_cursor();
if (OB_FAIL(cursor_info->row_desc_.reserve(expr.get_column_types().count()))) {
LOG_WARN("fail to init row_desc_", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < expr.get_column_types().count(); ++i) {
ObDataType type;
type.set_meta_type(expr.get_column_types().at(i));
type.set_accuracy(expr.get_column_types().at(i).get_accuracy());
OZ (cursor_info->row_desc_.push_back(type));
}
if (OB_SUCC(ret)) {
rt_expr.extra_info_ = cursor_info;
LOG_DEBUG("succ init_cursor_info", KPC(cursor_info));
}
}
return ret;
}
int ObExprSubQueryRef::ExtraInfo::deep_copy(common::ObIAllocator &allocator,
const ObExprOperatorType type,
ObIExprExtraInfo *&copied_info) const
{
int ret = OB_SUCCESS;
ExtraInfo *copied_cursor_info = NULL;
if (OB_FAIL(ObExprExtraInfoFactory::alloc(allocator, type, copied_info))) {
LOG_WARN("failed to alloc expr extra info", K(ret));
} else if (OB_ISNULL(copied_cursor_info = static_cast<ExtraInfo *>(copied_info))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected error", K(ret));
} else if (OB_FAIL(copied_cursor_info->row_desc_.prepare_allocate(row_desc_.count()))) {
LOG_WARN("failed to prepare allocate", K(ret));
} else {
copied_cursor_info->is_cursor_ = is_cursor_;
for (int i = 0; OB_SUCC(ret) && i < row_desc_.count(); i++) {
copied_cursor_info->row_desc_.at(i) = row_desc_.at(i);
}
}
return ret;
}
OB_DEF_SERIALIZE(ObExprSubQueryRef)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObExprOperator::serialize(buf, buf_len, pos))) {
LOG_WARN("fail to serialize ObExprOperator", K(buf_len), K(pos), K(ret));
}
bool is_scalar = static_cast<bool>(extra_.is_scalar_);
int64_t iter_idx = static_cast<int64_t>(extra_.iter_idx_);
LST_DO_CODE(OB_UNIS_ENCODE,
is_scalar,
extra_info_.scalar_result_type_,
iter_idx,
extra_info_.is_cursor_,
extra_info_.row_desc_);
return ret;
}
OB_DEF_DESERIALIZE(ObExprSubQueryRef)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObExprOperator::deserialize(buf, data_len, pos))) {
LOG_WARN("fail to serialize ObExprOperator", K(data_len), K(pos), K(ret));
}
bool is_scalar = false;
int64_t iter_idx = 0;
LST_DO_CODE(OB_UNIS_DECODE,
is_scalar,
extra_info_.scalar_result_type_,
iter_idx,
extra_info_.is_cursor_,
extra_info_.row_desc_);
if (OB_SUCC(ret)) {
extra_.is_scalar_ = static_cast<uint16_t>(is_scalar);
extra_.iter_idx_ = static_cast<uint16_t>(iter_idx);
}
return ret;
}
OB_DEF_SERIALIZE_SIZE(ObExprSubQueryRef)
{
int64_t len = 0;
bool is_scalar = static_cast<bool>(extra_.is_scalar_);
int64_t iter_idx = static_cast<int64_t>(extra_.iter_idx_);
len += ObExprOperator::get_serialize_size();
LST_DO_CODE(OB_UNIS_ADD_LEN,
is_scalar,
extra_info_.scalar_result_type_,
iter_idx,
extra_info_.is_cursor_,
extra_info_.row_desc_);
return len;
}
int ObExprSubQueryRef::ObExprSubQueryRefCtx::add_cursor_info(
pl::ObPLCursorInfo *cursor_info, sql::ObSQLSessionInfo *session_info)
{
int ret = OB_SUCCESS;
CK (OB_NOT_NULL(session_info));
CK (OB_NOT_NULL(cursor_info));
OX (session_info_ = session_info);
if (OB_FAIL(ret)) {
} else if (NULL == cursor_info_) {
OX (cursor_info_ = cursor_info);
} else if (cursor_info_ != cursor_info) {
OZ (cursor_info_->close(*session_info_));
OX (cursor_info_->~ObPLCursorInfo());
OX (cursor_info_ = cursor_info);
}
return ret;
}
ObExprSubQueryRef::ObExprSubQueryRef(ObIAllocator &alloc)
: ObExprOperator(alloc, T_REF_QUERY,
N_REF_QUERY,
0,
NOT_ROW_DIMENSION,
INTERNAL_IN_MYSQL_MODE,
INTERNAL_IN_ORACLE_MODE),
extra_(),
extra_info_(alloc, T_REF_QUERY)
{
}
ObExprSubQueryRef::~ObExprSubQueryRef()
{
}
int ObExprSubQueryRef::assign(const ObExprOperator &other)
{
int ret = OB_SUCCESS;
const ObExprSubQueryRef *tmp_other = static_cast<const ObExprSubQueryRef *>(&other);
if (OB_UNLIKELY(NULL == tmp_other)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument. wrong type for other", K(ret), K(other));
} else if (this != tmp_other) {
if (OB_FAIL(ObExprOperator::assign(other))) {
LOG_WARN("copy in Base class ObExprOperator failed", K(ret));
} else if (OB_FAIL(scalar_result_type_.assign(tmp_other->scalar_result_type_))) {
LOG_WARN("copy scalar_result_type_ failed", K(ret));
} else if (OB_FAIL(row_desc_.assign(tmp_other->row_desc_))) {
LOG_WARN("copy accuracy desc failed", K(ret));
} else {
this->result_is_scalar_ = tmp_other->result_is_scalar_;
this->subquery_idx_ = tmp_other->subquery_idx_;
OZ (extra_.assign(tmp_other->extra_));
OZ (extra_info_.assign(tmp_other->extra_info_));
}
}
return ret;
@ -58,19 +225,20 @@ int ObExprSubQueryRef::assign(const ObExprOperator& other)
void ObExprSubQueryRef::reset()
{
result_is_scalar_ = false;
subquery_idx_ = OB_INVALID_INDEX;
result_type_.set_null();
row_desc_.reset();
extra_.reset();
extra_info_.reset();
}
int ObExprSubQueryRef::calc_result_type0(ObExprResType& type, ObExprTypeCtx& type_ctx) const
int ObExprSubQueryRef::calc_result_type0(ObExprResType &type, ObExprTypeCtx &type_ctx) const
{
UNUSED(type_ctx);
if (result_is_scalar_) {
type = scalar_result_type_;
if (extra_info_.is_cursor_) {
type.set_ext();
} else if (extra_.is_scalar_) {
//subquery的结果是一个标量,那么返回类型是标量的实际返回类型
type = extra_info_.scalar_result_type_;
} else {
// for static typing engine, we return ObExpr::extra_
//subquery的结果是一个向量或者集合,那么返回类型是其迭代器index的数据类型
type.set_int();
type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].scale_);
type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].precision_);
@ -78,113 +246,155 @@ int ObExprSubQueryRef::calc_result_type0(ObExprResType& type, ObExprTypeCtx& typ
return OB_SUCCESS;
}
int ObExprSubQueryRef::calc_result0(ObObj& result, ObExprCtx& expr_ctx) const
void ObExprSubQueryRef::set_scalar_result_type(const ObExprResType &result_type)
{
extra_info_.scalar_result_type_ = result_type;
}
int ObExprSubQueryRef::cg_expr(
ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const
{
int ret = OB_SUCCESS;
ObNewRow* row = NULL;
ObNewRowIterator* row_iter = NULL;
ObIArray<ObNewRowIterator*>* row_iters = expr_ctx.subplan_iters_;
if (OB_ISNULL(row_iters) || OB_ISNULL(expr_ctx.calc_buf_)) {
const ObQueryRefRawExpr *expr = static_cast<const ObQueryRefRawExpr *>(&raw_expr);
CK (OB_NOT_NULL(expr));
OZ (ExtraInfo::init_cursor_info(op_cg_ctx.allocator_, *expr, type_, rt_expr));
OX (rt_expr.eval_func_ = &expr_eval);
return ret;
}
int ObExprSubQueryRef::convert_datum_to_obj(
ObEvalCtx &ctx, ObSubQueryIterator &iter, ObIAllocator &allocator, ObNewRow &row)
{
int ret = OB_SUCCESS;
if (iter.get_output().count() > 0 && NULL == row.cells_) {
if (OB_ISNULL(row.cells_ = static_cast<ObObj *>(
allocator.alloc(sizeof(ObObj) * iter.get_output().count())))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory failed", K(ret));
} else {
for (int64_t i = 0; i < iter.get_output().count(); i++) {
new (&row.cells_[i]) ObObj();
}
row.count_ = iter.get_output().count();
row.projector_size_ = 0;
row.projector_ = NULL;
}
}
if (OB_SUCC(ret)) {
for (int64_t i = 0; OB_SUCC(ret) && i < iter.get_output().count(); i++) {
ObDatum *datum = NULL;
ObExpr *expr = iter.get_output().at(i);
if (OB_FAIL(expr->eval(ctx, datum))) {
LOG_WARN("expr evaluate failed", K(ret));
} else if (OB_FAIL(datum->to_obj(
row.cells_[i], expr->obj_meta_, expr->obj_datum_map_))) {
LOG_WARN("convert datum to obj failed", K(ret));
}
}
}
return ret;
}
int ObExprSubQueryRef::expr_eval(
const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
{
int ret = OB_SUCCESS;
const Extra &extra = Extra::get_info(expr);
const ExtraInfo *extra_info = static_cast<ExtraInfo *>(expr.extra_info_);
ObDatum *datum = NULL;
ObSubQueryIterator *iter = NULL;
//对所有iter 进行reset操作
if (OB_ISNULL(extra_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_UNLIKELY(subquery_idx_ < 0 || subquery_idx_ >= row_iters->count())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("subquery row iterator does not exist", "row_iters_count", row_iters->count(), K_(subquery_idx));
} else if (OB_ISNULL(row_iter = row_iters->at(subquery_idx_))) {
LOG_WARN("extra info is null", K(ret));
} else if (OB_FAIL(get_subquery_iter(ctx, extra, iter))) {
LOG_WARN("get sub query iterator failed", K(ret), K(extra));
} else if (OB_ISNULL(iter)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
row_iter->reset();
LOG_WARN("null iter returned", K(ret));
} else if (OB_FAIL(iter->rewind())) {
LOG_WARN("filter to rewind subquery iterator", K(ret));
}
if (OB_FAIL(ret)) {
/*do nothing*/
} else if (result_is_scalar_) {
// subquery result is a scalar obj
bool iter_end = false;
if (OB_FAIL(row_iter->get_next_row(row))) {
if (OB_LIKELY(OB_ITER_END == ret)) {
ret = OB_SUCCESS;
iter_end = true;
result.set_null();
} else {
LOG_WARN("get next row from row iterator failed", K(ret));
}
} else if (OB_ISNULL(row)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("row is null", K(ret));
} else if (OB_UNLIKELY(1 != row->get_count())) {
// not a scalar obj
ret = OB_ERR_INVALID_COLUMN_NUM;
LOG_USER_ERROR(OB_ERR_INVALID_COLUMN_NUM, (int64_t)1);
} else if (OB_FAIL(ob_write_obj(*expr_ctx.calc_buf_, row->get_cell(0), result))) {
LOG_WARN("deep copy obj failed", K(ret), K(row->get_cell(0)));
}
if (OB_SUCC(ret)) {
if (iter_end) {
// it's iter end, don't get next row
// #bug29851474
} else if (OB_UNLIKELY(OB_SUCCESS == (ret = row_iter->get_next_row(row)))) {
LOG_WARN("subquery too many rows", K(ret));
ret = OB_SUBQUERY_TOO_MANY_ROW;
} else if (OB_LIKELY(OB_ITER_END == ret)) {
ret = OB_SUCCESS;
} else {
LOG_WARN("get next row from row iterator failed", K(ret));
}
}
} else {
// subquery result is a row or a set, so return the index of subquery row iterator
result.set_int(subquery_idx_);
}
return ret;
}
void ObExprSubQueryRef::set_scalar_result_type(const ObExprResType& result_type)
{
scalar_result_type_ = result_type;
}
int ObExprSubQueryRef::cg_expr(ObExprCGCtx&, const ObRawExpr&, ObExpr& rt_expr) const
{
int ret = OB_SUCCESS;
ExtraInfo::get_info(rt_expr).is_scalar_ = result_is_scalar_;
CK(OB_INVALID_INDEX != subquery_idx_);
ExtraInfo::get_info(rt_expr).iter_idx_ = subquery_idx_;
rt_expr.eval_func_ = &expr_eval;
return ret;
}
int ObExprSubQueryRef::expr_eval(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& expr_datum)
{
int ret = OB_SUCCESS;
const ExtraInfo& info = ExtraInfo::get_info(expr);
if (info.is_scalar_) {
ObDatum* datum = NULL;
ObSubQueryIterator* iter = NULL;
if (OB_FAIL(get_subquery_iter(ctx, info, iter))) {
LOG_WARN("get sub query iterator failed", K(ret), K(info));
} else if (OB_ISNULL(iter)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null iter returned", K(ret));
} else if (1 != iter->get_output().count()) {
// not a scalar obj
} else if (extra.is_scalar_) {
if (1 != iter->get_output().count()) {
//not a scalar obj
ret = OB_ERR_INVALID_COLUMN_NUM;
LOG_USER_ERROR(OB_ERR_INVALID_COLUMN_NUM, 1L);
} else {
iter->reset();
if (OB_FAIL(iter->get_next_row())) {
bool iter_end = false;
bool found_in_hash_map = false;
bool is_hash_enabled = iter->has_hashmap();
if (is_hash_enabled) {
ObDatum out;
if (OB_FAIL(iter->get_curr_probe_row())) {
LOG_WARN("failed to get probe row", K(ret));
} else if (OB_FAIL(iter->get_refactored(out))) {
if (OB_HASH_NOT_EXIST != ret) {
LOG_WARN("failed to find in hash map", K(ret));
} else {
ret = OB_SUCCESS;
}
} else {
found_in_hash_map = true;
if (OB_FAIL(expr.deep_copy_datum(ctx, out))) {
LOG_WARN("failed to deep copy datum", K(ret));
}
}
}
if (OB_FAIL(ret) || found_in_hash_map) {
} else if (OB_FAIL(iter->get_next_row())) {
if (OB_LIKELY(OB_ITER_END == ret)) {
ret = OB_SUCCESS;
iter_end = true;
expr_datum.set_null();
} else {
LOG_WARN("get next row from subquery failed", K(ret));
}
} else if (OB_FAIL(iter->get_output().at(0)->eval(ctx, datum))) {
} else if (OB_FAIL(iter->get_output().at(0)->eval(iter->get_eval_ctx(), datum))) {
LOG_WARN("expr evaluate failed", K(ret));
// deep copy datum since the following iter->get_next_row() make datum invalid.
} else if (OB_FAIL(expr.deep_copy_datum(ctx, *datum))) {
LOG_WARN("deep copy datum failed", K(ret), K(datum));
} else {
}
if (OB_SUCC(ret) && is_hash_enabled
&& iter->probe_row_.cnt_ > 0
&& !found_in_hash_map
&& !iter_end) {
//now we can insert curr row and curr result into hashmap
//first to get arena allocator from sp_iter to deep copy row
ObDatum value;
DatumRow row_key;
row_key.cnt_ = iter->probe_row_.cnt_;
//first check memory is enough
int64_t need_size = datum->len_ + sizeof(ObDatum);
for (int64_t i = 0; i < iter->probe_row_.cnt_; ++i) {
need_size += (iter->probe_row_.elems_[i].len_ + sizeof(ObDatum));
}
bool can_insert = iter->check_can_insert(need_size);
ObIAllocator *alloc = nullptr;
if (!can_insert) {
//memory is exceed, do not insert new rows
} else if (OB_FAIL(iter->get_arena_allocator(alloc)) || OB_ISNULL(alloc)) {
LOG_WARN("failed to get arena allocator", K(ret));
} else if (OB_ISNULL(row_key.elems_
= static_cast<ObDatum *> (alloc->alloc(sizeof(ObDatum) * row_key.cnt_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc memory for row key", K(ret), K(row_key.cnt_));
} else if (OB_FAIL(value.deep_copy(*datum, *alloc))) {
LOG_WARN("deep copy datum failed", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < row_key.cnt_; ++i) {
if (OB_FAIL(row_key.elems_[i].deep_copy(iter->probe_row_.elems_[i], *alloc))) {
LOG_WARN("failed to copy probe row", K(ret));
}
}
if (OB_SUCC(ret) && OB_FAIL(iter->set_refactored(row_key, value, need_size))) {
LOG_WARN("failed to insert into hashmap", K(ret));
}
}
}
if (OB_SUCC(ret) && !found_in_hash_map && !iter_end) {
if (OB_UNLIKELY(OB_SUCCESS == (ret = iter->get_next_row()))) {
ret = OB_SUBQUERY_TOO_MANY_ROW;
LOG_WARN("subquery too many rows", K(ret));
@ -202,32 +412,59 @@ int ObExprSubQueryRef::expr_eval(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& ex
return ret;
}
int ObExprSubQueryRef::get_subquery_iter(ObEvalCtx& ctx, const ExtraInfo& extra_info, ObSubQueryIterator*& iter)
int ObExprSubQueryRef::get_subquery_iter(ObEvalCtx &ctx,
const Extra &extra,
ObSubQueryIterator *&iter)
{
int ret = OB_SUCCESS;
if (!extra_info.is_valid()) {
if (!extra.is_valid()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid extra info", K(ret), K(extra_info));
LOG_WARN("invalid extra info", K(ret), K(extra));
} else {
ObOperatorKit* kit = ctx.exec_ctx_.get_operator_kit(extra_info.op_id_);
ObOperatorKit *kit = ctx.exec_ctx_.get_operator_kit(extra.op_id_);
if (OB_ISNULL(kit) || OB_ISNULL(kit->op_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("operator is NULL", K(ret), K(extra_info), KP(kit));
LOG_WARN("operator is NULL", K(ret), K(extra), KP(kit));
} else if (PHY_SUBPLAN_FILTER != kit->op_->get_spec().type_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("is not subplan filter operator", K(ret), K(extra_info), "spec", kit->op_->get_spec());
LOG_WARN("is not subplan filter operator", K(ret), K(extra),
"spec", kit->op_->get_spec());
} else {
ObSubPlanFilterOp* op = static_cast<ObSubPlanFilterOp*>(kit->op_);
if (extra_info.iter_idx_ >= op->get_subplan_iters().count()) {
ObSubPlanFilterOp *op = static_cast<ObSubPlanFilterOp *>(kit->op_);
if (extra.iter_idx_ >= op->get_subplan_iters().count()) {
ret = OB_ARRAY_OUT_OF_RANGE;
LOG_WARN("out of range", K(ret), K(extra_info), "iter_cnt", op->get_subplan_iters().count());
LOG_WARN("out of range", K(ret), K(extra),
"iter_cnt", op->get_subplan_iters().count());
} else {
iter = op->get_subplan_iters().at(extra_info.iter_idx_);
iter = op->get_subplan_iters().at(extra.iter_idx_);
}
}
}
return ret;
}
int ObExprSubQueryRef::reset_onetime_expr(const ObExpr &expr, ObEvalCtx &ctx)
{
int ret = OB_SUCCESS;
const Extra &extra = Extra::get_info(expr);
const ExtraInfo *extra_info = static_cast<ExtraInfo *>(expr.extra_info_);
ObSubQueryIterator *iter = NULL;
bool reset_for_onetime_expr = true;
if (OB_ISNULL(extra_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("extra info is null", K(ret));
} else if (OB_FAIL(get_subquery_iter(ctx, extra, iter))) {
LOG_WARN("get sub query iterator failed", K(ret), K(extra));
} else if (OB_ISNULL(iter)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null iter returned", K(ret));
} else if (!iter->is_onetime_plan()) {
// do nothing
} else if (OB_FAIL(iter->rewind(reset_for_onetime_expr))) {
LOG_WARN("filter to rewind subquery iterator", K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase