patch 4.0
This commit is contained in:
386
src/sql/resolver/expr/ob_raw_expr_copier.cpp
Normal file
386
src/sql/resolver/expr/ob_raw_expr_copier.cpp
Normal file
@ -0,0 +1,386 @@
|
||||
/**
|
||||
* 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_RESV
|
||||
#include "common/ob_smart_call.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr_copier.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr_util.h"
|
||||
using namespace oceanbase;
|
||||
using namespace oceanbase::sql;
|
||||
using namespace oceanbase::common;
|
||||
|
||||
int ObIRawExprCopier::copy(ObRawExpr *&expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExpr *old_expr = expr;
|
||||
if (OB_FAIL(copy(old_expr, expr))) {
|
||||
LOG_WARN("failed to copy expr", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObIRawExprCopier::copy(const ObRawExpr *expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
new_expr = NULL;
|
||||
if (OB_LIKELY(expr != NULL)) {
|
||||
if (OB_FAIL(check_need_copy(expr, new_expr))) {
|
||||
LOG_WARN("failed to check need copy", K(ret));
|
||||
} else if (new_expr != NULL) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(do_copy_expr(expr, new_expr))) {
|
||||
LOG_WARN("failed to copy expr", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObNonFixedExprCopier::check_need_copy(const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
new_expr = NULL;
|
||||
if (OB_LIKELY(old_expr != NULL)) {
|
||||
if (!use_new_allocator_ &&
|
||||
!copy_fixed_expr_ &&
|
||||
is_fixed_expr(*old_expr)) {
|
||||
new_expr = const_cast<ObRawExpr *>(old_expr);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObNonFixedExprCopier::do_copy_expr(const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool cur_value = copy_fixed_expr_;
|
||||
// disable for param expr or attribute expr
|
||||
copy_fixed_expr_ = false;
|
||||
if (OB_ISNULL(old_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("old expr is null", K(ret));
|
||||
} else if (OB_FAIL(expr_factory_.create_raw_expr(old_expr->get_expr_class(),
|
||||
old_expr->get_expr_type(),
|
||||
new_expr))) {
|
||||
LOG_WARN("failed to create raw expr", K(ret));
|
||||
} else if (OB_FAIL(new_expr->deep_copy(*this, *old_expr))) {
|
||||
LOG_WARN("failed to assign old expr", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < new_expr->get_param_count(); ++i) {
|
||||
if (OB_FAIL(SMART_CALL(copy(new_expr->get_param_expr(i))))) {
|
||||
LOG_WARN("failed to copy param expr", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
// restore
|
||||
if (cur_value) {
|
||||
copy_fixed_expr_ = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObNonFixedExprCopier::is_fixed_expr(const ObRawExpr &expr)
|
||||
{
|
||||
return expr.is_column_ref_expr() ||
|
||||
expr.is_query_ref_expr() ||
|
||||
expr.is_aggr_expr() ||
|
||||
expr.is_win_func_expr() ||
|
||||
expr.is_set_op_expr() ||
|
||||
expr.is_exec_param_expr() ||
|
||||
is_pseudo_column_like_expr(expr) ||
|
||||
expr.has_flag(IS_SHARED_REF) ||
|
||||
expr.is_param_expr();
|
||||
}
|
||||
|
||||
bool ObNonFixedExprCopier::is_pseudo_column_like_expr(const ObRawExpr &expr)
|
||||
{
|
||||
bool bret = false;
|
||||
if (ObRawExpr::EXPR_PSEUDO_COLUMN == expr.get_expr_class() ||
|
||||
T_FUN_SYS_ROWNUM == expr.get_expr_type() ||
|
||||
T_FUN_SYS_SEQ_NEXTVAL == expr.get_expr_type()) {
|
||||
bret = true;
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
int ObPLExprCopier::copy_expr(ObRawExprFactory &expr_factory,
|
||||
const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
ObPLExprCopier copier(expr_factory);
|
||||
return copier.copy(old_expr, new_expr);
|
||||
}
|
||||
|
||||
int ObPLExprCopier::check_need_copy(const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
UNUSED(old_expr);
|
||||
new_expr = NULL;
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObPLExprCopier::do_copy_expr(const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(old_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("old expr is null", K(ret));
|
||||
} else if (OB_FAIL(expr_factory_.create_raw_expr(old_expr->get_expr_class(),
|
||||
old_expr->get_expr_type(),
|
||||
new_expr))) {
|
||||
LOG_WARN("failed to create raw expr", K(ret));
|
||||
} else if (OB_FAIL(new_expr->deep_copy(*this, *old_expr))) {
|
||||
LOG_WARN("failed to assign old expr", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < new_expr->get_param_count(); ++i) {
|
||||
if (OB_FAIL(SMART_CALL(copy(new_expr->get_param_expr(i))))) {
|
||||
LOG_WARN("failed to copy param expr", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::check_need_copy(const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int tmp = OB_SUCCESS;
|
||||
uint64_t key = reinterpret_cast<uint64_t>(old_expr);
|
||||
uint64_t val = 0;
|
||||
new_expr = NULL;
|
||||
if (OB_UNLIKELY(!copied_exprs_.created())) {
|
||||
// do nothing
|
||||
} else if (OB_HASH_EXIST == (tmp = new_exprs_.exist_refactored(key))) {
|
||||
// the old expr is copied in the current context
|
||||
new_expr = const_cast<ObRawExpr *>(old_expr);
|
||||
} else if (OB_UNLIKELY(OB_HASH_NOT_EXIST != tmp)) {
|
||||
ret = tmp;
|
||||
LOG_WARN("get expr from hash map failed", K(ret));
|
||||
} else if (OB_SUCCESS == (tmp = copied_exprs_.get_refactored(key, val))) {
|
||||
new_expr = reinterpret_cast<ObRawExpr *>(val);
|
||||
} else if (OB_UNLIKELY(OB_HASH_NOT_EXIST != tmp)) {
|
||||
ret = tmp;
|
||||
LOG_WARN("get expr from hash map failed", K(ret));
|
||||
} else if (old_expr->is_exec_param_expr() &&
|
||||
!static_cast<const ObExecParamRawExpr *>(old_expr)->is_onetime()) {
|
||||
// TODO link.zt skip the copy of exec param expr
|
||||
// let the query ref raw expr to copy the expr
|
||||
// to be improved
|
||||
new_expr = const_cast<ObRawExpr *>(old_expr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::copy_expr_node(const ObRawExpr *expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExpr *tmp = NULL;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr is null", K(ret));
|
||||
} else if (OB_FAIL(expr_factory_.create_raw_expr(expr->get_expr_class(),
|
||||
expr->get_expr_type(),
|
||||
tmp))) {
|
||||
LOG_WARN("failed to create raw expr", K(ret));
|
||||
} else if (OB_FAIL(tmp->deep_copy(*this, *expr))) {
|
||||
LOG_WARN("failed to assign old expr", K(ret));
|
||||
} else if (OB_FAIL(add_expr(expr, tmp))) {
|
||||
LOG_WARN("failed to add expr", K(ret));
|
||||
} else {
|
||||
new_expr = tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::copy_expr(ObRawExprFactory &expr_factory,
|
||||
const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
ObRawExprCopier copier(expr_factory);
|
||||
return copier.copy(old_expr, new_expr);
|
||||
}
|
||||
|
||||
int ObRawExprCopier::copy_expr_node(ObRawExprFactory &expr_factory,
|
||||
const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExpr *tmp = NULL;
|
||||
ObRawExprCopier copier(expr_factory);
|
||||
if (OB_ISNULL(old_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr is null", K(ret));
|
||||
} else if (OB_FAIL(expr_factory.create_raw_expr(old_expr->get_expr_class(),
|
||||
old_expr->get_expr_type(),
|
||||
tmp))) {
|
||||
LOG_WARN("failed to create raw expr", K(ret));
|
||||
} else if (OB_FAIL(tmp->deep_copy(copier, *old_expr))) {
|
||||
LOG_WARN("failed to assign old expr", K(ret));
|
||||
} else {
|
||||
new_expr = tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::add_expr(const ObRawExpr *from,
|
||||
const ObRawExpr *to)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(from) || OB_ISNULL(to)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("input exprs are invalid", K(ret), K(from), K(to));
|
||||
} else if (OB_UNLIKELY(!copied_exprs_.created())) {
|
||||
if (OB_FAIL(copied_exprs_.create(64, ObModIds::OB_SQL_COMPILE))) {
|
||||
LOG_WARN("failed to create expr map", K(ret));
|
||||
} else if (OB_FAIL(new_exprs_.create(64))) {
|
||||
LOG_WARN("failed to create expr set", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(copied_exprs_.set_refactored(reinterpret_cast<uint64_t>(from),
|
||||
reinterpret_cast<uint64_t>(to)))) {
|
||||
LOG_WARN("faield to add copied expr into map", K(ret));
|
||||
} else if (OB_FAIL(new_exprs_.set_refactored(reinterpret_cast<uint64_t>(to)))) {
|
||||
LOG_WARN("failed to add copied expr into set", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::add_expr(const ObIArray<ObRawExpr *> &from_exprs,
|
||||
const ObIArray<ObRawExpr *> &to_exprs)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(from_exprs.count() != to_exprs.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("array size does not match",
|
||||
K(ret), K(from_exprs.count()), K(to_exprs.count()));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < from_exprs.count(); ++i) {
|
||||
if (is_existed(from_exprs.at(i))) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(add_expr(from_exprs.at(i), to_exprs.at(i)))) {
|
||||
LOG_WARN("failed to add expr", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObRawExprCopier::is_existed(const ObRawExpr *target) const
|
||||
{
|
||||
bool bret = false;
|
||||
if (OB_LIKELY(copied_exprs_.created())) {
|
||||
uint64_t key = reinterpret_cast<uint64_t>(target);
|
||||
uint64_t val = 0;
|
||||
if (OB_SUCCESS == copied_exprs_.get_refactored(key, val)) {
|
||||
bret = true;
|
||||
}
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::do_copy_expr(const ObRawExpr *old_expr,
|
||||
ObRawExpr *&new_expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
new_expr = NULL;
|
||||
if (OB_ISNULL(old_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("old expr is null", K(ret));
|
||||
} else if (OB_FAIL(copy_expr_node(old_expr, new_expr))) {
|
||||
LOG_WARN("failed to copy expr node", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < new_expr->get_param_count(); ++i) {
|
||||
if (OB_FAIL(SMART_CALL(copy(new_expr->get_param_expr(i))))) {
|
||||
LOG_WARN("failed to copy param expr", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::copy_on_replace(ObRawExpr *from_expr,
|
||||
ObRawExpr *&to_expr,
|
||||
ObIRawExprReplacer *replacer /*= NULL*/,
|
||||
ObIArray<ObRawExpr *> *uncopy_list)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRawExpr *tmp = NULL;
|
||||
to_expr = NULL;
|
||||
if (OB_ISNULL(from_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("input expr is null", K(ret));
|
||||
} else if (OB_FAIL(check_need_copy(from_expr, tmp))) {
|
||||
LOG_WARN("failed to check need copy", K(ret));
|
||||
} else if (NULL != tmp) {
|
||||
// the base_expr is already re-created
|
||||
to_expr = tmp;
|
||||
} else if (NULL != replacer) {
|
||||
if (OB_FAIL(replacer->generate_new_expr(expr_factory_, from_expr, tmp))) {
|
||||
LOG_WARN("failed to generate new expr", K(ret));
|
||||
} else if (NULL != tmp) {
|
||||
if (OB_FAIL(add_expr(from_expr, tmp))) {
|
||||
LOG_WARN("failed to add expr into replace map", K(ret));
|
||||
} else {
|
||||
to_expr = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && NULL == to_expr) {
|
||||
to_expr = from_expr;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < to_expr->get_param_count(); ++i) {
|
||||
ObRawExpr *param = from_expr->get_param_expr(i);
|
||||
ObRawExpr *new_param = NULL;
|
||||
if (OB_FAIL(SMART_CALL(copy_on_replace(param, new_param, replacer)))) {
|
||||
LOG_WARN("failed to static replace expr", K(ret));
|
||||
} else if (param == new_param ||
|
||||
(uncopy_list != NULL && ObRawExprUtils::find_expr(*uncopy_list, from_expr))) {
|
||||
// do noting if the param does not change, or the expr is marked as uncopy.
|
||||
} else if (from_expr == to_expr && OB_FAIL(copy_expr_node(from_expr, to_expr))) {
|
||||
// the param is changed, create a copy of the from_expr
|
||||
// and then make modifications on the copy (to_expr).
|
||||
LOG_WARN("failed to copy expr node", K(ret));
|
||||
} else {
|
||||
to_expr->get_param_expr(i) = new_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprCopier::add_skipped_expr(const ObRawExpr *target)
|
||||
{
|
||||
return add_expr(target, target);
|
||||
}
|
||||
|
||||
int ObRawExprCopier::add_skipped_expr(const ObIArray<ObRawExpr *> &targets)
|
||||
{
|
||||
return add_expr(targets, targets);
|
||||
}
|
||||
|
||||
int ObRawExprCopier::add_replaced_expr(const ObRawExpr *from_expr,
|
||||
const ObRawExpr *to_expr)
|
||||
{
|
||||
return add_expr(from_expr, to_expr);
|
||||
}
|
||||
|
||||
int ObRawExprCopier::add_replaced_expr(const ObIArray<ObRawExpr *> &from_exprs,
|
||||
const ObIArray<ObRawExpr *> &to_exprs)
|
||||
{
|
||||
return add_expr(from_exprs, to_exprs);
|
||||
}
|
||||
Reference in New Issue
Block a user