Files
oceanbase/src/sql/resolver/expr/ob_raw_expr_precalc_analyzer.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

222 lines
8.2 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_RESV
#include "sql/resolver/expr/ob_raw_expr_precalc_analyzer.h"
#include "sql/resolver/expr/ob_raw_expr.h"
#include "sql/resolver/expr/ob_raw_expr_util.h"
#include "sql/resolver/dml/ob_dml_stmt.h"
#include "sql/resolver/dml/ob_select_stmt.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/ob_sql_context.h"
#include "common/ob_smart_call.h"
namespace oceanbase {
using namespace common;
namespace sql {
const ObItemType ObRawExprPrecalcAnalyzer::EXPR_FILTER_LIST[] = {T_OP_IN, T_OP_NOT_IN, T_OP_ARG_CASE, T_FUN_SYS_NULLIF};
int ObRawExprPrecalcAnalyzer::analyze_all_expr(ObDMLStmt& stmt)
{
int ret = OB_SUCCESS;
ObArray<ObRawExpr*> relation_exprs;
ObArray<ObSelectStmt*> child_stmts;
if (OB_ISNULL(my_session_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid null session", K(ret));
} else if (OB_FAIL(stmt.get_relation_exprs(relation_exprs))) {
LOG_WARN("get relation exprs failed", K(ret));
} else if (OB_FAIL(stmt.get_child_stmts(child_stmts))) {
LOG_WARN("get child stmt failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < relation_exprs.count(); ++i) {
if (OB_FAIL(analyze_expr_tree(relation_exprs.at(i), stmt, my_session_->use_static_typing_engine()))) {
LOG_WARN("pre cast expr recursively failed", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
ObDMLStmt* child_stmt = child_stmts.at(i);
if (OB_ISNULL(child_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("child stmt is null");
} else if (OB_FAIL(SMART_CALL(analyze_all_expr(*child_stmt)))) {
LOG_WARN("analyze child stmt all expr failed", K(ret));
}
}
return ret;
}
int ObRawExprPrecalcAnalyzer::pre_cast_const_expr(ObRawExpr* expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null");
} else if (!expr->has_generalized_column() || !(expr->has_flag(CNT_CONST) || expr->has_flag(CNT_CALCULABLE_EXPR)) ||
!can_be_pre_cast(expr->get_expr_type())) {
// do nothing
} else if (expr->is_op_expr() || expr->is_sys_func_expr() || expr->is_udf_expr()) {
ObOpRawExpr* op_expr = static_cast<ObOpRawExpr*>(expr);
if (op_expr->get_input_types().count() == op_expr->get_param_count()) {
for (int64_t i = 0; OB_SUCC(ret) && i < op_expr->get_param_count(); ++i) {
ObRawExpr* param_expr = op_expr->get_param_expr(i);
if (OB_ISNULL(param_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("param expr is null");
} else if (param_expr->has_flag(IS_CONST) || param_expr->has_flag(IS_CALCULABLE_EXPR)) {
ObObjType calc_type = op_expr->get_input_types().at(i).get_calc_type();
if (calculation_need_cast(param_expr->get_data_type(), calc_type)) {
ObSysFunRawExpr* func_expr = NULL;
if (OB_FAIL(ObRawExprUtils::create_to_type_expr(
expr_factory_, param_expr, calc_type, func_expr, my_session_))) {
LOG_WARN("create cast expr failed", K(ret));
} else if (OB_FAIL(op_expr->replace_param_expr(i, func_expr))) {
LOG_WARN("replace param expr failed", K(ret));
}
}
}
}
}
}
return ret;
}
int ObRawExprPrecalcAnalyzer::pre_cast_recursively(ObRawExpr* expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null");
} else if (!expr->has_generalized_column() || !(expr->has_flag(CNT_CONST) || expr->has_flag(CNT_CALCULABLE_EXPR))) {
// do nothing
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(pre_cast_recursively(expr->get_param_expr(i))))) {
LOG_WARN("pre cast recursively failed", K(ret));
}
}
if (OB_SUCC(ret) && OB_FAIL(pre_cast_const_expr(expr))) {
LOG_WARN("pre cast const expr failed", K(ret));
}
}
return ret;
}
int ObRawExprPrecalcAnalyzer::extract_calculable_expr(ObRawExpr*& expr, ObDMLStmt& stmt, const bool filter_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr) || OB_ISNULL(stmt.get_query_ctx())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expr), K(stmt.get_query_ctx()));
} else if (expr->has_flag(IS_CALCULABLE_EXPR)) {
if (filter_expr && is_filtered(*expr)) {
// do nothing
} else {
ObHiddenColumnItem hidden_col;
hidden_col.hidden_idx_ = stmt.get_pre_param_size();
hidden_col.expr_ = expr;
if (expr->has_flag(CNT_CUR_TIME)) {
stmt.get_query_ctx()->fetch_cur_time_ = true;
}
ObRawExpr* orig_expr = expr;
if (OB_FAIL(stmt.add_calculable_item(hidden_col))) {
LOG_WARN("add calculable item to stmt failed", K(ret));
} else if (OB_FAIL(ObRawExprUtils::create_param_expr(expr_factory_, hidden_col.hidden_idx_, expr))) {
LOG_WARN("create param expr failed", K(ret));
} else if (expr != orig_expr) {
expr->set_orig_expr(orig_expr);
}
}
}
return ret;
}
int ObRawExprPrecalcAnalyzer::extract_calculable_expr_recursively(
ObRawExpr*& expr, ObDMLStmt& stmt, const bool filter_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null");
} else if (expr->has_flag(IS_CALCULABLE_EXPR)) {
if (OB_FAIL(extract_calculable_expr(expr, stmt, filter_expr))) {
LOG_WARN("extract calculabe expr failed", K(ret));
}
} else if (expr->has_flag(CNT_CALCULABLE_EXPR)) {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(extract_calculable_expr_recursively(expr->get_param_expr(i), stmt)))) {
LOG_WARN("extract calculabe expr recursively failed", K(ret));
}
}
}
return ret;
}
int ObRawExprPrecalcAnalyzer::analyze_expr_tree(ObRawExpr* expr, ObDMLStmt& stmt, const bool filter_expr /* false */)
{
int ret = OB_SUCCESS;
ObRawExpr* old_expr = expr;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null");
} else if (OB_FAIL(pre_cast_recursively(expr))) {
LOG_WARN("pre cast expr recursively failed", K(ret));
} else if (OB_FAIL(expr->extract_info())) {
LOG_WARN("extract expr info failed", K(ret));
} else if (OB_FAIL(extract_calculable_expr_recursively(expr, stmt, filter_expr))) {
LOG_WARN("extract calculabe expr recursively failed", K(ret));
} else if (OB_FAIL(expr->extract_info())) {
LOG_WARN("extract expr info failed", K(ret));
} else if (old_expr != expr) {
if (OB_FAIL(stmt.replace_expr_in_stmt(old_expr, expr))) {
LOG_WARN("replace expr in stmt failed", K(ret));
}
}
return ret;
}
bool ObRawExprPrecalcAnalyzer::can_be_pre_cast(ObItemType expr_type) const
{
bool bret = true;
if (T_FUN_SYS_TO_TYPE == expr_type || T_OP_ARG_CASE == expr_type || T_OP_CASE == expr_type ||
T_FUN_SYS_SET_COLLATION == expr_type || T_FUN_COLUMN_CONV == expr_type || T_FUN_SYS_DEFAULT == expr_type ||
T_FUN_SYS_AUTOINC_NEXTVAL == expr_type) {
bret = false;
}
return bret;
}
bool ObRawExprPrecalcAnalyzer::calculation_need_cast(ObObjType param_type, ObObjType calc_type) const
{
bool bret = false;
if (ObNullType == param_type || ObNullType == calc_type) {
bret = false;
} else if (ObMaxType == param_type || ObMaxType == calc_type) {
bret = false;
} else if (param_type != calc_type) { // TODO:char vs varchar?
bret = true;
}
return bret;
}
bool ObRawExprPrecalcAnalyzer::is_filtered(ObRawExpr& expr)
{
bool is_filtered = false;
for (int i = 0; !is_filtered && i < ARRAYSIZEOF(EXPR_FILTER_LIST); i++) {
if (expr.get_expr_type() == EXPR_FILTER_LIST[i]) {
is_filtered = true;
}
}
return is_filtered;
}
} // namespace sql
} // namespace oceanbase