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

4460 lines
177 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_util.h"
#include "share/ob_define.h"
#include "share/ob_errno.h"
#include "lib/allocator/ob_malloc.h"
#include "lib/allocator/page_arena.h"
#include "lib/string/ob_string.h"
#include "lib/string/ob_sql_string.h"
#include "lib/json/ob_json.h"
#include "lib/json/ob_json_print_utils.h"
#include "sql/resolver/dml/ob_select_stmt.h"
#include "sql/resolver/expr/ob_raw_expr.h"
#include "sql/resolver/expr/ob_raw_expr_resolver_impl.h"
#include "sql/resolver/ob_resolver_utils.h"
#include "sql/parser/ob_parser_utils.h"
#include "sql/parser/ob_parser.h"
#include "sql/parser/ob_sql_parser.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/engine/expr/ob_expr_to_type.h"
#include "sql/engine/expr/ob_expr_type_to_str.h"
#include "sql/engine/expr/ob_expr_column_conv.h"
#include "sql/engine/expr/ob_datum_cast.h"
#include "sql/engine/expr/ob_expr_cast.h"
#include "common/ob_smart_call.h"
#include "sql/optimizer/ob_optimizer_util.h"
namespace oceanbase {
using namespace common;
using namespace share;
using namespace share::schema;
namespace sql {
#define RESOLVE_ORALCE_IMLICIT_CAST_WARN_OR_ERR(warn_code, err_code) \
if ((session_info->get_sql_mode() & SMO_ERROR_ON_RESOLVE_CAST) > 0) { \
ret = err_code; \
} else { \
LOG_USER_WARN(warn_code); \
}
inline int ObRawExprUtils::resolve_op_expr_add_implicit_cast(ObRawExprFactory& expr_factory,
const ObSQLSessionInfo* session_info, ObRawExpr* src_expr, const ObExprResType& dst_type,
ObSysFunRawExpr*& func_expr)
{
int ret = OB_SUCCESS;
if (dst_type.is_varying_len_char_type() && !ob_is_rowid_tc(src_expr->get_result_type().get_type())) {
ObItemType func_type = T_MAX;
const char* func_name = NULL;
if (OB_ISNULL(src_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", K(ret), KP(src_expr));
} else if (src_expr->get_result_type().is_raw()) {
func_type = T_FUN_SYS_RAWTOHEX;
func_name = N_RAWTOHEX;
} else if (dst_type.is_nvarchar2()) {
func_type = T_FUN_SYS_TO_NCHAR;
func_name = N_TO_NCHAR;
} else if (dst_type.is_varchar()) {
func_type = T_FUN_SYS_TO_CHAR;
func_name = N_TO_CHAR;
}
if (OB_SUCC(ret)) {
if (OB_FAIL(expr_factory.create_raw_expr(func_type, func_expr))) {
LOG_WARN("create cast expr failed", K(ret));
} else if (OB_FAIL(func_expr->add_param_expr(src_expr))) {
LOG_WARN("add real param expr failed", K(ret));
} else {
func_expr->set_func_name(ObString::make_string(func_name));
if (OB_FAIL(func_expr->formalize(session_info))) {
LOG_WARN("formalize current expr failed", K(ret));
}
LOG_DEBUG("succ to create to char expr", K(dst_type));
}
}
} else {
OZ(ObRawExprUtils::create_cast_expr(expr_factory, src_expr, dst_type, func_expr, session_info));
CK(OB_NOT_NULL(func_expr));
}
return ret;
}
int ObRawExprUtils::resolve_op_expr_implicit_cast(ObRawExprFactory& expr_factory, const ObSQLSessionInfo* session_info,
ObItemType op_type, ObRawExpr*& sub_expr1, ObRawExpr*& sub_expr2)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(sub_expr1) || OB_ISNULL(sub_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null expr", K(ret), K(sub_expr1), K(sub_expr2));
} else {
ObSysFunRawExpr* new_expr = NULL;
ObSysFunRawExpr* new_expr2 = NULL;
ObObjType r_type1 = ObMaxType;
ObObjType r_type2 = ObMaxType;
ObObjType r_type3 = ObMaxType;
r_type1 = sub_expr1->get_result_type().get_type();
r_type2 = sub_expr2->get_result_type().get_type();
// formalize to get expr's type
if (OB_SUCC(ret) && !ob_is_valid_obj_o_type(r_type1)) {
if (OB_FAIL(sub_expr1->formalize(session_info))) {
LOG_WARN("expr fail to formalize");
} else if (!ob_is_valid_obj_o_type(r_type1 = sub_expr1->get_result_type().get_type())) {
RESOLVE_ORALCE_IMLICIT_CAST_WARN_OR_ERR(OB_OBJ_TYPE_ERROR, OB_OBJ_TYPE_ERROR);
LOG_WARN("invalid oracle type after formalize type1", K(r_type1), K(*sub_expr1));
}
}
if (OB_SUCC(ret) && !ob_is_valid_obj_o_type(r_type2)) {
if (OB_FAIL(sub_expr2->formalize(session_info))) {
LOG_WARN("expr fail to formalize");
} else if (!ob_is_valid_obj_o_type(r_type2 = sub_expr2->get_result_type().get_type())) {
RESOLVE_ORALCE_IMLICIT_CAST_WARN_OR_ERR(OB_OBJ_TYPE_ERROR, OB_OBJ_TYPE_ERROR);
LOG_WARN("invalid oracle type after formalize type1", K(r_type2), K(*sub_expr2));
}
}
r_type1 = ObLobType == r_type1 ? ObLongTextType : r_type1;
r_type2 = ObLobType == r_type2 ? ObLongTextType : r_type2;
if (OB_SUCC(ret) && share::is_oracle_mode()) {
// compare lob type date in oracle mode not allowed.
if (OB_UNLIKELY(ObLongTextType == r_type1 || ObLongTextType == r_type2) && IS_COMPARISON_OP(op_type)) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_WARN("can't calculate with lob type in oracle mode", K(ret), K(r_type1), K(r_type2), K(op_type));
}
}
if (OB_SUCC(ret)) {
ObObjOType type1 = ob_obj_type_to_oracle_type(r_type1);
ObObjOType type2 = ob_obj_type_to_oracle_type(r_type2);
if (type1 >= ObOMaxType || type2 >= ObOMaxType) {
LOG_WARN("INVALID ORACLE TYPE", K(type1), K(type2), K(*sub_expr1), K(*sub_expr2));
RESOLVE_ORALCE_IMLICIT_CAST_WARN_OR_ERR(OB_OBJ_TYPE_ERROR, OB_ERR_INVALID_TYPE_FOR_OP);
} else if (ObONullType == type1 || ObONullType == type2) {
LOG_DEBUG("No need to cast with null", K(type1), K(type2));
} else {
ImplicitCastDirection dir = ImplicitCastDirection::IC_NOT_SUPPORT;
ObObjType middle_type = ObMaxType;
ObObjTypeClass tc1 = OBJ_O_TYPE_TO_CLASS[type1];
ObObjTypeClass tc2 = OBJ_O_TYPE_TO_CLASS[type2];
switch (op_type) {
case T_OP_CNN:
case T_OP_LIKE: {
/* for non-string data type: select c1||c2 from tab; => cast(c1 as varchar)||cast(c2 as varchar) */
bool cast_left = true;
bool cast_right = true;
bool has_nstring = ob_is_nstring_type(r_type1) || ob_is_nstring_type(r_type2);
if (ob_is_string_or_lob_type(r_type1) && ob_is_nstring_type(r_type1) == has_nstring) {
cast_left = false;
}
if (ob_is_string_or_lob_type(r_type2) && ob_is_nstring_type(r_type2) == has_nstring) {
cast_right = false;
}
if (T_OP_LIKE == op_type) {
if (ob_is_rowid_tc(r_type1) && ob_is_string_tc(r_type2)) {
cast_left = true;
cast_right = false;
} else if (ob_is_string_tc(r_type1) && ob_is_rowid_tc(r_type2)) {
cast_right = true;
cast_left = false;
}
}
if (cast_left && cast_right) {
dir = ImplicitCastDirection::IC_TO_MIDDLE_TYPE;
middle_type = has_nstring ? ObNVarchar2Type : ObVarcharType;
} else if (cast_left) {
dir = ImplicitCastDirection::IC_A_TO_B;
r_type2 = has_nstring ? ObNVarchar2Type : ObVarcharType;
} else if (cast_right) {
dir = ImplicitCastDirection::IC_B_TO_A;
r_type1 = has_nstring ? ObNVarchar2Type : ObVarcharType;
} else {
dir = ImplicitCastDirection::IC_NO_CAST;
}
break;
}
case T_OP_ADD: {
if (ob_is_oracle_datetime_tc(r_type1)) {
if (ob_is_numeric_type(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
} else if (ob_is_string_tc(r_type2)) {
r_type3 = ObNumberType;
dir = ImplicitCastDirection::IC_B_TO_C;
}
} else if (ob_is_oracle_datetime_tc(r_type2)) {
if (ob_is_numeric_type(r_type1)) {
dir = ImplicitCastDirection::IC_NO_CAST;
} else if (ob_is_string_tc(r_type1)) {
r_type3 = ObNumberType;
dir = ImplicitCastDirection::IC_A_TO_C;
}
}
if (ob_is_raw_tc(r_type1)) {
if (ob_is_string_tc(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
} else if (ob_is_raw_tc(r_type2)) {
if (ob_is_string_tc(r_type1)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
}
if (ImplicitCastDirection::IC_NOT_SUPPORT != dir) {
break;
}
}
case T_OP_MINUS: {
if (ob_is_oracle_datetime_tc(r_type1)) {
if (ob_is_numeric_type(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
} else if (ob_is_string_tc(r_type2)) {
r_type3 = ObNumberType;
dir = ImplicitCastDirection::IC_B_TO_C;
} else if (ob_is_oracle_datetime_tc(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
} else if (ob_is_oracle_datetime_tc(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
if (ob_is_raw_tc(r_type1)) {
if (ob_is_string_tc(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
} else if (ob_is_raw_tc(r_type2)) {
if (ob_is_string_tc(r_type1)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
}
if (ImplicitCastDirection::IC_NOT_SUPPORT != dir) {
break;
}
}
case T_OP_MUL:
case T_OP_DIV:
case T_OP_MOD: {
if (ob_is_raw_tc(r_type1)) {
if (ob_is_string_tc(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
} else if (ob_is_raw_tc(r_type2)) {
if (ob_is_string_tc(r_type1)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
}
if (ImplicitCastDirection::IC_NOT_SUPPORT != dir) {
break;
}
}
// todo timestamp with tz/ltz...
default:
if (OB_UNLIKELY(ObLongTextType == r_type1 || ObLongTextType == r_type2)) {
/* lob type return warning */
} else {
middle_type = ObNumberType;
dir = OB_OBJ_IMPLICIT_CAST_DIRECTION_FOR_ORACLE[type1][type2];
if ((ImplicitCastDirection::IC_B_TO_C == dir && ob_is_nchar(r_type1)) ||
(ImplicitCastDirection::IC_A_TO_C == dir && ob_is_nchar(r_type2))) {
// nchar and varchar2, convert varchar to nvarchar2
r_type3 = ObNVarchar2Type;
}
}
break;
}
// when cast raw to char implicitly, it is cast to varchar actually.
if (ImplicitCastDirection::IC_A_TO_B == dir && ob_is_raw(r_type1) && ObCharType == r_type2) {
r_type3 = ObVarcharType;
dir = ImplicitCastDirection::IC_A_TO_C;
}
if (ob_is_interval_tc(r_type1) || ob_is_interval_tc(r_type2)) {
dir = ImplicitCastDirection::IC_NO_CAST;
}
LOG_DEBUG(
"Molly ORACLE IMPLICIT CAST DIR", K(dir), K(type1), K(type2), K(r_type3), K(*sub_expr1), K(*sub_expr2));
ObExprResType dest_type;
switch (dir) {
case ImplicitCastDirection::IC_NO_CAST: {
// int is number(38) in oracle, when number div number, the result can be decimal.
// So we add cast int as number b4 do div
if (tc1 == ObIntTC && tc2 == ObIntTC && op_type == T_OP_DIV) {
ObAccuracy acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[1][ObNumberType];
dest_type.set_precision(acc.get_precision());
dest_type.set_scale(acc.get_scale());
dest_type.set_collation_level(CS_LEVEL_NUMERIC);
dest_type.set_type(ObNumberType);
if (OB_FAIL(
resolve_op_expr_add_implicit_cast(expr_factory, session_info, sub_expr1, dest_type, new_expr))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_FAIL(resolve_op_expr_add_implicit_cast(
expr_factory, session_info, sub_expr2, dest_type, new_expr2))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr) || OB_ISNULL(new_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else if (OB_FAIL(new_expr2->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr1 = new_expr;
sub_expr2 = new_expr2;
}
}
break;
}
case ImplicitCastDirection::IC_A_TO_B: {
ObAccuracy acc = (ObNumberType == r_type2 ? ObAccuracy::DDL_DEFAULT_ACCURACY2[1][r_type2]
: ObAccuracy::MAX_ACCURACY2[1][r_type2]);
dest_type.set_precision(acc.get_precision());
dest_type.set_scale(acc.get_scale());
dest_type.set_type(r_type2);
if (OB_FAIL(
resolve_op_expr_add_implicit_cast(expr_factory, session_info, sub_expr1, dest_type, new_expr))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr1 = new_expr;
}
break;
}
case ImplicitCastDirection::IC_B_TO_A: {
ObAccuracy acc = (ObNumberType == r_type1 ? ObAccuracy::DDL_DEFAULT_ACCURACY2[1][r_type1]
: ObAccuracy::MAX_ACCURACY2[1][r_type1]);
dest_type.set_precision(acc.get_precision());
dest_type.set_scale(acc.get_scale());
// dest_type.set_collation_level(CS_LEVEL_NUMERIC);
dest_type.set_type(r_type1);
if (OB_FAIL(
resolve_op_expr_add_implicit_cast(expr_factory, session_info, sub_expr2, dest_type, new_expr))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else {
sub_expr2 = new_expr;
}
break;
}
case ImplicitCastDirection::IC_A_TO_C: {
ObAccuracy acc = (ObNumberType == r_type3 ? ObAccuracy::DDL_DEFAULT_ACCURACY2[1][r_type3]
: ObAccuracy::MAX_ACCURACY2[1][r_type3]);
dest_type.set_precision(acc.get_precision());
dest_type.set_scale(acc.get_scale());
dest_type.set_type(r_type3);
if (OB_FAIL(
resolve_op_expr_add_implicit_cast(expr_factory, session_info, sub_expr1, dest_type, new_expr))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr1 = new_expr;
}
break;
}
case ImplicitCastDirection::IC_B_TO_C: {
ObAccuracy acc = (ObNumberType == r_type3 ? ObAccuracy::DDL_DEFAULT_ACCURACY2[1][r_type3]
: ObAccuracy::MAX_ACCURACY2[1][r_type3]);
dest_type.set_precision(acc.get_precision());
dest_type.set_scale(acc.get_scale());
dest_type.set_type(r_type3);
if (OB_FAIL(
resolve_op_expr_add_implicit_cast(expr_factory, session_info, sub_expr2, dest_type, new_expr))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr2 = new_expr;
}
break;
}
case ImplicitCastDirection::IC_TO_MIDDLE_TYPE: {
ObAccuracy acc = (ObNumberType == middle_type ? ObAccuracy::DDL_DEFAULT_ACCURACY2[1][middle_type]
: ObAccuracy::MAX_ACCURACY2[1][middle_type]);
dest_type.set_precision(acc.get_precision());
dest_type.set_scale(acc.get_scale());
dest_type.set_collation_level(CS_LEVEL_NUMERIC);
dest_type.set_type(middle_type);
ObObjTypeClass middle_tc = OBJ_O_TYPE_TO_CLASS[middle_type];
// optimization: only need to cast string type to number type
if (middle_type == ObNumberType) {
if (ObStringTC == tc1 && (ObIntTC == tc2 || ObFloatTC == tc2 || ObDoubleTC == tc2 || ObNumberTC == tc2)) {
if (OB_FAIL(
ObRawExprUtils::create_cast_expr(expr_factory, sub_expr1, dest_type, new_expr, session_info))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr1 = new_expr;
}
} else if (ObStringTC == tc2 &&
(ObIntTC == tc1 || ObFloatTC == tc1 || ObDoubleTC == tc1 || ObNumberTC == tc1)) {
if (OB_FAIL(ObRawExprUtils::create_cast_expr(
expr_factory, sub_expr2, dest_type, new_expr2, session_info))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr2->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr2 = new_expr2;
}
} else {
LOG_WARN("create cast expr for implicit failed unexpected TO_MIDDLE_TYPE", K(tc1), K(tc2));
}
} else {
if (middle_tc != tc1) {
if (OB_FAIL(resolve_op_expr_add_implicit_cast(
expr_factory, session_info, sub_expr1, dest_type, new_expr))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr1 = new_expr;
}
}
if (middle_tc != tc2) {
if (OB_FAIL(resolve_op_expr_add_implicit_cast(
expr_factory, session_info, sub_expr2, dest_type, new_expr2))) {
LOG_WARN("create cast expr for implicit failed", K(ret));
} else if (OB_ISNULL(new_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(new_expr2->add_flag(IS_INNER_ADDED_EXPR))) {
LOG_WARN("failed to add flag", K(ret));
} else {
sub_expr2 = new_expr2;
}
}
}
break;
}
case ImplicitCastDirection::IC_NOT_SUPPORT: {
// ObString type1_str = ObString(ob_obj_type_str(r_type1));
// ObString type2_str = ObString(ob_obj_type_str(r_type2));
// return warning or error when can't do implicite datatype convert
bool is_error =
(session_info != NULL && ((session_info->get_sql_mode() & SMO_ERROR_ON_RESOLVE_CAST) > 0)) ||
(sub_expr1->get_result_type().is_blob() || sub_expr2->get_result_type().is_blob() ||
sub_expr1->get_result_type().is_blob_locator() || sub_expr2->get_result_type().is_blob_locator());
if (is_error) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_USER_ERROR(OB_ERR_INVALID_TYPE_FOR_OP, ob_obj_type_str(r_type1), ob_obj_type_str(r_type2));
} else {
LOG_USER_WARN(OB_ERR_INVALID_TYPE_FOR_OP, ob_obj_type_str(r_type1), ob_obj_type_str(r_type2));
}
LOG_WARN("expr get oracle implicit cast direction failed", K(is_error));
break;
}
}
}
}
}
return ret;
}
int ObRawExprUtils::resolve_op_expr_for_oracle_implicit_cast(
ObRawExprFactory& expr_factory, const ObSQLSessionInfo* session_info, ObOpRawExpr*& b_expr)
{
int ret = OB_SUCCESS;
ObRawExpr* sub_expr1 = NULL;
ObRawExpr* sub_expr2 = NULL;
sub_expr1 = b_expr->get_param_expr(0);
sub_expr2 = b_expr->get_param_expr(1);
if (OB_ISNULL(sub_expr1) || OB_ISNULL(sub_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null expr", K(ret), K(sub_expr1), K(sub_expr2));
} else if (T_OP_ROW == sub_expr1->get_expr_type() || T_OP_ROW == sub_expr2->get_expr_type()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get T_OP_ROW expr", K(ret), K(*sub_expr1), K(*sub_expr2));
} else {
if (!sub_expr1->is_query_ref_expr() && sub_expr2->is_query_ref_expr()) {
// t1.c1 =any (select c1 from t2)
ObQueryRefRawExpr* query_ref_expr = static_cast<ObQueryRefRawExpr*>(sub_expr2);
ObSelectStmt* query_stmt = query_ref_expr->get_ref_stmt();
ObRawExpr* select_expr = NULL;
if (OB_ISNULL(query_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(query_stmt));
} else if (OB_UNLIKELY(1 != query_stmt->get_select_item_size())) {
ret = OB_ERR_INVALID_COLUMN_NUM;
LOG_USER_ERROR(OB_ERR_INVALID_COLUMN_NUM, 1L);
LOG_WARN("query_ref_expr should have 1 output column", K(query_ref_expr->get_output_column()));
} else if (OB_ISNULL(select_expr = query_stmt->get_select_item(0).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(select_expr));
} else if (OB_FAIL(resolve_op_expr_implicit_cast(
expr_factory, session_info, b_expr->get_expr_type(), sub_expr1, select_expr))) {
LOG_WARN("failed to resolve_op_expr_implicit_cast", K(ret));
} else if (OB_ISNULL(select_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else {
query_stmt->get_select_item(0).expr_ = select_expr;
ObIArray<ObExprResType>& column_types = query_ref_expr->get_column_types();
column_types.reset();
if (OB_FAIL(column_types.push_back(select_expr->get_result_type()))) {
LOG_WARN("add column type failed", K(ret));
}
}
} else if (sub_expr1->is_query_ref_expr() && sub_expr2->is_query_ref_expr()) {
// (select c1 from t2 where t2.c1=1) =any (select c1 from t2)
ObQueryRefRawExpr* query_ref_expr1 = static_cast<ObQueryRefRawExpr*>(sub_expr1);
ObQueryRefRawExpr* query_ref_expr2 = static_cast<ObQueryRefRawExpr*>(sub_expr2);
ObSelectStmt* query_stmt1 = query_ref_expr1->get_ref_stmt();
ObSelectStmt* query_stmt2 = query_ref_expr2->get_ref_stmt();
ObRawExpr* select_expr1 = NULL;
ObRawExpr* select_expr2 = NULL;
if (OB_ISNULL(query_stmt1) || OB_ISNULL(query_stmt2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(query_stmt1), K(query_stmt2));
} else if (query_stmt1->get_select_item_size() != query_stmt2->get_select_item_size()) {
ret = OB_ERR_INVALID_COLUMN_NUM;
LOG_WARN("query expr should same output column",
K(query_ref_expr1->get_output_column()),
K(query_ref_expr2->get_output_column()));
} else {
ObIArray<ObExprResType>& column_types1 = query_ref_expr1->get_column_types();
column_types1.reset();
ObIArray<ObExprResType>& column_types2 = query_ref_expr2->get_column_types();
column_types2.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < query_stmt1->get_select_item_size(); ++i) {
if (OB_ISNULL(select_expr1 = query_stmt1->get_select_item(i).expr_) ||
OB_ISNULL(select_expr2 = query_stmt2->get_select_item(i).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(select_expr1), K(select_expr2));
} else if (OB_FAIL(resolve_op_expr_implicit_cast(
expr_factory, session_info, b_expr->get_expr_type(), select_expr1, select_expr2))) {
LOG_WARN("failed to resolve_op_expr_implicit_cast", K(ret));
} else if (OB_ISNULL(select_expr1) || OB_ISNULL(select_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (OB_FAIL(column_types1.push_back(select_expr1->get_result_type()))) {
LOG_WARN("add column type failed", K(ret));
} else if (OB_FAIL(column_types2.push_back(select_expr2->get_result_type()))) {
LOG_WARN("add column type failed", K(ret));
} else {
query_stmt1->get_select_item(i).expr_ = select_expr1;
query_stmt2->get_select_item(i).expr_ = select_expr2;
}
}
}
} else {
if (OB_FAIL(resolve_op_expr_implicit_cast(
expr_factory, session_info, b_expr->get_expr_type(), sub_expr1, sub_expr2))) {
LOG_WARN("failed to resolve_op_expr_implicit_cast", K(ret));
} else if (OB_FAIL(b_expr->replace_param_expr(0, sub_expr1))) {
LOG_WARN("failed to replace_param_expr", K(ret));
} else if (OB_FAIL(b_expr->replace_param_expr(1, sub_expr2))) {
LOG_WARN("failed to replace_param_expr", K(ret));
}
}
}
return ret;
}
int ObRawExprUtils::resolve_op_exprs_for_oracle_implicit_cast(
ObRawExprFactory& expr_factory, const ObSQLSessionInfo* session_info, ObIArray<ObOpRawExpr*>& op_exprs)
{
int ret = OB_SUCCESS;
if (session_info == NULL) {
LOG_WARN("can't get compatibility mode from session_info", K(session_info));
} else {
ObOpRawExpr* b_expr = NULL;
for (int64_t i = 0; OB_SUCC(ret) && i < op_exprs.count(); i++) {
b_expr = op_exprs.at(i);
if (OB_ISNULL(b_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null expr", K(ret));
} else if (b_expr->get_param_count() != 2) {
// TODO Molly case when
LOG_WARN("IMPLICIT UNEXPECTED BEXPR", K(*b_expr));
} else if (OB_FAIL(resolve_op_expr_for_oracle_implicit_cast(expr_factory, session_info, b_expr))) {
LOG_WARN("IMPLICIT UNEXPECTED BEXPR", K(*b_expr));
}
}
}
return ret;
}
int ObRawExprUtils::function_alias(ObRawExprFactory& expr_factory, ObSysFunRawExpr*& expr)
{
int ret = OB_SUCCESS;
int64_t decimal = 10;
int64_t binary = 2;
int64_t octal = 8;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(expr));
} else if (0 == expr->get_func_name().case_compare("bin")) {
// bin(N) is equivalent to CONV(N,10,2)
ObConstRawExpr* from_base = NULL;
ObConstRawExpr* to_base = NULL;
if (OB_FAIL(ObRawExprUtils::build_const_int_expr(expr_factory, ObIntType, decimal, from_base))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(expr_factory, ObIntType, binary, to_base))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_UNLIKELY(1 != expr->get_param_count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid param count", K(expr->get_param_count()));
} else if (OB_FAIL(expr->add_param_expr(from_base))) {
LOG_WARN("fail to add param expr", K(from_base));
} else if (OB_FAIL(expr->add_param_expr(to_base))) {
LOG_WARN("fail to add param expr", K(to_base));
} else {
expr->set_func_name("conv");
}
} else if (0 == expr->get_func_name().case_compare("oct")) {
// oct(N) is equivalent to CONV(N,10,8)
ObConstRawExpr* from_base = NULL;
ObConstRawExpr* to_base = NULL;
if (OB_FAIL(ObRawExprUtils::build_const_int_expr(expr_factory, ObIntType, decimal, from_base))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(expr_factory, ObIntType, octal, to_base))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_UNLIKELY(1 != expr->get_param_count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid param count", K(expr->get_param_count()));
} else if (OB_FAIL(expr->add_param_expr(from_base))) {
LOG_WARN("fail to add param expr", K(from_base), K(ret));
} else if (OB_FAIL(expr->add_param_expr(to_base))) {
LOG_WARN("fail to add param expr", K(to_base), K(ret));
} else {
expr->set_func_name("conv");
}
} else if (0 == expr->get_func_name().case_compare("lcase")) {
// lcase is synonym for lower
expr->set_func_name("lower");
} else if (0 == expr->get_func_name().case_compare("ucase")) {
// ucase is synonym for upper
expr->set_func_name("upper");
} else if (0 == expr->get_func_name().case_compare("power")) {
// don't alias "power" to "pow" in oracle mode, because oracle has no
// "pow" function.
if (!share::is_oracle_mode()) {
expr->set_func_name("pow");
}
} else if (0 == expr->get_func_name().case_compare("ws")) {
// ws is synonym for word_segment
expr->set_func_name("word_segment");
} else {
}
return ret;
}
int ObRawExprUtils::make_raw_expr_from_str(const char* expr_str, const int64_t buf_len,
ObExprResolveContext& resolve_ctx, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns,
ObIArray<ObVarInfo>& sys_vars, ObIArray<ObSubQueryInfo>* sub_query_info, ObIArray<ObAggFunRawExpr*>& aggr_exprs,
ObIArray<ObWinFunRawExpr*>& win_exprs)
{
int ret = OB_SUCCESS;
ObSqlString sql_str;
ParseResult parse_result;
ObParser parser(resolve_ctx.expr_factory_.get_allocator(), SMO_DEFAULT);
if (OB_ISNULL(expr_str) || OB_ISNULL(sub_query_info)) {
ret = OB_INVALID_ARGUMENT;
_LOG_WARN("expr_str is %p, sub_query_info = %p", expr_str, sub_query_info);
} else if (OB_FAIL(sql_str.append_fmt("SELECT %.*s", static_cast<int>(buf_len), expr_str))) {
LOG_WARN("fail to concat string", K(expr_str), K(ret));
} else if (OB_FAIL(parser.parse(sql_str.string(), parse_result))) {
_OB_LOG(WARN,
"parse: %p, %p, %p, msg=[%s], start_col_=[%d], end_col_[%d], "
"line_[%d], yycolumn[%d], yylineno_[%d]",
parse_result.yyscan_info_,
parse_result.result_tree_,
parse_result.malloc_pool_,
parse_result.error_msg_,
parse_result.start_col_,
parse_result.end_col_,
parse_result.line_,
parse_result.yycolumn_,
parse_result.yylineno_);
} else {
if (OB_UNLIKELY(OB_LOGGER.get_log_level() >= OB_LOG_LEVEL_DEBUG)) {
LOG_DEBUG("", "parser result", SJ(ObParserResultPrintWrapper(*parse_result.result_tree_)));
}
ParseNode* stmt_node = NULL;
ParseNode* select_node = NULL;
ParseNode* select_expr_list = NULL;
ParseNode* select_expr = NULL;
ParseNode* parsed_expr = NULL;
stmt_node = parse_result.result_tree_;
if (NULL == stmt_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(stmt_node));
} else if (T_STMT_LIST != stmt_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(stmt_node->type_));
}
if (OB_SUCC(ret)) {
select_node = stmt_node->children_[0];
if (NULL == select_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_node));
} else if (T_SELECT != select_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_node->type_));
}
}
if (OB_SUCC(ret)) {
select_expr_list = select_node->children_[PARSE_SELECT_SELECT];
if (NULL == select_expr_list) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_expr_list));
} else if (T_PROJECT_LIST != select_expr_list->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_expr_list->type_));
}
}
if (OB_SUCC(ret)) {
select_expr = select_expr_list->children_[0];
if (NULL == select_expr) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_expr));
} else if (T_PROJECT_STRING != select_expr->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_expr->type_));
}
}
if (OB_SUCC(ret)) {
parsed_expr = select_expr->children_[0];
if (OB_ISNULL(parsed_expr)) {
LOG_ERROR("internal arg is not correct", KP(parsed_expr));
}
}
if (OB_SUCC(ret)) {
ObArray<ObOpRawExpr*> op_exprs;
ObSEArray<ObUserVarIdentRawExpr*, 1> user_var_exprs;
ObRawExprResolverImpl expr_resolver(resolve_ctx);
// generate raw expr
if (OB_FAIL(expr_resolver.resolve(parsed_expr,
expr,
columns,
sys_vars,
*sub_query_info,
aggr_exprs,
win_exprs,
op_exprs,
user_var_exprs))) {
_LOG_WARN("failed to resolve expr tree, err=%d", ret);
}
}
// destroy syntax tree
parser.free_result(parse_result);
}
return ret;
}
int ObRawExprUtils::make_raw_expr_from_str(const ObString& expr_str, ObExprResolveContext& resolve_ctx,
ObRawExpr*& expr, ObIArray<ObQualifiedName>& column, ObIArray<ObVarInfo>& sys_vars,
ObIArray<ObSubQueryInfo>* sub_query_info, ObIArray<ObAggFunRawExpr*>& aggr_exprs,
ObIArray<ObWinFunRawExpr*>& win_exprs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(sub_query_info)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(sub_query_info));
} else if (OB_FAIL(make_raw_expr_from_str(expr_str.ptr(),
expr_str.length(),
resolve_ctx,
expr,
column,
sys_vars,
sub_query_info,
aggr_exprs,
win_exprs))) {
LOG_WARN("fail to make_raw_expr_from_str", K(ret));
}
return ret;
}
int ObRawExprUtils::parse_default_expr_from_str(
const ObString& expr_str, ObCollationType expr_str_cs_type, ObIAllocator& allocator, const ParseNode*& node)
{
int ret = OB_SUCCESS;
ObSqlString sql_str;
ParseResult parse_result;
ObSQLMode sql_mode = SMO_DEFAULT;
if (share::is_oracle_mode()) {
sql_mode = DEFAULT_ORACLE_MODE | SMO_ORACLE;
}
ObSQLParser parser(allocator, sql_mode);
MEMSET(&parse_result, 0, sizeof(ParseResult));
parse_result.malloc_pool_ = &allocator;
parse_result.pl_parse_info_.is_pl_parse_ = true;
parse_result.pl_parse_info_.is_pl_parse_expr_ = true;
parse_result.sql_mode_ = sql_mode;
parse_result.charset_info_ = ObCharset::get_charset(expr_str_cs_type);
parse_result.is_not_utf8_connection_ = ObCharset::is_valid_collation(expr_str_cs_type)
? (ObCharset::charset_type_by_coll(expr_str_cs_type) != CHARSET_UTF8MB4)
: false;
if (OB_FAIL(sql_str.append_fmt("DO %.*s", expr_str.length(), expr_str.ptr()))) {
LOG_WARN("failed to concat expr str", K(expr_str), K(ret));
} else if (OB_FAIL(parser.parse(sql_str.string().ptr(), sql_str.string().length(), parse_result))) {
_OB_LOG(WARN,
"parse: %p, %p, %p, msg=[%s], start_col_=[%d], end_col_[%d], "
"line_[%d], yycolumn[%d], yylineno_[%d]",
parse_result.yyscan_info_,
parse_result.result_tree_,
parse_result.malloc_pool_,
parse_result.error_msg_,
parse_result.start_col_,
parse_result.end_col_,
parse_result.line_,
parse_result.yycolumn_,
parse_result.yylineno_);
} else {
if (OB_UNLIKELY(OB_LOGGER.get_log_level() >= OB_LOG_LEVEL_DEBUG)) {
LOG_DEBUG("", "parser result", SJ(ObParserResultPrintWrapper(*parse_result.result_tree_)));
}
ParseNode* expr_node = NULL;
if (OB_ISNULL(expr_node = parse_result.result_tree_->children_[0])) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to parse default expr node", K(ret), K(expr_str));
} else if (OB_UNLIKELY(T_DEFAULT != expr_node->type_) || OB_UNLIKELY(1 != expr_node->num_child_) ||
OB_ISNULL(expr_node->children_) || OB_ISNULL(expr_node->children_[0])) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN(
"expr node type is illegal", K(ret), K(expr_node->type_), K(expr_node->num_child_), K(expr_node->children_));
} else {
node = expr_node->children_[0];
}
}
return ret;
}
int ObRawExprUtils::parse_expr_node_from_str(const ObString& expr_str, ObIAllocator& allocator, const ParseNode*& node)
{
int ret = OB_SUCCESS;
ObSqlString sql_str;
ParseResult parse_result;
ObSQLMode sql_mode = SMO_DEFAULT;
if (share::is_oracle_mode()) {
sql_mode = DEFAULT_ORACLE_MODE | SMO_ORACLE;
}
ObParser parser(allocator, sql_mode);
if (OB_FAIL(sql_str.append_fmt("SELECT %.*s FROM DUAL", expr_str.length(), expr_str.ptr()))) {
LOG_WARN("fail to concat string", K(expr_str), K(ret));
} else if (OB_FAIL(parser.parse(sql_str.string(), parse_result))) {
_OB_LOG(WARN,
"parse: %p, %p, %p, msg=[%s], start_col_=[%d], end_col_[%d], "
"line_[%d], yycolumn[%d], yylineno_[%d]",
parse_result.yyscan_info_,
parse_result.result_tree_,
parse_result.malloc_pool_,
parse_result.error_msg_,
parse_result.start_col_,
parse_result.end_col_,
parse_result.line_,
parse_result.yycolumn_,
parse_result.yylineno_);
} else {
if (OB_UNLIKELY(OB_LOGGER.get_log_level() >= OB_LOG_LEVEL_DEBUG)) {
LOG_DEBUG("", "parser result", SJ(ObParserResultPrintWrapper(*parse_result.result_tree_)));
}
ParseNode* stmt_node = NULL;
ParseNode* select_node = NULL;
ParseNode* select_expr_list = NULL;
ParseNode* select_expr = NULL;
stmt_node = parse_result.result_tree_;
if (NULL == stmt_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(stmt_node));
} else if (T_STMT_LIST != stmt_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(stmt_node->type_));
}
if (OB_SUCC(ret)) {
select_node = stmt_node->children_[0];
if (NULL == select_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_node));
} else if (T_SELECT != select_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_node->type_));
}
}
if (OB_SUCC(ret)) {
select_expr_list = select_node->children_[PARSE_SELECT_SELECT];
if (NULL == select_expr_list) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_expr_list));
} else if (T_PROJECT_LIST != select_expr_list->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_expr_list->type_));
}
}
if (OB_SUCC(ret)) {
select_expr = select_expr_list->children_[0];
if (NULL == select_expr) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_expr));
} else if (T_PROJECT_STRING != select_expr->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_expr->type_));
}
}
if (OB_SUCC(ret)) {
node = select_expr->children_[0];
}
}
return ret;
}
int ObRawExprUtils::parse_bool_expr_node_from_str(
const common::ObString& expr_str, common::ObIAllocator& allocator, const ParseNode*& node)
{
int ret = OB_SUCCESS;
ObSqlString sql_str;
ParseResult parse_result;
ObSQLMode sql_mode = SMO_DEFAULT;
if (share::is_oracle_mode()) {
sql_mode = DEFAULT_ORACLE_MODE | SMO_ORACLE;
}
ObParser parser(allocator, sql_mode);
if (OB_FAIL(sql_str.append_fmt("SELECT 1 FROM DUAL WHERE %.*s", expr_str.length(), expr_str.ptr()))) {
LOG_WARN("fail to concat string", K(expr_str), K(ret));
} else if (OB_FAIL(parser.parse(sql_str.string(), parse_result))) {
_OB_LOG(WARN,
"parse: %p, %p, %p, msg=[%s], start_col_=[%d], end_col_[%d], "
"line_[%d], yycolumn[%d], yylineno_[%d]",
parse_result.yyscan_info_,
parse_result.result_tree_,
parse_result.malloc_pool_,
parse_result.error_msg_,
parse_result.start_col_,
parse_result.end_col_,
parse_result.line_,
parse_result.yycolumn_,
parse_result.yylineno_);
} else {
if (OB_UNLIKELY(OB_LOGGER.get_log_level() >= OB_LOG_LEVEL_DEBUG)) {
LOG_DEBUG("", "parser result", SJ(ObParserResultPrintWrapper(*parse_result.result_tree_)));
}
ParseNode* stmt_node = NULL;
ParseNode* select_node = NULL;
ParseNode* where_node = NULL;
ParseNode* expr_node = NULL;
stmt_node = parse_result.result_tree_;
if (NULL == stmt_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(stmt_node));
} else if (T_STMT_LIST != stmt_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(stmt_node->type_));
}
if (OB_SUCC(ret)) {
select_node = stmt_node->children_[0];
if (NULL == select_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(select_node));
} else if (T_SELECT != select_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(select_node->type_));
}
}
if (OB_SUCC(ret)) {
where_node = select_node->children_[PARSE_SELECT_WHERE];
if (NULL == where_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(where_node));
} else if (T_WHERE_CLAUSE != where_node->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", K(where_node->type_));
}
}
if (OB_SUCC(ret)) {
expr_node = where_node->children_[0];
if (NULL == expr_node) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("internal arg is not correct", KP(expr_node));
}
}
if (OB_SUCC(ret)) {
node = expr_node;
}
}
return ret;
}
int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns,
const ObSchemaChecker* schema_checker)
{
int ret = OB_SUCCESS;
const ParseNode* node = NULL;
if (OB_FAIL(parse_expr_node_from_str(expr_str, expr_factory.get_allocator(), node))) {
LOG_WARN("parse expr node from string failed", K(ret), K(expr_str));
} else if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is null");
} else if (OB_FAIL(build_generated_column_expr(expr_factory, session_info, *node, expr, columns, schema_checker))) {
LOG_WARN("build generated column expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, const ObTableSchema& table_schema, ObRawExpr*& expr,
const ObSchemaChecker* schema_checker)
{
int ret = OB_SUCCESS;
const ParseNode* node = NULL;
ObSEArray<ObQualifiedName, 4> columns;
const ObColumnSchemaV2* col_schema = NULL;
if (OB_FAIL(parse_expr_node_from_str(expr_str, expr_factory.get_allocator(), node))) {
LOG_WARN("parse expr node from string failed", K(ret));
} else if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is null");
} else if (OB_FAIL(build_generated_column_expr(expr_factory, session_info, *node, expr, columns, schema_checker))) {
LOG_WARN("build generated column expr failed", K(ret), K(expr_str));
}
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); i++) {
const ObQualifiedName& q_name = columns.at(i);
if (OB_UNLIKELY(!q_name.database_name_.empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid generated column name", K(q_name));
} else if (!q_name.tbl_name_.empty() &&
!ObCharset::case_insensitive_equal(q_name.tbl_name_, table_schema.get_table_name_str())) {
ret = OB_ERR_BAD_TABLE;
LOG_USER_ERROR(OB_ERR_BAD_TABLE, q_name.tbl_name_.length(), q_name.tbl_name_.ptr());
} else if (OB_ISNULL(col_schema = table_schema.get_column_schema(q_name.col_name_))) {
ret = OB_ERR_KEY_COLUMN_DOES_NOT_EXITS;
LOG_USER_ERROR(OB_ERR_KEY_COLUMN_DOES_NOT_EXITS, q_name.col_name_.length(), q_name.col_name_.ptr());
} else if (OB_UNLIKELY(col_schema->is_generated_column())) {
ret = OB_ERR_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN;
LOG_USER_ERROR(OB_ERR_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, "Generated column in column expression");
} else if (OB_FAIL(ObRawExprUtils::init_column_expr(*col_schema, *q_name.ref_expr_))) {
LOG_WARN("init column expr failed", K(ret), K(q_name));
} else {
q_name.ref_expr_->set_ref_id(table_schema.get_table_id(), col_schema->get_column_id());
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(expr->formalize(&session_info))) {
LOG_WARN("formalize expr failed", K(ret), KPC(expr));
}
}
return ret;
}
int ObRawExprUtils::build_check_constraint_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
const ParseNode& node, ObRawExpr*& expr, common::ObIArray<ObQualifiedName>& columns)
{
int ret = OB_SUCCESS;
ObArray<ObVarInfo> sys_vars;
ObArray<ObAggFunRawExpr*> aggr_exprs;
ObArray<ObWinFunRawExpr*> win_exprs;
ObArray<ObSubQueryInfo> sub_query_info;
ObArray<ObOpRawExpr*> op_exprs;
if (OB_FAIL(build_raw_expr(expr_factory,
session_info,
node,
expr,
columns,
sys_vars,
aggr_exprs,
win_exprs,
sub_query_info,
op_exprs))) {
LOG_WARN("fail to get collation_connection", K(ret));
} else if (OB_UNLIKELY(expr->has_flag(CNT_SUB_QUERY))) {
ret = OB_ERR_INVALID_SUBQUERY_USE;
LOG_WARN("subquery not allowed here", K(ret));
} else if (OB_UNLIKELY(expr->has_flag(CNT_AGG))) {
ret = OB_ERR_GROUP_FUNC_NOT_ALLOWED;
LOG_WARN("group function is not allowed here", K(ret));
} else if (OB_UNLIKELY(expr->has_flag(CNT_ROWNUM) || expr->has_flag(CNT_PSEUDO_COLUMN))) {
ret = OB_ERR_CBY_PSEUDO_COLUMN_NOT_ALLOWED;
LOG_WARN("Specified pseudo column or operator not allowed here",
K(ret),
K(expr->has_flag(CNT_ROWNUM)),
K(expr->has_flag(CNT_PSEUDO_COLUMN)));
} else if (OB_UNLIKELY(expr->has_flag(CNT_WINDOW_FUNC))) {
ret = OB_ERR_INVALID_WINDOW_FUNC_USE;
} else if (OB_UNLIKELY(sys_vars.count() > 0 || expr->has_flag(CNT_CUR_TIME) || expr->has_flag(CNT_STATE_FUNC))) {
ret = OB_ERR_DATE_OR_SYS_VAR_CANNOT_IN_CHECK_CST;
LOG_WARN("date or system variable wrongly specified in CHECK constraint",
K(ret),
K(expr->has_flag(CNT_CUR_TIME)),
K(expr->has_flag(CNT_STATE_FUNC)));
} else { /*do nothing*/
}
return ret;
}
int ObRawExprUtils::build_generated_column_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
const ParseNode& node, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns, const ObSchemaChecker* schema_checker)
{
int ret = OB_SUCCESS;
ObArray<ObVarInfo> sys_vars;
ObArray<ObAggFunRawExpr*> aggr_exprs;
ObArray<ObWinFunRawExpr*> win_exprs;
ObArray<ObSubQueryInfo> sub_query_info;
ObArray<ObOpRawExpr*> op_exprs;
if (OB_FAIL(build_raw_expr(expr_factory,
session_info,
const_cast<ObSchemaChecker*>(schema_checker),
T_NONE_SCOPE,
NULL,
NULL,
NULL,
node,
expr,
columns,
sys_vars,
aggr_exprs,
win_exprs,
sub_query_info,
op_exprs,
false))) {
LOG_WARN("fail to get collation_connection", K(ret));
} else if (OB_UNLIKELY(sys_vars.count() > 0)) {
// todo:mysql ERROR 3102 (HY000): Expression of generated column 'column' contains a disallowed function.
// mysql error code: ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
// format: Expression of generated column '%s' contains a disallowed function
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "use variables in generated column");
} else if (OB_UNLIKELY(sub_query_info.count() > 0)) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "use subquery in generated column");
} else if (OB_UNLIKELY(aggr_exprs.count() > 0)) {
ret = OB_ERR_INVALID_GROUP_FUNC_USE;
LOG_USER_ERROR(OB_ERR_INVALID_GROUP_FUNC_USE);
} else if (OB_UNLIKELY(win_exprs.count() > 0)) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "use window function in generated column");
} else if (lib::is_oracle_mode()) {
// generated column contain only two types of access obj:sysfunc expression and column expression
// only column expression will be handled in the upper function call,
// so sysfunc expression should be filtered in this function and can't return to the upper function call
ObSEArray<std::pair<ObRawExpr*, ObRawExpr*>, 2> ref_sys_exprs;
ObSEArray<ObQualifiedName, 2> real_columns;
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); i++) {
const ObQualifiedName& q_name = columns.at(i);
if (q_name.is_sys_func()) {
ObRawExpr* sys_func = q_name.access_idents_.at(0).sys_func_expr_;
CK(OB_NOT_NULL(sys_func));
for (int64_t i = 0; OB_SUCC(ret) && i < ref_sys_exprs.count(); ++i) {
OZ(ObRawExprUtils::replace_ref_column(sys_func, ref_sys_exprs.at(i).first, ref_sys_exprs.at(i).second));
}
OZ(q_name.access_idents_.at(0).sys_func_expr_->check_param_num());
OZ(ObRawExprUtils::replace_ref_column(expr, q_name.ref_expr_, sys_func));
OZ(ref_sys_exprs.push_back(std::pair<ObRawExpr*, ObRawExpr*>(q_name.ref_expr_, sys_func)));
} else {
OZ(real_columns.push_back(q_name), q_name, i);
}
}
if (OB_SUCC(ret) && real_columns.count() != columns.count()) {
columns.reuse();
OZ(columns.assign(real_columns), real_columns);
}
}
return ret;
}
int ObRawExprUtils::build_raw_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
const ParseNode& node, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns, ObIArray<ObVarInfo>& sys_vars,
ObIArray<ObAggFunRawExpr*>& aggr_exprs, ObIArray<ObWinFunRawExpr*>& win_exprs,
ObIArray<ObSubQueryInfo>& sub_query_info, common::ObIArray<ObOpRawExpr*>& op_exprs,
bool is_prepare_protocol /*= false*/)
{
int ret = OB_SUCCESS;
if (OB_FAIL(build_raw_expr(expr_factory,
session_info,
NULL,
T_NONE_SCOPE,
NULL,
NULL,
NULL,
node,
expr,
columns,
sys_vars,
aggr_exprs,
win_exprs,
sub_query_info,
op_exprs,
is_prepare_protocol))) {
LOG_WARN("failed to build raw expr", K(ret));
}
return ret;
}
int ObRawExprUtils::build_raw_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
ObSchemaChecker* schema_checker, ObStmtScope current_scope, ObStmt* stmt, const ParamStore* param_list,
common::ObIArray<std::pair<ObRawExpr*, ObConstRawExpr*>>* external_param_info, const ParseNode& node,
ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns, ObIArray<ObVarInfo>& sys_vars,
ObIArray<ObAggFunRawExpr*>& aggr_exprs, ObIArray<ObWinFunRawExpr*>& win_exprs,
ObIArray<ObSubQueryInfo>& sub_query_info, ObIArray<ObOpRawExpr*>& op_exprs, bool is_prepare_protocol /*= false*/)
{
int ret = OB_SUCCESS;
ObCollationType collation_connection = CS_TYPE_INVALID;
ObCharsetType character_set_connection = CHARSET_INVALID;
if (OB_FAIL(session_info.get_collation_connection(collation_connection))) {
LOG_WARN("fail to get collation_connection", K(ret));
} else if (OB_FAIL(session_info.get_character_set_connection(character_set_connection))) {
LOG_WARN("fail to get character_set_connection", K(ret));
} else {
ObExprResolveContext ctx(expr_factory, session_info.get_timezone_info(), OB_NAME_CASE_INVALID);
ctx.dest_collation_ = collation_connection;
ctx.connection_charset_ = character_set_connection;
ctx.param_list_ = param_list;
ctx.is_extract_param_type_ = !is_prepare_protocol; // when prepare do not extract
ctx.external_param_info_ = external_param_info;
ctx.current_scope_ = current_scope;
ctx.stmt_ = stmt;
ctx.schema_checker_ = schema_checker;
ctx.session_info_ = &session_info;
ObSEArray<ObUserVarIdentRawExpr*, 1> user_var_exprs;
ObRawExprResolverImpl expr_resolver(ctx);
if (OB_FAIL(session_info.get_name_case_mode(ctx.case_mode_))) {
LOG_WARN("fail to get name case mode", K(ret));
} else if (OB_FAIL(expr_resolver.resolve(
&node, expr, columns, sys_vars, sub_query_info, aggr_exprs, win_exprs, op_exprs, user_var_exprs))) {
LOG_WARN("resolve expr failed", K(ret));
} else { /*do nothing*/
}
}
return ret;
}
int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, uint64_t table_id, const ObTableSchema& table_schema,
const ObColumnSchemaV2& gen_col_schema, ObRawExpr*& expr, const ObSchemaChecker* schema_checker)
{
int ret = OB_SUCCESS;
ObArray<ObQualifiedName> columns;
const ObColumnSchemaV2* col_schema = NULL;
if (OB_FAIL(build_generated_column_expr(expr_str, expr_factory, session_info, expr, columns, schema_checker))) {
LOG_WARN("build generated column expr failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); ++i) {
const ObQualifiedName& q_name = columns.at(i);
if (OB_UNLIKELY(!q_name.database_name_.empty()) || OB_UNLIKELY(!q_name.tbl_name_.empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid generated column name", K(q_name));
} else if (OB_ISNULL(col_schema = table_schema.get_column_schema(q_name.col_name_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column schema is null");
} else if (OB_FAIL(init_column_expr(*col_schema, *q_name.ref_expr_))) {
LOG_WARN("init column expr failed", K(ret));
} else {
q_name.ref_expr_->set_ref_id(table_id, col_schema->get_column_id());
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(expr->formalize(&session_info))) {
LOG_WARN("formalize expr failed", K(ret));
}
}
if (OB_SUCC(ret) && !gen_col_schema.is_hidden()) {
// only generated column defined by user need to do cast.
ObExprResType expected_type;
expected_type.set_meta(gen_col_schema.get_meta_type());
expected_type.set_accuracy(gen_col_schema.get_accuracy());
expected_type.set_result_flag(calc_column_result_flag(gen_col_schema));
if (ObRawExprUtils::need_column_conv(expected_type, *expr)) {
if (OB_FAIL(build_column_conv_expr(expr_factory, &gen_col_schema, expr, &session_info))) {
LOG_WARN("create cast expr failed", K(ret));
}
}
}
return ret;
}
// compare two raw expressions
bool ObRawExprUtils::is_same_raw_expr(const ObRawExpr* src, const ObRawExpr* dst)
{
bool is_same = false;
if ((NULL == src && NULL != dst) || (NULL != src && NULL == dst)) {
is_same = false;
} else if (NULL == src && NULL == dst) {
is_same = true;
} else {
if (!src->same_as(*dst)) {
is_same = false;
} else {
is_same = true;
}
}
return is_same;
}
int ObRawExprUtils::replace_all_ref_column(
ObRawExpr*& raw_expr, const common::ObIArray<ObRawExpr*>& exprs, int64_t& offset)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(raw_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(raw_expr));
} else if (offset >= exprs.count()) {
LOG_WARN("beyond the index", K(offset), K(exprs.count()));
} else if (T_REF_COLUMN == raw_expr->get_expr_type()) {
LOG_DEBUG("replace leaf node", K(*raw_expr), K(*exprs.at(offset)), K(offset));
raw_expr = exprs.at(offset);
++offset;
} else {
int64_t N = raw_expr->get_param_count();
for (int64_t i = 0; OB_SUCC(ret) && i < N && offset < exprs.count(); ++i) {
ObRawExpr*& child_expr = raw_expr->get_param_expr(i);
if (OB_FAIL(replace_all_ref_column(child_expr, exprs, offset))) {
LOG_WARN("replace reference column failed", K(ret));
}
} // end for
}
return ret;
}
// if %expr_factory is not NULL, will deep copy %to expr. default behavior is shallow copy
int ObRawExprUtils::replace_ref_column(
ObRawExpr*& raw_expr, ObRawExpr* from, ObRawExpr* to, ObRawExprFactory* expr_factory)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(raw_expr) || OB_ISNULL(from) || OB_ISNULL(to)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(raw_expr), K(from), K(to));
} else if (raw_expr == to) {
// do nothing
// in case: parent(child) = to (from)
// replace as: parenet(child) = to (to)
} else if (raw_expr == from) {
if (NULL != expr_factory) {
ObRawExpr* new_to = NULL;
if (OB_FAIL(copy_expr(*expr_factory, to, new_to, COPY_REF_DEFAULT))) {
LOG_WARN("copy expr failed", K(ret), K(*to));
} else if (OB_ISNULL(new_to)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("copied expr is NULL", K(ret), KP(new_to));
} else {
raw_expr = new_to;
}
} else {
raw_expr = to;
LOG_DEBUG("replace leaf node", K(*from), K(*to), K(from), K(to));
}
} else if (raw_expr->is_query_ref_expr()) {
ObSelectStmt* ref_stmt = static_cast<ObQueryRefRawExpr*>(raw_expr)->get_ref_stmt();
ObSEArray<ObRawExpr*, 16> relation_exprs;
if (OB_ISNULL(ref_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(ref_stmt));
} else if (OB_FAIL(ref_stmt->get_relation_exprs(relation_exprs))) {
LOG_WARN("failed to get relation exprs", K(ret));
} else if (OB_FAIL(SMART_CALL(replace_ref_column(relation_exprs, from, to)))) {
LOG_WARN("replace reference column failed", K(ret));
}
} else {
int64_t N = raw_expr->get_param_count();
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
ObRawExpr*& child_expr = raw_expr->get_param_expr(i);
if (OB_FAIL(SMART_CALL(replace_ref_column(child_expr, from, to, expr_factory)))) {
LOG_WARN("replace reference column failed", K(ret));
}
} // end for
}
return ret;
}
int ObRawExprUtils::replace_ref_column(ObIArray<ObRawExpr*>& exprs, ObRawExpr* from, ObRawExpr* to)
{
int ret = OB_SUCCESS;
bool is_stack_overflow = false;
if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
LOG_WARN("check stack overflow failed", K(ret));
} else if (is_stack_overflow) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("too deep recursive", K(ret));
} else if (OB_ISNULL(from) || OB_ISNULL(to)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(from), K(to), K(ret));
} else {
ObRawExpr* tmp_raw_expr = NULL;
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
ObRawExpr*& raw_expr = tmp_raw_expr;
if (OB_FAIL(exprs.at(i, raw_expr))) {
LOG_WARN("failed to get raw expr", K(i), K(ret));
} else if (OB_FAIL(SMART_CALL(replace_ref_column(raw_expr, from, to)))) {
LOG_WARN("failed to replace_ref_column", K(from), K(to), K(ret));
} else { /*do nothing*/
}
}
}
return ret;
}
bool ObRawExprUtils::all_column_exprs(const common::ObIArray<ObRawExpr*>& exprs)
{
bool all_column = true;
for (int64_t i = 0; all_column && i < exprs.count(); ++i) {
if (OB_ISNULL(exprs.at(i))) {
all_column = false;
} else if (!exprs.at(i)->is_column_ref_expr()) {
all_column = false;
} else {
}
}
return all_column;
}
int ObRawExprUtils::extract_column_exprs(const ObRawExpr* raw_expr, ObIArray<ObRawExpr*>& column_exprs)
{
int ret = OB_SUCCESS;
if (NULL == raw_expr) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid raw expr", K(ret), K(raw_expr));
} else {
if (T_REF_COLUMN == raw_expr->get_expr_type()) {
ret = add_var_to_array_no_dup(column_exprs, const_cast<ObRawExpr*>(raw_expr));
} else {
int64_t N = raw_expr->get_param_count();
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
ret = extract_column_exprs(raw_expr->get_param_expr(i), column_exprs);
}
}
}
return ret;
}
int ObRawExprUtils::extract_column_exprs(const ObIArray<ObRawExpr*>& exprs, ObIArray<ObRawExpr*>& column_exprs)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
if (OB_ISNULL(exprs.at(i))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Expr is NULL", K(ret), K(i));
} else if (OB_FAIL(extract_column_exprs(exprs.at(i), column_exprs))) {
LOG_WARN("Failed to extract column exprs", K(ret));
} else {
} // do nothing
}
return ret;
}
int ObRawExprUtils::extract_column_ids(const ObIArray<ObRawExpr*>& exprs, common::ObIArray<uint64_t>& column_ids)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); i++) {
if (OB_ISNULL(exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(extract_column_ids(exprs.at(i), column_ids))) {
LOG_WARN("failed to extract column ids", K(ret));
} else { /*do nothing*/
}
}
return ret;
}
int ObRawExprUtils::extract_column_ids(const ObRawExpr* raw_expr, common::ObIArray<uint64_t>& column_ids)
{
int ret = OB_SUCCESS;
if (NULL == raw_expr) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid raw expr", K(ret), K(raw_expr));
} else {
if (T_REF_COLUMN == raw_expr->get_expr_type()) {
ret = add_var_to_array_no_dup(column_ids, static_cast<const ObColumnRefRawExpr*>(raw_expr)->get_column_id());
} else {
int64_t N = raw_expr->get_param_count();
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
ret = SMART_CALL(extract_column_ids(raw_expr->get_param_expr(i), column_ids));
}
}
}
return ret;
}
int ObRawExprUtils::extract_table_ids(const ObRawExpr* raw_expr, common::ObIArray<uint64_t>& table_ids)
{
int ret = OB_SUCCESS;
if (NULL == raw_expr) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid raw expr", K(ret), K(raw_expr));
} else {
if (T_REF_COLUMN == raw_expr->get_expr_type()) {
ret = add_var_to_array_no_dup(table_ids, static_cast<const ObColumnRefRawExpr*>(raw_expr)->get_table_id());
} else {
int64_t N = raw_expr->get_param_count();
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
ret = extract_table_ids(raw_expr->get_param_expr(i), table_ids);
}
}
}
return ret;
}
int ObRawExprUtils::cnt_current_level_aggr_expr(const ObRawExpr* expr, int32_t cur_level, bool& cnt_aggr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null");
} else if (expr->has_flag(IS_AGG) && expr->get_expr_level() == cur_level) {
cnt_aggr = true;
} else if (expr->has_flag(IS_SUB_QUERY)) {
const ObQueryRefRawExpr* query_ref = static_cast<const ObQueryRefRawExpr*>(expr);
const ObSelectStmt* subquery = NULL;
if ((subquery = query_ref->get_ref_stmt()) != NULL) {
if (OB_FAIL(cnt_current_level_aggr_expr(subquery, cur_level, cnt_aggr))) {
LOG_WARN("get generalized column in subquery failed", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Invalid query ref expr", K(*expr), K(ret));
}
} else if ((expr->has_flag(CNT_AGG) || expr->has_flag(CNT_SUB_QUERY)) && !expr->is_set_op_expr()) {
for (int64_t i = 0; OB_SUCC(ret) && !cnt_aggr && i < expr->get_param_count(); ++i) {
if (OB_FAIL(cnt_current_level_aggr_expr(expr->get_param_expr(i), cur_level, cnt_aggr))) {
LOG_WARN("cnt current level aggr expr failed", K(ret));
}
}
}
return ret;
}
int ObRawExprUtils::cnt_current_level_aggr_expr(const ObDMLStmt* stmt, int32_t column_level, bool& cnt_aggr)
{
int ret = OB_SUCCESS;
ObArray<ObRawExpr*> relation_exprs;
ObArray<ObSelectStmt*> child_stmts;
cnt_aggr = false;
if (OB_ISNULL(stmt)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("stmt is null");
} else if (OB_FAIL(stmt->get_relation_exprs(relation_exprs))) {
LOG_WARN("get stmt relation exprs failed", K(ret));
} else if (OB_FAIL(stmt->get_from_subquery_stmts(child_stmts))) {
LOG_WARN("get child stmt failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && !cnt_aggr && i < relation_exprs.count(); ++i) {
if (OB_FAIL(cnt_current_level_aggr_expr(relation_exprs.at(i), column_level, cnt_aggr))) {
LOG_WARN("get generalized column in expr tree failed", K(ret));
}
}
for (int64_t i = 0; OB_SUCC(ret) && !cnt_aggr && i < child_stmts.count(); ++i) {
if (OB_FAIL(cnt_current_level_aggr_expr(child_stmts.at(i), column_level, cnt_aggr))) {
LOG_WARN("get generalized column in stmt failed", K(ret));
}
}
return ret;
}
int ObRawExprUtils::try_add_cast_expr_above(ObRawExprFactory* expr_factory, const ObSQLSessionInfo* session,
ObRawExpr& src_expr, const ObExprResType& dst_type, ObRawExpr*& new_expr)
{
int ret = OB_SUCCESS;
ObCastMode cm = CM_NONE;
OZ(ObSQLUtils::get_default_cast_mode(false, /* explicit_cast */
0, /* result_flag */
session,
cm));
OZ(try_add_cast_expr_above(expr_factory, session, src_expr, dst_type, cm, new_expr));
return ret;
}
int ObRawExprUtils::try_add_cast_expr_above(ObRawExprFactory* expr_factory, const ObSQLSessionInfo* session,
ObRawExpr& expr, const ObExprResType& dst_type, const ObCastMode& cm, ObRawExpr*& new_expr)
{
int ret = OB_SUCCESS;
new_expr = &expr;
bool need_cast = false;
const ObExprResType& src_type = expr.get_result_type();
CK(OB_NOT_NULL(session) && OB_NOT_NULL(expr_factory));
OZ(ObRawExprUtils::check_need_cast_expr(src_type, dst_type, need_cast));
if (OB_SUCC(ret) && need_cast) {
if (T_FUN_SYS_CAST == expr.get_expr_type() && expr.has_flag(IS_OP_OPERAND_IMPLICIT_CAST)) {
ret = OB_ERR_UNEXPECTED;
#ifdef DEBUG
LOG_ERROR("try to add implicit cast again, check if type deduction is correct",
K(ret),
K(expr),
K(dst_type),
K(session->get_current_query_string()));
#else
LOG_WARN("try to add implicit cast again, check if type deduction is correct",
K(ret),
K(expr),
K(dst_type),
K(session->get_current_query_string()));
#endif
} else {
// setup zerofill cm
// eg: select concat(cast(c_zf as char(10)), cast(col_no_zf as char(10))) from t1;
ObCastMode cm_zf = cm;
if (expr.get_result_type().has_result_flag(OB_MYSQL_ZEROFILL_FLAG)) {
cm_zf |= CM_ZERO_FILL;
}
ObSysFunRawExpr* cast_expr = NULL;
OZ(ObRawExprUtils::create_cast_expr(*expr_factory, &expr, dst_type, cast_expr, session, false, cm_zf));
CK(OB_NOT_NULL(new_expr = dynamic_cast<ObRawExpr*>(cast_expr)));
}
LOG_DEBUG("in try_add_cast", K(ret), K(dst_type), K(cm));
}
return ret;
}
int ObRawExprUtils::create_cast_expr(ObRawExprFactory& expr_factory, ObRawExpr* src_expr, const ObExprResType& dst_type,
ObSysFunRawExpr*& func_expr, const ObSQLSessionInfo* session, bool use_def_cm, ObCastMode cm)
{
int ret = OB_SUCCESS;
CK(OB_NOT_NULL(src_expr));
CK(OB_NOT_NULL(session));
if (OB_SUCC(ret) && use_def_cm) {
OZ(ObSQLUtils::get_default_cast_mode(false, /* explicit_cast */
0, /* result_flag */
session,
cm));
}
if (OB_SUCC(ret)) {
if (session->use_static_typing_engine()) {
const ObExprResType& src_type = src_expr->get_result_type();
bool need_extra_cast_for_src_type = false;
bool need_extra_cast_for_dst_type = false;
need_extra_cast(src_type, dst_type, need_extra_cast_for_src_type, need_extra_cast_for_dst_type);
// extra cast expr: cast non-utf8 to utf8
ObSysFunRawExpr* extra_cast = NULL;
if (need_extra_cast_for_src_type) {
ObExprResType src_type_utf8;
OZ(setup_extra_cast_utf8_type(src_type, src_type_utf8));
OZ(create_real_cast_expr(expr_factory, src_expr, src_type_utf8, extra_cast, session));
OZ(create_real_cast_expr(expr_factory, extra_cast, dst_type, func_expr, session));
} else if (need_extra_cast_for_dst_type) {
ObExprResType dst_type_utf8;
OZ(setup_extra_cast_utf8_type(dst_type, dst_type_utf8));
OZ(create_real_cast_expr(expr_factory, src_expr, dst_type_utf8, extra_cast, session));
OZ(create_real_cast_expr(expr_factory, extra_cast, dst_type, func_expr, session));
} else {
OZ(create_real_cast_expr(expr_factory, src_expr, dst_type, func_expr, session));
}
if (NULL != extra_cast) {
OX(extra_cast->set_extra(cm));
OZ(extra_cast->add_flag(IS_INNER_ADDED_EXPR));
}
CK(OB_NOT_NULL(func_expr));
OX(func_expr->set_extra(cm));
OZ(func_expr->add_flag(IS_INNER_ADDED_EXPR));
} else {
OZ(create_real_cast_expr(expr_factory, src_expr, dst_type, func_expr, session));
OZ(func_expr->add_flag(IS_INNER_ADDED_EXPR));
}
OZ(func_expr->formalize(session));
}
return ret;
}
void ObRawExprUtils::need_extra_cast(const ObExprResType& src_type, const ObExprResType& dst_type,
bool& need_extra_cast_for_src_type, bool& need_extra_cast_for_dst_type)
{
need_extra_cast_for_src_type = false;
need_extra_cast_for_dst_type = false;
const ObCharsetType& src_cs = ObCharset::charset_type_by_coll(src_type.get_collation_type());
const ObCharsetType& dst_cs = ObCharset::charset_type_by_coll(dst_type.get_collation_type());
bool nonstr_to_str = !src_type.is_string_type() && dst_type.is_string_type();
bool str_to_nonstr = src_type.is_string_type() && !dst_type.is_string_type();
if (src_type.is_null() || dst_type.is_null()) {
// do nothing
} else if (str_to_nonstr) {
if (CHARSET_BINARY != src_cs && ObCharset::get_default_charset() != src_cs) {
need_extra_cast_for_src_type = true;
}
} else if (nonstr_to_str) {
if (CHARSET_BINARY != dst_cs && ObCharset::get_default_charset() != dst_cs) {
need_extra_cast_for_dst_type = true;
}
}
}
int ObRawExprUtils::setup_extra_cast_utf8_type(const ObExprResType& type, ObExprResType& utf8_type)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!type.is_string_type())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("in type must be string type", K(ret), K(type));
} else {
utf8_type = type;
utf8_type.set_collation_type(ObCharset::get_system_collation());
if (ObNVarchar2Type == type.get_type()) {
utf8_type.set_type(ObVarcharType);
} else if (ObNCharType == type.get_type()) {
utf8_type.set_type(ObCharType);
}
}
return ret;
}
int ObRawExprUtils::erase_inner_added_exprs(ObRawExpr* src_expr, ObRawExpr*& out_expr)
{
int ret = OB_SUCCESS;
CK(OB_NOT_NULL(src_expr));
OX(out_expr = src_expr);
if (OB_SUCC(ret) && src_expr->has_flag(IS_INNER_ADDED_EXPR)) {
switch (src_expr->get_expr_type()) {
case T_OP_BOOL:
case T_FUN_SYS_REMOVE_CONST: {
CK(1 == src_expr->get_param_count());
OZ(erase_inner_added_exprs(src_expr->get_param_expr(0), out_expr));
break;
}
case T_FUN_SYS_CAST: {
CK(2 == src_expr->get_param_count());
OZ(erase_inner_added_exprs(src_expr->get_param_expr(0), out_expr));
break;
}
default: {
break;
}
}
}
return ret;
}
int ObRawExprUtils::erase_operand_implicit_cast(ObRawExpr* src, ObRawExpr*& out)
{
int ret = OB_SUCCESS;
CK(OB_NOT_NULL(src));
if (OB_SUCC(ret)) {
if (src->has_flag(IS_OP_OPERAND_IMPLICIT_CAST)) {
OZ(erase_operand_implicit_cast(src->get_param_expr(0), out));
} else {
for (int64_t i = 0; i < src->get_param_count() && OB_SUCC(ret); i++) {
OZ(erase_operand_implicit_cast(src->get_param_expr(i), src->get_param_expr(i)));
}
if (OB_SUCC(ret)) {
out = src;
}
}
}
return ret;
}
int ObRawExprUtils::create_to_type_expr(ObRawExprFactory& expr_factory, ObRawExpr* src_expr, const ObObjType& dst_type,
ObSysFunRawExpr*& to_type, ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObExprOperator* op = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_TO_TYPE, to_type))) {
LOG_WARN("create to_type expr failed", K(ret));
} else if (OB_ISNULL(to_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("to_type is null");
} else if (OB_FAIL(to_type->add_param_expr(src_expr))) {
LOG_WARN("add param expr failed", K(ret));
} else if (OB_ISNULL(op = to_type->get_op())) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("allocate expr operator failed");
} else {
to_type->set_func_name(N_TO_TYPE);
ObExprToType* to_type_op = static_cast<ObExprToType*>(op);
to_type_op->set_expect_type(dst_type);
if (OB_FAIL(to_type->formalize(session_info))) {
LOG_WARN("formalize to_type expr failed", K(ret));
}
}
return ret;
}
int ObRawExprUtils::create_substr_expr(ObRawExprFactory& expr_factory, ObSQLSessionInfo* session_info,
ObRawExpr* first_expr, ObRawExpr* second_expr, ObRawExpr* third_expr, ObSysFunRawExpr*& out_expr)
{
int ret = OB_SUCCESS;
if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_SUBSTR, out_expr))) {
LOG_WARN("create to_type expr failed", K(ret));
} else if (OB_ISNULL(out_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("to_type is null");
} else {
if (NULL == third_expr) {
if (OB_FAIL(out_expr->set_param_exprs(first_expr, second_expr))) {
LOG_WARN("add param expr failed", K(ret));
}
} else {
if (OB_FAIL(out_expr->set_param_exprs(first_expr, second_expr, third_expr))) {
LOG_WARN("add param expr failed", K(ret));
}
}
}
if (OB_SUCC(ret) && OB_FAIL(out_expr->formalize(session_info))) {
LOG_WARN("formalize to_type expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::create_type_to_str_expr(ObRawExprFactory& expr_factory, ObRawExpr* src_expr,
ObSysFunRawExpr*& out_expr, ObSQLSessionInfo* session_info, bool is_type_to_str)
{
int ret = OB_SUCCESS;
ObExprOperator* op = NULL;
ObObjType data_type = ObNullType;
if (OB_ISNULL(src_expr) || OB_ISNULL(session_info)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("src_expr or session_info is NULL", KP(src_expr), KP(session_info), K(ret));
} else if (OB_UNLIKELY(!src_expr->is_terminal_expr() && !src_expr->is_sys_func_expr() && !src_expr->is_udf_expr())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("src_expr should be terminal expr or func expr", KPC(src_expr), K(ret));
} else if (FALSE_IT(data_type = src_expr->get_data_type())) {
} else if (OB_UNLIKELY(!ob_is_enumset_tc(data_type))) {
LOG_WARN("data_type of src_expr is invalid", K(data_type), KPC(src_expr), K(ret));
} else {
ObItemType item_type = (true == is_type_to_str)
? (ObEnumType == data_type ? T_FUN_ENUM_TO_STR : T_FUN_SET_TO_STR)
: (ObEnumType == data_type ? T_FUN_ENUM_TO_INNER_TYPE : T_FUN_SET_TO_INNER_TYPE);
const char* func_name = (true == is_type_to_str)
? (ObEnumType == data_type ? N_ENUM_TO_STR : N_SET_TO_STR)
: (ObEnumType == data_type ? N_ENUM_TO_INNER_TYPE : N_SET_TO_INNER_TYPE);
if (OB_FAIL(expr_factory.create_raw_expr(item_type, out_expr))) {
LOG_WARN("create out_expr expr failed", K(ret));
} else if (OB_ISNULL(out_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("created out_expr is null", K(ret));
} else if (OB_ISNULL(op = out_expr->get_op())) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("allocate expr operator failed", K(ret));
} else {
out_expr->set_func_name(ObString::make_string(func_name));
}
ObConstRawExpr* col_accuracy_expr = NULL;
if (OB_SUCC(ret)) {
ObString str_col_accuracy;
if (OB_FAIL(build_const_string_expr(
expr_factory, ObVarcharType, str_col_accuracy, src_expr->get_collation_type(), col_accuracy_expr))) {
LOG_WARN("fail to build type expr", K(ret));
} else if (OB_ISNULL(col_accuracy_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("col_accuracy_expr is NULL", K(ret));
} else {
col_accuracy_expr->set_collation_type(src_expr->get_collation_type());
col_accuracy_expr->set_accuracy(src_expr->get_accuracy());
}
}
if (OB_SUCC(ret)) {
ObExprTypeToStr* type_to_str = static_cast<ObExprTypeToStr*>(op);
const ObIArray<ObString>& enum_set_values = src_expr->get_enum_set_values();
if (OB_ISNULL(type_to_str)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to cast ObExprOperator* to ObExprTypeToStr*", K(ret));
} else if (OB_UNLIKELY(enum_set_values.count() < 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("enum_set_values is empty", K(ret));
} else if (OB_FAIL(out_expr->add_param_expr(col_accuracy_expr))) {
LOG_WARN("failed to add param expr", K(ret));
} else if (OB_FAIL(out_expr->add_param_expr(src_expr))) {
LOG_WARN("failed to add param expr", K(ret));
} else if (OB_FAIL(type_to_str->shallow_copy_str_values(enum_set_values))) {
LOG_WARN("failed to shallow_copy_str_values", K(ret));
} else if (OB_FAIL(out_expr->formalize(session_info))) {
LOG_WARN("formalize to_type expr failed", K(ret));
} else {
}
}
}
return ret;
}
int ObRawExprUtils::create_type_to_str_expr(ObRawExprFactory& expr_factory, ObRawExpr* src_expr, int32_t expr_level,
ObSysFunRawExpr*& out_expr, ObSQLSessionInfo* session_info, bool is_type_to_str)
{
int ret = OB_SUCCESS;
if (OB_FAIL(create_type_to_str_expr(expr_factory, src_expr, out_expr, session_info, is_type_to_str))) {
LOG_WARN("failed to create type_to_str_expr", K(ret));
} else if (OB_ISNULL(out_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null expr", K(ret));
} else if (OB_FAIL(out_expr->pull_relation_id_and_levels(expr_level))) {
LOG_WARN("failed to pull_relation_id_and_levels", K(ret));
}
return ret;
}
// init_expr are initial expressions before parameterization;
// src_expr output expression after parameterization.
int ObRawExprUtils::create_exec_param_expr(ObStmt* stmt, ObRawExprFactory& expr_factory, ObRawExpr*& src_expr,
ObSQLSessionInfo* session_info, std::pair<int64_t, ObRawExpr*>& init_expr)
{
UNUSED(session_info);
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", KP(stmt));
} else {
init_expr.first = stmt->get_question_marks_count();
init_expr.second = src_expr;
stmt->increase_question_marks_count();
if (OB_FAIL(create_param_expr(expr_factory, init_expr.first, src_expr, true))) {
LOG_WARN("create param expr failed", K(ret));
} else if (OB_FAIL(stmt->get_exec_param_ref_exprs().push_back(src_expr))) {
LOG_WARN("store param expr failed", K(ret));
}
}
return ret;
}
int ObRawExprUtils::create_param_expr(
ObRawExprFactory& expr_factory, int64_t param_idx, ObRawExpr*& expr, bool is_exec_param)
{
int ret = OB_SUCCESS;
ObConstRawExpr* c_expr = NULL;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null");
} else if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, c_expr))) {
LOG_WARN("create const raw expr failed", K(ret));
} else if (OB_ISNULL(c_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("const raw expr is null", K(ret));
} else {
ObObjParam val;
val.set_unknown(param_idx);
val.set_param_meta();
c_expr->set_value(val);
c_expr->set_result_type(expr->get_result_type());
if (is_exec_param) {
c_expr->add_flag(IS_EXEC_PARAM);
}
if (ob_is_enumset_tc(expr->get_result_type().get_type())) {
if (OB_FAIL(c_expr->set_enum_set_values(expr->get_enum_set_values()))) {
LOG_WARN("failed to set enum_set_values", K(*expr), K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(c_expr->extract_info())) {
LOG_WARN("extract const raw expr info failed", K(ret));
} else {
expr = c_expr;
}
}
}
return ret;
}
int ObRawExprUtils::copy_exprs(ObRawExprFactory& expr_factory, const ObIArray<ObGroupbyExpr>& origin,
ObIArray<ObGroupbyExpr>& dest, const uint64_t copy_types, bool use_new_allocator)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < origin.count(); i++) {
ObGroupbyExpr dest_item;
if (OB_FAIL(ObRawExprUtils::copy_exprs(
expr_factory, origin.at(i).groupby_exprs_, dest_item.groupby_exprs_, copy_types, use_new_allocator))) {
LOG_WARN("failed to copy exprs.", K(ret));
} else if (OB_FAIL(dest.push_back(dest_item))) {
LOG_WARN("failed to push back into dest.", K(ret));
} else { /*do nothing.*/
}
}
return ret;
}
int ObRawExprUtils::copy_expr(ObRawExprFactory& expr_factory, const ObRawExpr* origin, ObRawExpr*& dest,
const uint64_t copy_types, bool use_new_allocator)
{
int ret = OB_SUCCESS;
bool need_copy = true;
bool copy_share_expr = (COPY_REF_SHARED == copy_types) || use_new_allocator;
if (NULL == origin) {
need_copy = false;
dest = NULL;
} else if (copy_share_expr) {
// current expr should be copied no matter it is shared or not
} else if (origin->is_column_ref_expr() || origin->is_query_ref_expr() || origin->is_aggr_expr() ||
origin->is_win_func_expr() || origin->is_set_op_expr() || is_pseudo_column_like_expr(*origin) ||
origin->has_flag(IS_SHARED_REF) || origin->has_flag(IS_PARAM)) {
// a shared expr is not copied in default mode
dest = const_cast<ObRawExpr*>(origin);
need_copy = false;
}
if (OB_SUCC(ret) && need_copy) {
// deep copy here
ObRawExpr::ExprClass expr_class = origin->get_expr_class();
switch (expr_class) {
case ObRawExpr::EXPR_QUERY_REF: {
// this is not deep copy, should change !!!
ObQueryRefRawExpr* dest_query_ref = NULL;
const ObQueryRefRawExpr* origin_query_ref = static_cast<const ObQueryRefRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_query_ref)) ||
OB_ISNULL(dest_query_ref)) {
LOG_WARN("failed to allocate raw expr", K(dest_query_ref), K(ret));
} else if (OB_FAIL(dest_query_ref->assign(*origin_query_ref))) {
LOG_WARN("failed to assign query ref", K(ret));
} else {
dest = dest_query_ref;
}
break;
}
case ObRawExpr::EXPR_COLUMN_REF: {
ObColumnRefRawExpr* dest_column_ref = NULL;
const ObColumnRefRawExpr* origin_column_ref = static_cast<const ObColumnRefRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(T_REF_COLUMN, dest_column_ref)) || OB_ISNULL(dest_column_ref)) {
LOG_WARN("failed to allocate raw expr", K(dest_column_ref), K(ret));
} else if (OB_FAIL(dest_column_ref->deep_copy(expr_factory, *origin_column_ref, use_new_allocator))) {
LOG_WARN("failed to deep copy column ref", K(ret));
} else {
dest = dest_column_ref;
}
break;
}
case ObRawExpr::EXPR_AGGR: {
ObAggFunRawExpr* dest_agg = NULL;
const ObAggFunRawExpr* origin_agg = static_cast<const ObAggFunRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_agg)) || OB_ISNULL(dest_agg)) {
LOG_WARN("failed to allocate raw expr", K(dest_agg), K(ret));
} else if (OB_FAIL(dest_agg->deep_copy(expr_factory, *origin_agg, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy agg expr", K(ret));
} else {
dest = dest_agg;
}
break;
}
case ObRawExpr::EXPR_CONST: {
ObConstRawExpr* dest_const = NULL;
const ObConstRawExpr* origin_const = static_cast<const ObConstRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_const)) || OB_ISNULL(dest_const)) {
LOG_WARN("failed to allocate raw expr", K(dest_const), K(ret));
} else if (OB_FAIL(dest_const->deep_copy(expr_factory, *origin_const, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy const expr", K(ret));
} else {
dest = dest_const;
}
break;
}
case ObRawExpr::EXPR_OPERATOR: {
const ObOpRawExpr* origin_op = static_cast<const ObOpRawExpr*>(origin);
if (origin->is_obj_access_expr()) {
const ObObjAccessRawExpr* origin_oa = static_cast<const ObObjAccessRawExpr*>(origin);
ObObjAccessRawExpr* dest_oa = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_oa))) {
LOG_WARN("failed to allocate raw expr", K(ret));
} else if (OB_ISNULL(dest_oa)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is NULL", K(dest_oa), K(ret));
} else if (OB_FAIL(dest_oa->deep_copy(expr_factory, *origin_oa, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to assign", K(*dest_oa), K(ret));
} else {
dest = dest_oa;
}
} else if (origin->is_assoc_index_expr()) {
ret = OB_NOT_SUPPORTED;
} else if (T_SP_CPARAM == origin->get_expr_type()) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "call procedure");
} else if (T_FUN_PL_INTEGER_CHECKER == origin->get_expr_type()) {
ret = OB_NOT_SUPPORTED;
} else {
ObOpRawExpr* dest_op = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_op)) || OB_ISNULL(dest_op)) {
LOG_WARN("failed to allocate raw expr", K(dest_op), K(ret));
} else if (OB_FAIL(dest_op->deep_copy(expr_factory, *origin_op, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy op expr", K(ret));
} else {
dest = dest_op;
}
}
break;
}
case ObRawExpr::EXPR_CASE_OPERATOR: {
ObCaseOpRawExpr* dest_case = NULL;
const ObCaseOpRawExpr* origin_case = static_cast<const ObCaseOpRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_case)) || OB_ISNULL(dest_case)) {
LOG_WARN("failed to allocate raw expr", K(dest_case), K(ret));
} else if (OB_FAIL(dest_case->deep_copy(expr_factory, *origin_case, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy case expr", K(ret));
} else {
dest = dest_case;
}
break;
}
case ObRawExpr::EXPR_SYS_FUNC: {
if (T_FUN_SYS_SEQ_NEXTVAL == origin->get_expr_type()) {
ObSequenceRawExpr* dest_seq = NULL;
const ObSequenceRawExpr* origin_seq = static_cast<const ObSequenceRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_seq))) {
LOG_WARN("failed to allocate raw expr", K(dest_seq), K(ret));
} else if (OB_ISNULL(dest_seq)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is NULL", K(dest_seq), K(ret));
} else if (OB_FAIL(dest_seq->deep_copy(expr_factory, *origin_seq, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy sys func expr", K(ret));
} else {
dest = dest_seq;
}
} else if (T_FUN_NORMAL_UDF == origin->get_expr_type()) {
ObNormalDllUdfRawExpr* dest_nudf = NULL;
const ObNormalDllUdfRawExpr* origin_nudf = static_cast<const ObNormalDllUdfRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_nudf))) {
LOG_WARN("failed to allocate raw expr", K(dest_nudf), K(ret));
} else if (OB_ISNULL(dest_nudf)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is NULL", K(dest_nudf), K(ret));
} else if (OB_FAIL(dest_nudf->deep_copy(expr_factory, *origin_nudf, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy sys func expr", K(ret));
} else {
dest = dest_nudf;
}
} else if (T_FUN_PL_COLLECTION_CONSTRUCT == origin->get_expr_type()) {
ret = OB_NOT_SUPPORTED;
} else if (T_FUN_PL_OBJECT_CONSTRUCT == origin->get_expr_type()) {
ret = OB_NOT_SUPPORTED;
} else if (T_FUN_PL_GET_CURSOR_ATTR == origin->get_expr_type()) {
ret = OB_NOT_SUPPORTED;
} else if (T_FUN_PL_SQLCODE_SQLERRM == origin->get_expr_type()) {
ObPLSQLCodeSQLErrmRawExpr* dest_scse = NULL;
const ObPLSQLCodeSQLErrmRawExpr* origin_scse = static_cast<const ObPLSQLCodeSQLErrmRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_scse))) {
LOG_WARN("failed to allocate raw expr", K(dest_scse), K(ret));
} else if (OB_ISNULL(dest_scse)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is NULL", K(dest_scse), K(ret));
} else if (OB_FAIL(dest_scse->deep_copy(expr_factory, *origin_scse, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy sys func expr", K(ret));
} else {
dest = dest_scse;
}
} else {
ObSysFunRawExpr* dest_sys = NULL;
const ObSysFunRawExpr* origin_sys = static_cast<const ObSysFunRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_sys))) {
LOG_WARN("failed to allocate raw expr", K(dest_sys), K(ret));
} else if (OB_ISNULL(dest_sys)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is NULL", K(dest_sys), K(ret));
} else if (OB_FAIL(dest_sys->deep_copy(expr_factory, *origin_sys, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy sys func expr", K(ret));
} else {
dest = dest_sys;
}
}
break;
}
case ObRawExpr::EXPR_UDF: {
ret = OB_NOT_SUPPORTED;
break;
}
case ObRawExpr::EXPR_ALIAS_REF: {
ObAliasRefRawExpr* dest_alias = NULL;
const ObAliasRefRawExpr* origin_alias = static_cast<const ObAliasRefRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_alias)) || OB_ISNULL(dest_alias)) {
LOG_WARN("failed to allocate raw expr", K(dest_alias), K(ret));
} else if (OB_FAIL(dest_alias->deep_copy(expr_factory, *origin_alias, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to copy alias", K(ret));
} else {
dest = dest_alias;
}
break;
}
case ObRawExpr::EXPR_PSEUDO_COLUMN: {
ObPseudoColumnRawExpr* dest_pseudo_column = NULL;
const ObPseudoColumnRawExpr* origin_pseudo_column = static_cast<const ObPseudoColumnRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_pseudo_column)) ||
OB_ISNULL(dest_pseudo_column)) {
LOG_WARN("failed to alocate raw expr", K(ret));
} else if (OB_FAIL(dest_pseudo_column->deep_copy(
expr_factory, *origin_pseudo_column, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to assign pseudo column", K(ret));
} else {
dest = dest_pseudo_column;
}
break;
}
case ObRawExpr::EXPR_WINDOW: {
ObWinFunRawExpr* dest_win_fun = NULL;
const ObWinFunRawExpr* origin_win_fun = static_cast<const ObWinFunRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_win_fun)) || OB_ISNULL(dest_win_fun)) {
LOG_WARN("failed to allocate raw expr", K(dest_win_fun), K(ret));
} else if (OB_FAIL(
dest_win_fun->deep_copy(expr_factory, *origin_win_fun, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy window function", K(ret));
} else {
dest = dest_win_fun;
}
break;
}
case ObRawExpr::EXPR_DOMAIN_INDEX: {
ret = OB_NOT_SUPPORTED;
LOG_WARN("not supported deep copy of domain index expr", K(ret));
break;
}
case ObRawExpr::EXPR_VAR: {
ObVarRawExpr* dest_var_expr = NULL;
const ObVarRawExpr* origin_var_expr = static_cast<const ObVarRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_var_expr)) || OB_ISNULL(dest_var_expr)) {
LOG_WARN("failed to allocate raw expr", K(dest_var_expr), K(ret));
} else if (OB_FAIL(
dest_var_expr->deep_copy(expr_factory, *origin_var_expr, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy var raw expr", K(ret));
} else {
dest = dest_var_expr;
}
break;
}
case ObRawExpr::EXPR_SET_OP: {
ObSetOpRawExpr* dest_set_op_expr = NULL;
const ObSetOpRawExpr* origin_set_op_expr = static_cast<const ObSetOpRawExpr*>(origin);
if (OB_FAIL(expr_factory.create_raw_expr(origin->get_expr_type(), dest_set_op_expr)) ||
OB_ISNULL(dest_set_op_expr)) {
LOG_WARN("failed to allocate raw expr", K(dest_set_op_expr), K(ret));
} else if (OB_FAIL(dest_set_op_expr->deep_copy(
expr_factory, *origin_set_op_expr, COPY_REF_DEFAULT, use_new_allocator))) {
LOG_WARN("failed to deep copy set op raw expr", K(ret));
} else {
dest = dest_set_op_expr;
}
break;
}
case ObRawExpr::EXPR_INVALID_CLASS:
default:
// should not reach here
break;
}
}
return ret;
}
bool ObRawExprUtils::need_column_conv(const ObExprResType& expected_type, const ObRawExpr& expr)
{
int bret = true;
if (expected_type.get_type() == expr.get_data_type()) {
bool type_matched = false;
if (expected_type.is_integer_type() || expected_type.is_temporal_type()) {
type_matched = true;
} else if (expected_type.get_collation_type() == expr.get_collation_type() &&
expected_type.get_accuracy().get_accuracy() == expr.get_accuracy().get_accuracy()) {
type_matched = true;
}
if (type_matched) {
if (expected_type.has_result_flag(OB_MYSQL_NOT_NULL_FLAG) &&
expr.get_result_type().has_result_flag(OB_MYSQL_NOT_NULL_FLAG)) {
bret = false;
} else if (!expected_type.has_result_flag(OB_MYSQL_NOT_NULL_FLAG)) {
bret = false;
} else { /*do nothing*/
}
}
}
return bret;
}
bool ObRawExprUtils::need_column_conv(const ColumnItem& column, ObRawExpr& expr)
{
int bret = true;
if (column.get_expr() != NULL && column.get_expr()->is_fulltext_column()) {
// generated column of fulltext idnex is a inner hidden column, don't need to do column convert.
bret = false;
} else if (column.get_column_type() != NULL) {
const ObExprResType& column_type = *column.get_column_type();
if (column_type.get_type() == expr.get_data_type() &&
column_type.get_collation_type() == expr.get_collation_type() &&
column_type.get_accuracy().get_accuracy() == expr.get_accuracy().get_accuracy()) {
if (column.is_not_null() && expr.get_result_type().has_result_flag(OB_MYSQL_NOT_NULL_FLAG)) {
bret = false;
} else if (!column.is_not_null()) {
bret = false;
} else { /*do nothing*/
}
} else { /*do nothing*/
}
} else { /*do nothing*/
}
return bret;
}
int ObRawExprUtils::build_column_conv_expr(ObRawExprFactory& expr_factory,
const share::schema::ObColumnSchemaV2* column_schema, ObRawExpr*& expr, const ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
CK(OB_NOT_NULL(session_info));
CK(OB_NOT_NULL(column_schema));
if (OB_SUCC(ret)) {
if (column_schema->is_fulltext_column()) {
} else if (OB_FAIL(build_column_conv_expr(session_info,
expr_factory,
column_schema->get_data_type(),
column_schema->get_collation_type(),
column_schema->get_accuracy().get_accuracy(),
column_schema->is_nullable(),
NULL,
NULL,
expr))) {
LOG_WARN("failed to build column convert expr", K(ret));
}
}
return ret;
}
int ObRawExprUtils::build_column_conv_expr(ObRawExprFactory& expr_factory, common::ObIAllocator& allocator,
const ObColumnRefRawExpr& col_ref, ObRawExpr*& expr, const ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObString column_conv_info;
const ObString& database_name = col_ref.get_database_name();
const ObString& table_name = col_ref.get_table_name();
const ObString& column_name = col_ref.get_column_name();
int64_t buff_len = database_name.length() + table_name.length() + column_name.length() + 20;
char* temp_str_buf = static_cast<char*>(allocator.alloc(buff_len));
if (OB_UNLIKELY(OB_ISNULL(temp_str_buf))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc memory", K(ret));
} else if (snprintf(temp_str_buf,
buff_len,
"\"%.*s\".\"%.*s\".\"%.*s\"",
database_name.length(),
database_name.ptr(),
table_name.length(),
table_name.ptr(),
column_name.length(),
column_name.ptr()) < 0) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("failed to generate buffer for temp_str_buf", K(ret));
} else {
column_conv_info = ObString(buff_len, static_cast<int32_t>(strlen(temp_str_buf)), temp_str_buf);
}
CK(session_info);
if (OB_SUCC(ret)) {
if (col_ref.is_fulltext_column()) {
} else if (OB_FAIL(build_column_conv_expr(session_info,
expr_factory,
col_ref.get_data_type(),
col_ref.get_collation_type(),
col_ref.get_accuracy().get_accuracy(),
!col_ref.is_not_null(),
&column_conv_info,
&col_ref.get_enum_set_values(),
expr))) {
LOG_WARN("fail to build column convert expr", K(ret));
}
}
return ret;
}
int ObRawExprUtils::build_column_conv_expr(const ObSQLSessionInfo* session_info, ObRawExprFactory& expr_factory,
const ObObjType& type, const ObCollationType& collation, const int64_t& accuracy, const bool& is_nullable,
const common::ObString* column_conv_info, const ObIArray<ObString>* type_infos, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObObjType dest_type = ObLobType == type ? ObLongTextType : type;
ObSysFunRawExpr* f_expr = NULL;
ObConstRawExpr* is_nullable_expr = NULL;
ObConstRawExpr* type_expr = NULL;
ObConstRawExpr* collation_expr = NULL;
ObConstRawExpr* accuracy_expr = NULL;
ObConstRawExpr* column_info_expr = NULL;
uint64_t def_cast_mode = 0;
CK(OB_NOT_NULL(session_info));
CK(OB_NOT_NULL(expr));
ObString column_info;
if (OB_NOT_NULL(column_conv_info)) {
column_info = *column_conv_info;
}
if (OB_FAIL(ret)) {
// do nothing ...
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_COLUMN_CONV, f_expr))) {
LOG_WARN("fail to create T_FUN_COLUMN_CONV raw expr", K(ret));
} else if (OB_FAIL(build_const_int_expr(expr_factory, ObInt32Type, static_cast<int32_t>(dest_type), type_expr))) {
LOG_WARN("fail to build const int expr", K(ret));
} else if (OB_FAIL(
build_const_int_expr(expr_factory, ObInt32Type, static_cast<int32_t>(collation), collation_expr))) {
LOG_WARN("fail to build type expr", K(ret));
} else if (OB_FAIL(build_const_int_expr(expr_factory, ObIntType, accuracy, accuracy_expr))) {
LOG_WARN("fail to build int expr", K(ret), K(accuracy));
} else if (OB_FAIL(build_const_int_expr(expr_factory, ObTinyIntType, is_nullable, is_nullable_expr))) {
LOG_WARN("fail to build bool expr", K(ret));
} else if (OB_FAIL(build_const_string_expr(
expr_factory, ObCharType, column_info, CS_TYPE_UTF8MB4_GENERAL_CI, column_info_expr))) {
LOG_WARN("fail to build column info expr", K(ret));
} else if (OB_FAIL(f_expr->add_param_expr(type_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(f_expr->add_param_expr(collation_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(f_expr->add_param_expr(accuracy_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(f_expr->add_param_expr(is_nullable_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(f_expr->add_param_expr(expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (GET_MIN_CLUSTER_VERSION() >= CLUSTER_VERSION_2273 && OB_FAIL(f_expr->add_param_expr(column_info_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (ObSQLUtils::get_default_cast_mode(false, /* explicit_cast */
0, /* result_flag */
session_info,
def_cast_mode)) {
LOG_WARN("fail to get_default_cast_mode", K(ret));
} else {
if (ob_is_enumset_tc(dest_type) && OB_NOT_NULL(type_infos)) {
ObExprColumnConv* column_conv = NULL;
ObExprOperator* op = NULL;
if (OB_ISNULL(op = f_expr->get_op())) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("allocate expr operator failed", K(ret));
} else if (OB_ISNULL(column_conv = static_cast<ObExprColumnConv*>(op))) {
LOG_WARN("fail to cast ObExprOperator* to ObExprColumnConv*", K(ret));
} else if (OB_FAIL(column_conv->shallow_copy_str_values(*type_infos))) {
LOG_WARN("fail to shallow_copy_str_values", K(ret));
} else if (f_expr->set_enum_set_values(*type_infos)) {
LOG_WARN("fail to set_enum_set_values", K(ret));
} else { /*success*/
}
}
if (OB_SUCC(ret)) {
f_expr->set_extra(def_cast_mode);
f_expr->set_func_name(ObString::make_string(N_COLUMN_CONV));
f_expr->set_data_type(dest_type);
f_expr->set_expr_type(T_FUN_COLUMN_CONV);
if (expr->is_for_generated_column()) {
f_expr->set_for_generated_column();
}
expr = f_expr;
if (OB_FAIL(expr->formalize(session_info))) {
LOG_WARN("fail to extract info", K(ret));
}
}
}
return ret;
}
// invoker should remember to add to stmt's expr_store to free the memory
// stmt->store_expr(expr)
int ObRawExprUtils::build_const_int_expr(
ObRawExprFactory& expr_factory, ObObjType type, int64_t int_value, ObConstRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObConstRawExpr* c_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(static_cast<ObItemType>(type), c_expr))) {
LOG_WARN("fail to create const raw c_expr", K(ret));
} else {
ObObj obj;
obj.set_int(type, int_value);
c_expr->set_value(obj);
expr = c_expr;
}
return ret;
}
int ObRawExprUtils::build_const_number_expr(
ObRawExprFactory& expr_factory, ObObjType type, const number::ObNumber value, ObConstRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObConstRawExpr* c_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(static_cast<ObItemType>(type), c_expr))) {
LOG_WARN("fail to create const raw c_expr", K(ret));
} else {
ObObj obj;
obj.set_number(type, value);
c_expr->set_value(obj);
expr = c_expr;
}
return ret;
}
int ObRawExprUtils::build_var_int_expr(ObRawExprFactory& expr_factory, ObConstRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObConstRawExpr* c_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_VAR_INT, c_expr))) {
LOG_WARN("fail to create const raw c_expr", K(ret));
} else {
ObObj obj;
obj.set_int(0);
c_expr->set_value(obj);
expr = c_expr;
}
return ret;
}
int ObRawExprUtils::build_const_string_expr(ObRawExprFactory& expr_factory, ObObjType type,
const ObString& string_value, ObCollationType cs_type, ObConstRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObConstRawExpr* c_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(static_cast<ObItemType>(type), c_expr))) {
LOG_WARN("fail to create const raw c_expr", K(ret));
} else {
ObObj obj;
obj.set_string(type, string_value);
obj.set_collation_type(cs_type);
c_expr->set_value(obj);
expr = c_expr;
}
return ret;
}
int ObRawExprUtils::build_variable_expr(
ObRawExprFactory& expr_factory, const ObExprResType& result_type, ObVarRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObVarRawExpr* c_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_EXEC_VAR, c_expr))) {
LOG_WARN("fail to create const raw c_expr", K(ret));
} else {
c_expr->set_result_type(result_type);
expr = c_expr;
}
return ret;
}
int ObRawExprUtils::build_null_expr(ObRawExprFactory& expr_factory, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObConstRawExpr* c_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_NULL, c_expr))) {
LOG_WARN("create const expr failed", K(ret));
} else {
ObObj obj;
obj.set_null();
c_expr->set_value(obj);
expr = c_expr;
}
return ret;
}
int ObRawExprUtils::build_trim_expr(const ObColumnSchemaV2* column_schema, ObRawExprFactory& expr_factory,
ObSQLSessionInfo* session_info, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* trim_expr = NULL;
int64_t trim_type = 2;
ObConstRawExpr* type_expr = NULL;
ObConstRawExpr* pattem_expr = NULL;
ObString padding_char(1, &OB_PADDING_CHAR);
ObCollationType padding_char_cs_type = CS_TYPE_INVALID;
if (NULL == column_schema || NULL == expr) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(column_schema), K(expr));
} else {
bool is_cs_nonascii = ObCharset::is_cs_nonascii(column_schema->get_collation_type());
padding_char_cs_type =
is_cs_nonascii ? ObCharset::get_default_collation(CHARSET_UTF8MB4) : column_schema->get_collation_type();
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_INNER_TRIM, trim_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_ISNULL(trim_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to store expr", K(ret));
} else if (OB_FAIL(build_const_int_expr(expr_factory, ObIntType, trim_type, type_expr))) {
LOG_WARN("fail to build type expr", K(ret));
} else if (trim_expr->add_param_expr(type_expr)) {
LOG_WARN("fail to add param expr", K(ret), K(*type_expr));
} else if (OB_FAIL(
build_const_string_expr(expr_factory, ObCharType, padding_char, padding_char_cs_type, pattem_expr))) {
LOG_WARN("fail to build pattem expr", K(ret));
} else if (FALSE_IT(static_cast<ObConstRawExpr*>(pattem_expr)->get_value().set_collation_level(CS_LEVEL_IMPLICIT))) {
LOG_WARN("fail to set collation type", K(ret));
} else if (trim_expr->add_param_expr(pattem_expr)) {
LOG_WARN("fail to add param expr", K(ret));
} else if (trim_expr->add_param_expr(expr)) {
LOG_WARN("fail to add param expr", K(ret), K(*expr));
} else {
trim_expr->set_data_type(ObCharType);
trim_expr->set_func_name(ObString::make_string(N_INNER_TRIM));
if (expr->is_for_generated_column()) {
trim_expr->set_for_generated_column();
}
expr = trim_expr;
if (OB_FAIL(expr->formalize(session_info))) {
LOG_WARN("fail to extract info", K(ret));
}
}
return ret;
}
int ObRawExprUtils::build_pad_expr(ObRawExprFactory& expr_factory, bool is_char, const ObColumnSchemaV2* column_schema,
ObRawExpr*& expr, sql::ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* pad_expr = NULL;
ObConstRawExpr* pading_word_expr = NULL;
ObConstRawExpr* length_expr = NULL;
ObString padding_char(1, &OB_PADDING_CHAR);
ObString padding_binary(1, &OB_PADDING_BINARY);
ObObjType padding_expr_type = ObMaxType;
ObCollationType padding_expr_collation = CS_TYPE_INVALID;
if (NULL == column_schema) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("inalid argument", K(column_schema));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_PAD, pad_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_ISNULL(pad_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("pad expr is null", K(ret));
} else if (FALSE_IT(padding_expr_type =
ob_is_nstring_type(column_schema->get_data_type()) ? ObNVarchar2Type : ObVarcharType)) {
} else if (FALSE_IT(padding_expr_collation = ob_is_nstring_type(column_schema->get_data_type())
? CS_TYPE_UTF8MB4_BIN
: column_schema->get_collation_type())) {
} else if (is_char && OB_FAIL(build_const_string_expr(
expr_factory, padding_expr_type, padding_char, padding_expr_collation, pading_word_expr))) {
LOG_WARN("fail to build pading word expr", K(ret));
} else if (!is_char &&
OB_FAIL(build_const_string_expr(
expr_factory, padding_expr_type, padding_binary, padding_expr_collation, pading_word_expr))) {
LOG_WARN("fail to build pading word expr", K(ret));
} else if (OB_FAIL(build_const_int_expr(expr_factory, ObIntType, column_schema->get_data_length(), length_expr))) {
LOG_WARN("fail to build length expr", K(ret));
} else if (OB_FAIL(pad_expr->add_param_expr(expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(pad_expr->add_param_expr(pading_word_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(pad_expr->add_param_expr(length_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else {
ObAccuracy padding_accuracy = pading_word_expr->get_accuracy();
padding_accuracy.set_length_semantics(column_schema->get_accuracy().get_length_semantics());
pading_word_expr->set_accuracy(padding_accuracy);
pad_expr->set_data_type(padding_expr_type);
pad_expr->set_func_name(ObString::make_string(N_PAD));
if (expr->is_for_generated_column()) {
pad_expr->set_for_generated_column();
}
expr = pad_expr;
if (OB_FAIL(expr->formalize(session_info))) {
LOG_WARN("fail to extract info", K(ret));
}
LOG_DEBUG("build pad expr", KPC(pading_word_expr), KPC(pad_expr));
}
return ret;
}
int ObRawExprUtils::build_nvl_expr(ObRawExprFactory& expr_factory, const ColumnItem* column_item, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* nvl_func_expr = NULL;
ObSysFunRawExpr* now_func_expr = NULL;
if (NULL == column_item || NULL == expr) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("fail bo build length expr", K(column_item), K(expr));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_TIMESTAMP_NVL, nvl_func_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_CUR_TIMESTAMP, now_func_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_ISNULL(nvl_func_expr) || OB_ISNULL(now_func_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("func expr is null", K(nvl_func_expr), K(now_func_expr));
} else {
nvl_func_expr->set_expr_type(T_FUN_SYS_TIMESTAMP_NVL);
nvl_func_expr->set_func_name(ObString::make_string(N_TIMESTAMP_NVL));
nvl_func_expr->set_data_type(ObTimestampType);
nvl_func_expr->set_accuracy(column_item->get_column_type()->get_accuracy());
now_func_expr->set_expr_type(T_FUN_SYS_CUR_TIMESTAMP);
now_func_expr->set_data_type(ObDateTimeType);
now_func_expr->set_accuracy(column_item->get_column_type()->get_accuracy()); // the accuracy of column
now_func_expr->set_func_name(ObString::make_string(N_CUR_TIMESTAMP));
}
if (OB_SUCC(ret)) {
if (OB_FAIL(nvl_func_expr->add_param_expr(expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(nvl_func_expr->add_param_expr(now_func_expr))) {
LOG_WARN("fail to add param expr", K(ret));
} else {
expr = nvl_func_expr;
}
}
return ret;
}
int ObRawExprUtils::build_lnnvl_expr(ObRawExprFactory& expr_factory, ObRawExpr* param_expr, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* lnnvl_expr = NULL;
expr = NULL;
if (OB_ISNULL(param_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(param_expr), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_LNNVL, lnnvl_expr))) {
LOG_WARN("failed to create raw expr", K(ret));
} else if (OB_ISNULL(lnnvl_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null expr", K(ret));
} else {
lnnvl_expr->set_func_name(ObString::make_string(N_LNNVL));
lnnvl_expr->set_data_type(ObTinyIntType);
if (OB_FAIL(lnnvl_expr->add_param_expr(param_expr))) {
LOG_WARN("failed to add param expr", K(ret));
} else {
expr = lnnvl_expr;
}
}
return ret;
}
int ObRawExprUtils::build_equal_last_insert_id_expr(
ObRawExprFactory& expr_factory, ObRawExpr*& expr, ObSQLSessionInfo* session)
{
int ret = OB_SUCCESS;
ObOpRawExpr* equal_expr = NULL;
ObSysFunRawExpr* last_insert_id = NULL;
if (OB_ISNULL(expr) || OB_UNLIKELY(!expr->is_op_expr())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expr));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_EQ, equal_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_LAST_INSERT_ID, last_insert_id))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_ISNULL(equal_expr) || OB_ISNULL(last_insert_id)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(equal_expr), K(last_insert_id));
} else {
last_insert_id->set_func_name(ObString::make_string(N_LAST_INSERT_ID));
last_insert_id->set_data_type(ObIntType);
if (OB_FAIL(equal_expr->add_param_expr(expr->get_param_expr(0)))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(equal_expr->add_param_expr(last_insert_id))) {
LOG_WARN("fail to add param expr", K(ret));
} else if (OB_FAIL(equal_expr->formalize(session))) {
LOG_WARN("fail to formalize expr", K(*equal_expr), K(ret));
} else {
expr = equal_expr;
}
}
return ret;
}
int ObRawExprUtils::build_get_user_var(ObRawExprFactory& expr_factory, const ObString& var_name, ObRawExpr*& expr,
const ObSQLSessionInfo* session_info /* = NULL */, ObQueryCtx* query_ctx /* = NULL */,
ObIArray<ObUserVarIdentRawExpr*>* user_var_exprs /* = NULL*/)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* f_expr = NULL;
ObUserVarIdentRawExpr* var_expr = NULL;
ObIArray<ObUserVarIdentRawExpr*>* all_vars = (NULL == query_ctx ? NULL : &query_ctx->all_user_variable_);
bool query_has_udf = (NULL == query_ctx ? false : query_ctx->has_udf_);
if (OB_FAIL(expr_factory.create_raw_expr(T_OP_GET_USER_VAR, f_expr))) {
LOG_WARN("create ObOpRawExpr failed", K(ret));
} else {
ObString str = var_name;
ObCharset::casedn(CS_TYPE_UTF8MB4_GENERAL_CI, str);
ObObj val;
val.set_varchar(str);
val.set_collation_type(ObCharset::get_system_collation());
val.set_collation_level(CS_LEVEL_IMPLICIT);
if (NULL != all_vars) {
for (int64_t i = 0; OB_SUCC(ret) && i < all_vars->count(); ++i) {
if (OB_ISNULL(all_vars->at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get null user var ident expr", K(ret));
} else if (all_vars->at(i)->is_same_variable(val)) {
var_expr = all_vars->at(i);
}
}
}
if (OB_SUCC(ret) && NULL == var_expr) {
if (OB_FAIL(expr_factory.create_raw_expr(T_USER_VARIABLE_IDENTIFIER, var_expr))) {
LOG_WARN("fail to create user var ident expr", K(ret));
} else if (NULL != all_vars && OB_FAIL(all_vars->push_back(var_expr))) {
LOG_WARN("failed to push back var expr", K(ret));
} else {
var_expr->set_value(val);
}
}
if (OB_SUCC(ret)) {
var_expr->set_query_has_udf(query_has_udf);
if (OB_FAIL(f_expr->set_param_expr(var_expr))) {
LOG_WARN("failed to add param expr", K(ret));
} else if (NULL != user_var_exprs && OB_FAIL(add_var_to_array_no_dup(*user_var_exprs, var_expr))) {
LOG_WARN("failed to add var to array no dup", K(ret));
} else {
expr = f_expr;
}
}
}
if (OB_SUCC(ret) && NULL != session_info) {
if (OB_FAIL(expr->formalize(session_info))) {
LOG_WARN("failed to formalize", K(ret));
}
}
return ret;
}
int ObRawExprUtils::build_get_sys_var(ObRawExprFactory& expr_factory, const ObString& var_name,
ObSetVar::SetScopeType var_scope, ObRawExpr*& expr, const ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObConstRawExpr* name_expr = NULL;
ObConstRawExpr* scope_expr = NULL;
ObSysFunRawExpr* get_sys_var_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_VARCHAR, name_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_INT, scope_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_GET_SYS_VAR, get_sys_var_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_ISNULL(name_expr) || OB_ISNULL(scope_expr) || OB_ISNULL(get_sys_var_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(name_expr), K(scope_expr), K(get_sys_var_expr));
} else {
ObObj name_obj;
name_obj.set_varchar(var_name);
name_obj.set_collation_level(CS_LEVEL_SYSCONST);
name_obj.set_collation_type(ObCharset::get_system_collation());
name_expr->set_value(name_obj);
ObObj scope_obj;
scope_obj.set_int(static_cast<int64_t>(var_scope));
scope_expr->set_expr_type(static_cast<ObItemType>(scope_obj.get_type()));
scope_expr->set_value(scope_obj);
expr = get_sys_var_expr;
get_sys_var_expr->set_expr_type(T_OP_GET_SYS_VAR);
get_sys_var_expr->set_func_name(ObString::make_string(N_GET_SYS_VAR));
ret = get_sys_var_expr->set_param_exprs(name_expr, scope_expr);
}
if (OB_SUCC(ret) && NULL != session_info) {
if (OB_FAIL(expr->formalize(session_info))) {
LOG_WARN("failed to formalize", K(ret));
}
}
return ret;
}
int ObRawExprUtils::build_calc_part_id_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session,
uint64_t ref_table_id, ObPartitionLevel part_level, ObRawExpr* part_expr, ObRawExpr* subpart_expr, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
expr = NULL;
ObSysFunRawExpr* calc_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS, calc_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_ISNULL(calc_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("fail to create raw expr", K(calc_expr), K(ret));
} else {
if (schema::PARTITION_LEVEL_TWO == part_level) {
if (OB_ISNULL(part_expr) || OB_ISNULL(subpart_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("subpart_expr is null", K(subpart_expr), K(ret));
} else if (OB_FAIL(calc_expr->add_param_expr(part_expr)) || OB_FAIL(calc_expr->add_param_expr(subpart_expr))) {
LOG_WARN("fail to add param expr", K(ret), K(*part_expr), K(*subpart_expr));
}
} else if (schema::PARTITION_LEVEL_ONE == part_level) {
if (OB_ISNULL(part_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("part_expr is null", K(part_level), K(part_expr), K(ret));
} else if (OB_FAIL(calc_expr->add_param_expr(part_expr))) {
LOG_WARN("fail to add param expr", K(ret), K(*part_expr));
}
}
if (OB_SUCC(ret)) {
ObString func_name;
if (OB_FAIL(ob_write_string(expr_factory.get_allocator(), ObString("calc_partition_id"), func_name))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Malloc function name failed", K(ret));
} else {
calc_expr->set_func_name(func_name);
calc_expr->set_extra(ref_table_id);
}
if (OB_SUCC(ret)) {
if (OB_FAIL(calc_expr->formalize(&session))) {
LOG_WARN("fail to formalize expr", K(ret), K(calc_expr));
} else {
expr = calc_expr;
}
}
}
}
return ret;
}
int ObRawExprUtils::build_get_package_var(ObRawExprFactory& expr_factory, uint64_t package_id, int64_t var_idx,
ObExprResType* result_type, ObRawExpr*& expr, const ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* f_expr = NULL;
ObConstRawExpr* c_expr1 = NULL;
ObConstRawExpr* c_expr2 = NULL;
ObConstRawExpr* c_expr3 = NULL;
OZ(expr_factory.create_raw_expr(T_OP_GET_PACKAGE_VAR, f_expr));
OZ(build_const_int_expr(expr_factory, ObUInt64Type, package_id, c_expr1));
OZ(f_expr->add_param_expr(c_expr1));
OZ(build_const_int_expr(expr_factory, ObIntType, var_idx, c_expr2));
OZ(f_expr->add_param_expr(c_expr2));
OZ(build_const_int_expr(expr_factory, ObIntType, reinterpret_cast<int64>(result_type), c_expr3));
OZ(f_expr->add_param_expr(c_expr3));
OX(f_expr->set_func_name(ObString::make_string(N_GET_PACKAGE_VAR)));
OX(expr = f_expr);
CK(OB_NOT_NULL(session_info));
OZ(expr->formalize(session_info));
return ret;
}
int ObRawExprUtils::build_get_subprogram_var(ObRawExprFactory& expr_factory, uint64_t package_id, uint64_t routine_id,
int64_t var_idx, ObExprResType* result_type, ObRawExpr*& expr, const ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* f_expr = NULL;
ObConstRawExpr* c_expr1 = NULL;
ObConstRawExpr* c_expr2 = NULL;
ObConstRawExpr* c_expr3 = NULL;
ObConstRawExpr* c_expr4 = NULL;
OZ(expr_factory.create_raw_expr(T_OP_GET_SUBPROGRAM_VAR, f_expr));
OZ(build_const_int_expr(expr_factory, ObUInt64Type, package_id, c_expr1));
OZ(f_expr->add_param_expr(c_expr1));
OZ(build_const_int_expr(expr_factory, ObUInt64Type, routine_id, c_expr2));
OZ(f_expr->add_param_expr(c_expr2));
OZ(build_const_int_expr(expr_factory, ObIntType, var_idx, c_expr3));
OZ(f_expr->add_param_expr(c_expr3));
OZ(build_const_int_expr(expr_factory, ObIntType, reinterpret_cast<int64>(result_type), c_expr4));
OZ(f_expr->add_param_expr(c_expr4));
OX(f_expr->set_func_name(ObString::make_string(N_GET_SUBPROGRAM_VAR)));
OX(expr = f_expr);
CK(OB_NOT_NULL(session_info));
OZ(expr->formalize(session_info));
return ret;
}
int ObRawExprUtils::create_equal_expr(ObRawExprFactory& expr_factory, ObSQLSessionInfo* session_info,
const ObRawExpr* val_ref, const ObRawExpr* col_ref, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* equal_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_OP_EQ, equal_expr))) {
LOG_WARN("create equal expr failed", K(ret));
} else if (OB_ISNULL(expr = equal_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("equal expr is null");
} else if (OB_FAIL(equal_expr->set_param_exprs(const_cast<ObRawExpr*>(col_ref), const_cast<ObRawExpr*>(val_ref)))) {
LOG_WARN("set param expr failed", K(ret));
} else if (OB_FAIL(equal_expr->formalize(session_info))) {
LOG_WARN("formalize equal expr failed", K(ret));
} else {
}
return ret;
}
int ObRawExprUtils::create_double_op_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo* session_info,
ObItemType expr_type, ObRawExpr*& add_expr, const ObRawExpr* left_expr, const ObRawExpr* right_expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* op_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(expr_type, op_expr))) {
LOG_WARN("create add op expr failed", K(ret));
} else if (OB_ISNULL(add_expr = op_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null");
} else if (OB_FAIL(op_expr->set_param_exprs(const_cast<ObRawExpr*>(left_expr), const_cast<ObRawExpr*>(right_expr)))) {
LOG_WARN("set param exprs failed", K(ret));
} else if (OB_FAIL(op_expr->formalize(session_info))) {
LOG_WARN("formalize add operator failed", K(ret));
}
return ret;
}
int ObRawExprUtils::make_set_op_expr(ObRawExprFactory& expr_factory, int64_t idx, ObItemType set_op_type,
const ObExprResType& res_type, ObSQLSessionInfo* session_info, ObRawExpr*& out_expr)
{
int ret = OB_SUCCESS;
ObSetOpRawExpr* set_expr = NULL;
if (OB_UNLIKELY(set_op_type <= T_OP_SET) || OB_UNLIKELY(set_op_type > T_OP_EXCEPT)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknow set operator type", K(set_op_type));
} else if (OB_FAIL(expr_factory.create_raw_expr(set_op_type, set_expr))) {
LOG_WARN("create set op raw expr failed", K(ret));
} else if (OB_ISNULL(out_expr = set_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("out expr is null");
} else if (OB_FAIL(set_expr->add_flag(IS_SET_OP))) {
LOG_WARN("failed to add flag IS_SET_OP", K(ret));
} else {
set_expr->set_result_type(res_type);
set_expr->set_idx(idx);
if (session_info != NULL && OB_FAIL(set_expr->formalize(session_info))) {
LOG_WARN("formalize set expr failed", K(ret));
}
}
return ret;
}
int ObRawExprUtils::merge_variables(const ObIArray<ObVarInfo>& src_vars, ObIArray<ObVarInfo>& dst_vars)
{
int ret = OB_SUCCESS;
int64_t N = src_vars.count();
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
const ObVarInfo& var = src_vars.at(i);
bool found = false;
int64_t M = dst_vars.count();
for (int64_t j = 0; j < M; ++j) {
if (var == dst_vars.at(j)) {
found = true;
break;
}
} // end for
if (!found) {
ret = dst_vars.push_back(var);
}
} // end for
return ret;
}
int ObRawExprUtils::get_array_param_index(const ObRawExpr* expr, int64_t& param_index)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(expr));
} else if (expr->is_const_expr()) {
if (expr->get_result_type().get_param().is_ext()) {
const ObConstRawExpr* c_expr = static_cast<const ObConstRawExpr*>(expr);
if (OB_FAIL(c_expr->get_value().get_unknown(param_index))) {
LOG_WARN("get param index failed", K(ret), K(c_expr->get_value()));
}
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && OB_INVALID_INDEX == param_index && i < expr->get_param_count(); ++i) {
if (OB_FAIL(get_array_param_index(expr->get_param_expr(i), param_index))) {
LOG_WARN("get array param index failed", K(ret), KPC(expr));
}
}
}
return ret;
}
int ObRawExprUtils::get_item_count(const ObRawExpr* expr, int64_t& count)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(expr));
} else if (expr->is_column_ref_expr()) {
const ObColumnRefRawExpr* col_ref = static_cast<const ObColumnRefRawExpr*>(expr);
if (col_ref->is_generated_column()) {
ret = get_item_count(col_ref->get_dependant_expr(), count);
} else {
++count;
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); i++) {
if (OB_ISNULL(expr->get_param_expr(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get invalie expr", K(i), K(ret));
} else if (OB_FAIL(get_item_count(expr->get_param_expr(i), count))) {
LOG_WARN("fail to get item count", K(ret));
}
}
if (OB_SUCC(ret)) {
count++;
}
}
return ret;
}
int ObRawExprUtils::build_column_expr(
ObRawExprFactory& expr_factory, const ObColumnSchemaV2& column_schema, ObColumnRefRawExpr*& column_expr)
{
int ret = OB_SUCCESS;
ObString database_name;
ObString table_name;
ObString column_name;
if (OB_FAIL(expr_factory.create_raw_expr(T_REF_COLUMN, column_expr))) {
LOG_WARN("create column expr failed", K(ret));
} else if (OB_ISNULL(column_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column_expr is null");
} else if (OB_FAIL(init_column_expr(column_schema, *column_expr))) {
LOG_WARN("init column expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::build_alias_column_expr(
ObRawExprFactory& expr_factory, ObRawExpr* ref_expr, int32_t alias_level, ObAliasRefRawExpr*& alias_expr)
{
int ret = OB_SUCCESS;
if (OB_FAIL(expr_factory.create_raw_expr(T_REF_ALIAS_COLUMN, alias_expr))) {
LOG_WARN("create alias column expr failed", K(ret));
} else if (OB_ISNULL(alias_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("alias column expr is null", K(ret));
} else {
alias_expr->set_expr_level(alias_level);
alias_expr->set_ref_expr(ref_expr);
}
return ret;
}
int ObRawExprUtils::build_query_output_ref(
ObRawExprFactory& expr_factory, ObQueryRefRawExpr* query_ref, int64_t project_index, ObAliasRefRawExpr*& alias_expr)
{
int ret = OB_SUCCESS;
ObSelectStmt* sel_stmt = NULL;
ObRawExpr* real_ref_expr = NULL;
if (OB_ISNULL(query_ref) || OB_ISNULL(sel_stmt = query_ref->get_ref_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("query ref expr is invalid", K(ret), K(query_ref), K(sel_stmt));
} else if (project_index < 0 || project_index >= query_ref->get_ref_stmt()->get_select_item_size() ||
OB_ISNULL(real_ref_expr = sel_stmt->get_select_item(project_index).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("project index is invalid", K(ret), K(project_index), K(real_ref_expr));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_REF_ALIAS_COLUMN, alias_expr))) {
LOG_WARN("create alias column expr failed", K(ret));
} else if (OB_ISNULL(alias_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("alias column expr is null", K(ret));
} else {
alias_expr->set_expr_level(query_ref->get_expr_level());
alias_expr->set_query_output(query_ref, project_index);
alias_expr->set_result_type(real_ref_expr->get_result_type());
}
return ret;
}
bool ObRawExprUtils::is_same_column_ref(const ObRawExpr* column_ref1, const ObRawExpr* column_ref2)
{
// need to compare real node in alias ref.
const ObRawExpr* left_real_ref = column_ref1;
const ObRawExpr* right_real_ref = column_ref2;
while (left_real_ref != NULL && T_REF_ALIAS_COLUMN == left_real_ref->get_expr_type()) {
left_real_ref = static_cast<const ObAliasRefRawExpr*>(left_real_ref)->get_ref_expr();
}
while (right_real_ref != NULL && T_REF_ALIAS_COLUMN == right_real_ref->get_expr_type()) {
right_real_ref = static_cast<const ObAliasRefRawExpr*>(right_real_ref)->get_ref_expr();
}
bool bret = (left_real_ref == right_real_ref);
return bret;
}
int32_t ObRawExprUtils::get_generalized_column_level(const ObRawExpr& generalized_column)
{
int32_t column_level = -1;
if (generalized_column.is_column_ref_expr()) {
column_level = static_cast<const ObColumnRefRawExpr&>(generalized_column).get_expr_level();
} else if (generalized_column.is_query_ref_expr()) {
column_level = static_cast<const ObQueryRefRawExpr&>(generalized_column).get_expr_level();
} else if (generalized_column.is_aggr_expr()) {
column_level = static_cast<const ObAggFunRawExpr&>(generalized_column).get_expr_level();
} else if (generalized_column.is_set_op_expr()) {
column_level = static_cast<const ObSetOpRawExpr&>(generalized_column).get_expr_level();
}
return column_level;
}
int ObRawExprUtils::init_column_expr(const ObColumnSchemaV2& column_schema, ObColumnRefRawExpr& column_expr)
{
int ret = OB_SUCCESS;
const ObAccuracy& accuracy = column_schema.get_accuracy();
column_expr.set_ref_id(column_schema.get_table_id(), column_schema.get_column_id());
column_expr.set_data_type(column_schema.get_data_type());
column_expr.set_result_flag(calc_column_result_flag(column_schema));
column_expr.get_column_name().assign_ptr(
column_schema.get_column_name_str().ptr(), column_schema.get_column_name_str().length());
column_expr.set_column_flags(column_schema.get_column_flags());
column_expr.set_hidden_column(column_schema.is_hidden());
if (ob_is_string_type(column_schema.get_data_type()) || ob_is_enumset_tc(column_schema.get_data_type())) {
column_expr.set_collation_type(column_schema.get_collation_type());
column_expr.set_collation_level(CS_LEVEL_IMPLICIT);
} else {
column_expr.set_collation_type(CS_TYPE_BINARY);
column_expr.set_collation_level(CS_LEVEL_NUMERIC);
}
if (OB_SUCC(ret)) {
column_expr.set_accuracy(accuracy);
if (OB_FAIL(column_expr.extract_info())) {
LOG_WARN("extract column expr info failed", K(ret));
}
}
if (OB_SUCC(ret) && column_schema.is_enum_or_set()) {
if (OB_FAIL(column_expr.set_enum_set_values(column_schema.get_extended_type_info()))) {
LOG_WARN("failed to set enum set values", K(ret));
}
}
return ret;
}
int ObRawExprUtils::expr_is_order_consistent(const ObRawExpr* from, const ObRawExpr* to, bool& is_consistent)
{
int ret = OB_SUCCESS;
is_consistent = false;
if (OB_ISNULL(from) || OB_ISNULL(to)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null", K(from), K(to));
} else if (OB_FAIL(ObObjCaster::is_order_consistent(from->get_result_type(), to->get_result_type(), is_consistent))) {
LOG_WARN("check is order consistent failed", K(ret));
}
return ret;
}
int ObRawExprUtils::exprs_contain_subquery(const ObIArray<ObRawExpr*>& exprs, bool& cnt_subquery)
{
int ret = OB_SUCCESS;
cnt_subquery = false;
for (int64_t i = 0; OB_SUCC(ret) && !cnt_subquery && i < exprs.count(); ++i) {
if (OB_ISNULL(exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(i));
} else if (exprs.at(i)->has_flag(CNT_SUB_QUERY)) {
cnt_subquery = true;
}
}
return ret;
}
uint32_t ObRawExprUtils::calc_column_result_flag(const ObColumnSchemaV2& column_schema)
{
uint32_t flag = 0;
if (column_schema.is_autoincrement()) {
flag |= OB_MYSQL_AUTO_INCREMENT_FLAG;
}
if (!column_schema.is_nullable()) {
flag |= OB_MYSQL_NOT_NULL_FLAG;
}
if (column_schema.is_rowkey_column()) {
flag |= OB_MYSQL_PRI_KEY_FLAG;
flag |= OB_MYSQL_PART_KEY_FLAG;
}
if (column_schema.is_index_column()) {
flag |= OB_MYSQL_PART_KEY_FLAG;
if (column_schema.get_index_position() == 1) {
flag |= OB_MYSQL_MULTIPLE_KEY_FLAG;
}
}
if (column_schema.is_zero_fill()) {
flag |= OB_MYSQL_ZEROFILL_FLAG;
}
return flag;
}
int ObRawExprUtils::extract_int_value(const ObRawExpr* expr, int64_t& val)
{
int ret = OB_SUCCESS;
int64_t count = 0;
if (OB_ISNULL(expr) || !expr->is_const_expr()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("const expr should not be null", K(ret), K(expr));
} else {
const ObConstRawExpr* const_expr = static_cast<const ObConstRawExpr*>(expr);
if (OB_ISNULL(const_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("const expr should not be null", K(ret));
} else {
const ObObj& result = const_expr->get_value();
if (OB_FAIL(result.get_int(count))) {
LOG_WARN("failed to get int", K(ret));
} else {
val = count;
}
}
}
return ret;
}
int ObRawExprUtils::need_wrap_to_string(
ObObjType param_type, ObObjType calc_type, const bool is_same_type_need, bool& need_wrap)
{
int ret = OB_SUCCESS;
need_wrap = false;
if (!ob_is_enumset_tc(param_type)) {
// only need to convert when parameter is enum type.
} else if (param_type == calc_type && (!is_same_type_need)) {
need_wrap = false;
} else {
switch (calc_type) {
case ObNullType:
case ObTinyIntType:
case ObSmallIntType:
case ObMediumIntType:
case ObInt32Type:
case ObIntType:
case ObUTinyIntType:
case ObUSmallIntType:
case ObUMediumIntType:
case ObUInt32Type:
case ObUInt64Type:
case ObFloatType:
case ObDoubleType:
case ObUFloatType:
case ObUDoubleType:
case ObNumberType:
case ObUNumberType:
case ObNumberFloatType:
case ObBitType:
case ObYearType: {
need_wrap = false;
break;
}
case ObDateTimeType:
case ObTimestampType:
case ObDateType:
case ObTimeType:
case ObVarcharType:
case ObCharType:
case ObTinyTextType:
case ObTextType:
case ObMediumTextType:
case ObLongTextType:
case ObEnumType:
case ObSetType:
case ObTimestampTZType:
case ObTimestampLTZType:
case ObTimestampNanoType:
case ObRawType:
case ObIntervalDSType:
case ObIntervalYMType:
case ObNVarchar2Type:
case ObNCharType: {
need_wrap = true;
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid calc_type", K(param_type), K(calc_type), K(ret));
}
}
}
LOG_DEBUG("finish need_wrap_to_string", K(need_wrap), K(param_type), K(calc_type), K(ret), K(lbt()));
return ret;
}
int ObRawExprUtils::extract_param_idxs(const ObRawExpr* expr, ObIArray<int64_t>& param_idxs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null");
} else if (expr->get_expr_type() == T_QUESTIONMARK) {
const ObConstRawExpr* const_expr = static_cast<const ObConstRawExpr*>(expr);
const ObObj& val = const_expr->get_value();
int64_t param_idx = OB_INVALID_INDEX;
if (OB_FAIL(val.get_unknown(param_idx))) {
LOG_WARN("get unknown of value failed", K(ret));
} else if (OB_FAIL(param_idxs.push_back(param_idx))) {
LOG_WARN("store param idx failed", K(ret));
}
} else if (expr->has_flag(CNT_PARAM)) {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
if (OB_FAIL(extract_param_idxs(expr->get_param_expr(i), param_idxs))) {
LOG_WARN("extract param idxs failed", K(ret));
}
}
}
return ret;
}
int ObRawExprUtils::find_alias_expr(ObRawExpr* expr, ObAliasRefRawExpr*& alias_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(ret));
} else if (expr->is_alias_ref_expr()) {
alias_expr = static_cast<ObAliasRefRawExpr*>(expr);
} else if (expr->has_flag(CNT_ALIAS)) {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(find_alias_expr(expr->get_param_expr(i), alias_expr)))) {
LOG_WARN("failed to find alias expr", K(ret));
}
}
}
return ret;
}
bool ObRawExprUtils::contain_id(const ObIArray<uint64_t>& ids, const uint64_t target)
{
bool found = false;
for (int64_t i = 0; !found && i < ids.count(); ++i) {
if (ids.at(i) == target) {
found = true;
}
}
return found;
}
int ObRawExprUtils::clear_exprs_flag(const ObIArray<ObRawExpr*>& exprs, ObExprInfoFlag flag)
{
int ret = OB_SUCCESS;
ARRAY_FOREACH(exprs, i)
{
ObRawExpr* raw_expr = exprs.at(i);
if (OB_ISNULL(raw_expr)) {
LOG_WARN("get output expr fail", K(i), K(exprs));
ret = OB_ERR_UNEXPECTED;
} else if (OB_FAIL(raw_expr->clear_flag(flag))) {
LOG_WARN("fail to clear flag", K(ret));
} else {
}
}
return ret;
}
bool ObRawExprUtils::has_prefix_str_expr(
const ObRawExpr& expr, const ObColumnRefRawExpr& orig_column_expr, const ObRawExpr*& substr_expr)
{
bool bret = false;
const ObRawExpr* tmp = &expr;
if (T_FUN_COLUMN_CONV == expr.get_expr_type()) {
tmp = expr.get_param_expr(4);
}
if (T_FUN_SYS_SUBSTR == tmp->get_expr_type()) {
const ObRawExpr* param_expr1 = tmp->get_param_expr(0);
if (param_expr1 != NULL && param_expr1->is_column_ref_expr() &&
param_expr1->get_result_type().is_string_or_lob_locator_type() && param_expr1->same_as(orig_column_expr)) {
if (3 == tmp->get_param_count()) {
const ObRawExpr* param_expr2 = tmp->get_param_expr(1);
if (param_expr2 != NULL && param_expr2->is_const_expr()) {
const ObConstRawExpr* const_expr = static_cast<const ObConstRawExpr*>(param_expr2);
if (const_expr->get_value().is_int() && const_expr->get_value().get_int() == 1) {
bret = true;
substr_expr = tmp;
}
}
}
}
}
return bret;
}
int ObRawExprUtils::build_like_expr(ObRawExprFactory& expr_factory, ObSQLSessionInfo* session_info,
ObRawExpr* text_expr, ObRawExpr* pattern_expr, ObRawExpr* escape_expr, ObOpRawExpr*& like_expr)
{
int ret = OB_SUCCESS;
if (OB_FAIL(expr_factory.create_raw_expr(T_OP_LIKE, like_expr))) {
LOG_WARN("create like expr failed", K(ret));
} else if (OB_FAIL(like_expr->add_param_expr(text_expr))) {
LOG_WARN("add text expr to like expr failed", K(ret));
} else if (OB_FAIL(like_expr->add_param_expr(pattern_expr))) {
LOG_WARN("add pattern expr to like expr failed", K(ret));
} else if (OB_FAIL(like_expr->add_param_expr(escape_expr))) {
LOG_WARN("add escape expr to like expr failed", K(ret));
} else if (OB_FAIL(like_expr->formalize(session_info))) {
LOG_WARN("formalize like expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::replace_level_column(ObRawExpr*& raw_expr, ObRawExpr* to, bool& replaced)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(raw_expr) || OB_ISNULL(to)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(raw_expr), K(to));
} else if (raw_expr->get_expr_type() == T_LEVEL) {
raw_expr = to;
replaced = true;
LOG_DEBUG("replace leaf node", K(*to), K(to));
} else {
int64_t N = raw_expr->get_param_count();
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
ObRawExpr*& child_expr = raw_expr->get_param_expr(i);
if (OB_FAIL(replace_level_column(child_expr, to, replaced))) {
LOG_WARN("replace reference column failed", K(ret));
}
} // end for
}
return ret;
}
int ObRawExprUtils::build_const_bool_expr(ObRawExprFactory* expr_factory, ObRawExpr*& expr, bool b_value)
{
int ret = OB_SUCCESS;
ObConstRawExpr* bool_expr = NULL;
if (OB_ISNULL(expr_factory)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr_factory is null", K(ret));
} else if (OB_FAIL(expr_factory->create_raw_expr(T_BOOL, bool_expr))) {
LOG_WARN("build const bool expr failed", K(ret));
} else if (OB_ISNULL(bool_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("bool expr is null", K(ret));
} else {
ObObj val;
val.set_bool(b_value);
bool_expr->set_value(val);
expr = bool_expr;
}
return ret;
}
int ObRawExprUtils::check_composite_cast(ObRawExpr*& expr, ObSchemaChecker& schema_checker)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is NULL", K(ret));
} else if (T_FUN_SYS_CAST == expr->get_expr_type()) {
CK(OB_NOT_NULL(expr->get_param_expr(0)), OB_NOT_NULL(expr->get_param_expr(1)));
CK(expr->get_param_expr(1)->is_const_expr());
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
OZ(SMART_CALL(check_composite_cast(expr->get_param_expr(i), schema_checker)));
}
}
return ret;
}
/*
int ObRawExprUtils::add_expr_to_set(ObRawExprUniqueSet &expr_set, ObRawExpr *expr)
{
int ret = expr_set.exist_refactored(expr);
if (OB_HASH_EXIST == ret) {
ret = OB_SUCCESS;
// do nothing
} else if (OB_HASH_NOT_EXIST == ret) {
OZ(expr_set.set_refactored(expr));
} else {
LOG_WARN("fail to search raw expr", K(ret));
}
return ret;
}
int ObRawExprUtils::add_exprs_to_set(ObRawExprUniqueSet &expr_set, const ObIArray<ObRawExpr *> &exprs)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); i++) {
OZ(add_expr_to_set(expr_set, exprs.at(i)));
}
return ret;
}
*/
int ObRawExprUtils::flatten_raw_exprs(
const ObIArray<ObRawExpr*>& raw_exprs, ObRawExprUniqueSet& flattened_exprs, std::function<bool(ObRawExpr*)> filter)
{
int ret = OB_SUCCESS;
for (int64_t i = 0; OB_SUCC(ret) && i < raw_exprs.count(); i++) {
if (OB_FAIL(flatten_raw_expr(raw_exprs.at(i), flattened_exprs, filter))) {
LOG_WARN("fail to flatten raw expr", K(ret));
}
}
return ret;
}
int ObRawExprUtils::flatten_raw_exprs(
const ObRawExprUniqueSet& raw_exprs, ObRawExprUniqueSet& flattened_exprs, std::function<bool(ObRawExpr*)> filter)
{
return flatten_raw_exprs(raw_exprs.get_expr_array(), flattened_exprs, filter);
}
int ObRawExprUtils::flatten_raw_expr(
ObRawExpr* raw_expr, ObRawExprUniqueSet& flattened_exprs, std::function<bool(ObRawExpr*)> filter)
{
int ret = OB_SUCCESS;
bool is_stack_overflow = false;
if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
LOG_WARN("check stack overflow failed", K(ret));
} else if (is_stack_overflow) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("too deep recursive", K(ret));
} else if (OB_ISNULL(raw_expr) || !filter(raw_expr)) {
// do nothing
} else if (OB_FAIL(flattened_exprs.append(raw_expr))) {
LOG_WARN("fail to push raw expr", K(ret), K(raw_expr));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < raw_expr->get_param_count(); i++) {
if (OB_ISNULL(raw_expr->get_param_expr(i))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null");
} else if (OB_FAIL(SMART_CALL(flatten_raw_expr(raw_expr->get_param_expr(i), flattened_exprs, filter)))) {
LOG_WARN("fail to flatten raw expr", K(ret), K(i));
}
}
if (OB_SUCC(ret) && raw_expr->get_expr_type() == T_CTE_CYCLE_COLUMN) {
ObPseudoColumnRawExpr* cycle_expr = static_cast<ObPseudoColumnRawExpr*>(raw_expr);
ObRawExpr *v_raw_expr, *d_v_raw_expr;
cycle_expr->get_cte_cycle_value(v_raw_expr, d_v_raw_expr);
if (OB_ISNULL(v_raw_expr) || OB_ISNULL(d_v_raw_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Invalid raw expr", K(ret));
} else if (OB_FAIL(SMART_CALL(flatten_raw_expr(v_raw_expr, flattened_exprs, filter)))) {
LOG_WARN("fail to flatten raw expr", K(ret), K(v_raw_expr));
} else if (OB_FAIL(SMART_CALL(flatten_raw_expr(d_v_raw_expr, flattened_exprs, filter)))) {
LOG_WARN("fail to flatten raw expr", K(ret), K(d_v_raw_expr));
}
}
// flatten dependent expr
if (OB_SUCC(ret) && T_REF_COLUMN == raw_expr->get_expr_type()) {
ObColumnRefRawExpr* col_expr = static_cast<ObColumnRefRawExpr*>(raw_expr);
ObRawExpr* dependant_expr = col_expr->get_dependant_expr();
if (NULL == dependant_expr) {
// do nothing
} else if (OB_FAIL(SMART_CALL(flatten_raw_expr(dependant_expr, flattened_exprs, filter)))) {
LOG_WARN("failed to flatten raw expr", K(ret), K(*dependant_expr));
}
}
}
return ret;
}
int ObRawExprUtils::try_add_bool_expr(ObCaseOpRawExpr* parent, ObRawExprFactory& expr_factory)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(parent)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("in expr is NULL", K(ret));
} else if (OB_UNLIKELY(T_OP_ARG_CASE == parent->get_expr_type())) {
// ignore T_OP_ARG_CASE
LOG_DEBUG("ignore adding bool expr for arg_case expr", K(ret), K(*parent));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < parent->get_when_expr_size(); ++i) {
ObRawExpr* when_expr = parent->get_when_param_expr(i);
ObRawExpr* new_when_expr = NULL;
if (OB_FAIL(try_create_bool_expr(when_expr, new_when_expr, expr_factory))) {
LOG_WARN("create_bool_expr failed", K(ret));
} else if (OB_ISNULL(new_when_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new param_expr is NULL", K(ret));
} else {
parent->replace_when_param_expr(i, new_when_expr);
}
}
}
return ret;
}
int ObRawExprUtils::try_add_bool_expr(ObOpRawExpr* parent, ObRawExprFactory& expr_factory)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(parent)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("in expr is NULL", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < parent->get_param_count(); ++i) {
ObRawExpr* param_expr = parent->get_param_expr(i);
ObRawExpr* new_param_expr = NULL;
if (OB_FAIL(try_create_bool_expr(param_expr, new_param_expr, expr_factory))) {
LOG_WARN("create_bool_expr failed", K(ret));
} else if (OB_ISNULL(new_param_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("new param_expr is NULL", K(ret));
} else {
parent->replace_param_expr(i, new_param_expr);
}
}
}
return ret;
}
int ObRawExprUtils::try_create_bool_expr(ObRawExpr* src_expr, ObRawExpr*& out_expr, ObRawExprFactory& expr_factory)
{
int ret = OB_SUCCESS;
out_expr = NULL;
if (OB_ISNULL(src_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("in expr is NULL", K(ret));
} else {
ObOpRawExpr* bool_expr = NULL;
bool need_bool_expr = true;
if (OB_FAIL(check_need_bool_expr(src_expr, need_bool_expr))) {
LOG_WARN("check_need_bool_expr failed", K(ret));
} else if (!need_bool_expr) {
out_expr = src_expr;
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_BOOL, bool_expr))) {
LOG_WARN("create bool expr failed", K(ret));
} else if (OB_ISNULL(bool_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("bool_expr is NULL", K(ret));
} else {
OZ(bool_expr->add_flag(IS_INNER_ADDED_EXPR));
OZ(bool_expr->add_param_expr(src_expr));
OX(out_expr = bool_expr);
}
}
return ret;
}
bool ObRawExprUtils::check_need_bool_expr(const ObRawExpr* expr, bool& need_bool_expr)
{
int ret = OB_SUCCESS;
need_bool_expr = true;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("in expr is NULL", K(ret));
} else if (is_oracle_mode()) {
need_bool_expr = false;
} else {
ObItemType expr_type = expr->get_expr_type();
switch (expr_type) {
case T_OP_EQ:
case T_OP_NSEQ:
case T_OP_LE:
case T_OP_LT:
case T_OP_GE:
case T_OP_GT:
case T_OP_NE:
case T_OP_SQ_EQ:
case T_OP_SQ_NSEQ:
case T_OP_SQ_LE:
case T_OP_SQ_LT:
case T_OP_SQ_GE:
case T_OP_SQ_GT:
case T_OP_SQ_NE:
case T_OP_IS:
case T_OP_IS_NOT:
case T_OP_BTW:
case T_OP_NOT_BTW:
case T_OP_LIKE:
case T_OP_NOT_LIKE:
case T_OP_REGEXP:
case T_OP_NOT_REGEXP:
case T_OP_NOT:
case T_OP_AND:
case T_OP_OR:
case T_OP_IN:
case T_OP_NOT_IN:
case T_OP_EXISTS:
case T_OP_NOT_EXISTS:
// all int is 8 byte in datum, so safe for expr to use get_int() for tinyint type
case T_TINYINT:
case T_SMALLINT:
case T_MEDIUMINT:
case T_INT32:
case T_INT:
case T_UTINYINT:
case T_USMALLINT:
case T_UMEDIUMINT:
case T_UINT32:
case T_UINT64:
case T_OP_XOR:
case T_OP_BOOL: {
need_bool_expr = false;
break;
}
default: {
need_bool_expr = true;
break;
}
}
}
return ret;
}
int ObRawExprUtils::get_real_expr_without_cast(
const bool is_static_typing_engine, const ObRawExpr* expr, const ObRawExpr*& out_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is NULL", K(ret));
} else {
if (is_static_typing_engine) {
while (T_FUN_SYS_CAST == expr->get_expr_type() && CM_IS_IMPLICIT_CAST(expr->get_extra())) {
if (OB_UNLIKELY(2 != expr->get_param_count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("param_count of cast expr should be 2", K(ret), K(*expr));
} else if (OB_ISNULL(expr = expr->get_param_expr(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("first child of cast expr is NULL", K(ret), K(*expr));
}
}
}
if (OB_SUCC(ret)) {
out_expr = expr;
LOG_DEBUG("get_real_expr_without_cast done", K(*out_expr));
}
}
return ret;
}
int ObRawExprUtils::build_remove_const_expr(
ObRawExprFactory& factory, ObSQLSessionInfo& session_info, ObRawExpr* arg, ObRawExpr*& out)
{
int ret = OB_SUCCESS;
CK(NULL != arg);
if (OB_SUCC(ret)) {
ObSysFunRawExpr* rc_expr = NULL;
OZ(factory.create_raw_expr(T_FUN_SYS_REMOVE_CONST, rc_expr));
CK(NULL != rc_expr);
OZ(rc_expr->add_param_expr(arg));
OX(rc_expr->set_func_name(ObString::make_string(N_REMOVE_CONST)));
OZ(rc_expr->formalize(&session_info));
OZ(rc_expr->add_flag(IS_INNER_ADDED_EXPR));
OX(out = rc_expr);
}
return ret;
};
bool ObRawExprUtils::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;
}
bool ObRawExprUtils::is_sharable_expr(const ObRawExpr& expr)
{
int bret = false;
if (expr.is_query_ref_expr() || expr.is_column_ref_expr() || expr.is_aggr_expr() || expr.is_win_func_expr() ||
is_pseudo_column_like_expr(expr)) {
bret = true;
}
return bret;
}
int ObRawExprUtils::check_need_cast_expr(const ObExprResType& src_type, const ObExprResType& dst_type, bool& need_cast)
{
int ret = OB_SUCCESS;
need_cast = false;
ObObjType in_type = src_type.get_type();
ObObjType out_type = dst_type.get_type();
ObCollationType in_cs_type = src_type.get_collation_type();
ObCollationType out_cs_type = dst_type.get_collation_type();
bool is_both_string = (ob_is_string_type(in_type) && ob_is_string_type(out_type));
const bool is_same_need = true;
bool need_wrap = false;
if (!ob_is_valid_obj_type(in_type) || !ob_is_valid_obj_type(out_type) ||
(ob_is_string_type(in_type) && !ObCharset::is_valid_collation(in_cs_type)) ||
(ob_is_string_type(out_type) && !ObCharset::is_valid_collation(out_cs_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid src type or dst type", K(ret), K(src_type), K(dst_type));
} else if ((!is_both_string && in_type == out_type) ||
(is_both_string && in_type == out_type && in_cs_type == out_cs_type)) {
need_cast = false;
} else if (ob_is_enumset_tc(out_type)) {
// no need add cast, will add column_conv later
need_cast = false;
} else if (OB_FAIL(ObRawExprUtils::need_wrap_to_string(in_type, out_type, is_same_need, need_wrap))) {
LOG_WARN("failed to check_need_wrap_to_string", K(ret));
} else if (need_wrap) {
// no need add cast, add enumset_str expr later
need_cast = false;
} else if (!cast_supported(in_type, in_cs_type, out_type, out_cs_type)) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_WARN("transition does not support", K(in_type), K(out_type));
} else if (src_type.is_null() || dst_type.is_null()) {
// null -> xxx or xxx -> null
// xxx->null will report an error.
need_cast = true;
} else {
need_cast = true;
}
LOG_DEBUG("check_need_cast_expr", K(ret), K(need_cast), K(src_type), K(dst_type));
return ret;
}
// private member, use create_cast_expr() instead.
int ObRawExprUtils::create_real_cast_expr(ObRawExprFactory& expr_factory, ObRawExpr* src_expr,
const ObExprResType& dst_type, ObSysFunRawExpr*& func_expr, const ObSQLSessionInfo* session_info)
{
int ret = OB_SUCCESS;
ObConstRawExpr* dst_expr = NULL;
ParseNode parse_node;
ObObj val;
if (OB_ISNULL(src_expr) || OB_ISNULL(session_info)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid args", KP(src_expr), KP(session_info));
} else {
if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_CAST, func_expr))) {
LOG_WARN("create cast expr failed", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_INT, dst_expr))) {
LOG_WARN("create dest type expr failed", K(ret));
} else if (OB_FAIL(func_expr->add_param_expr(src_expr))) {
LOG_WARN("add real param expr failed", K(ret));
} else {
func_expr->set_orig_expr(src_expr);
ObString func_name = ObString::make_string(N_CAST);
parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = static_cast<int16_t>(dst_type.get_type());
parse_node.int16_values_[OB_NODE_CAST_COLL_IDX] = static_cast<int16_t>(dst_type.get_collation_type());
if (ob_is_string_or_lob_type(dst_type.get_type())) {
parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = dst_type.get_length();
if (share::is_oracle_mode()) {
dst_expr->set_length_semantics(dst_type.get_length_semantics());
}
} else if (ob_is_rowid_tc(dst_type.get_type())) {
int32_t urowid_len = dst_type.get_length();
if (urowid_len <= -1) {
urowid_len = 4000;
}
parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX] = 4000;
} else if (ObIntervalYMType == dst_type.get_type()) {
parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = dst_type.get_scale(); // year
} else if (ObIntervalDSType == dst_type.get_type()) {
parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = (dst_type.get_scale() / 10); // day
parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = (dst_type.get_scale() % 10); // second
} else {
parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = dst_type.get_precision();
parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = dst_type.get_scale();
}
val.set_int(parse_node.value_);
dst_expr->set_value(val);
dst_expr->set_param(val);
func_expr->set_func_name(func_name);
if (src_expr->is_for_generated_column()) {
func_expr->set_for_generated_column();
}
if (OB_FAIL(func_expr->add_param_expr(dst_expr))) {
LOG_WARN("add dest type expr failed", K(ret));
}
LOG_DEBUG("create_cast_expr debug", K(ret), K(*src_expr), K(dst_type), K(*func_expr), K(lbt()));
}
}
return ret;
}
int ObRawExprUtils::build_add_expr(
ObRawExprFactory& expr_factory, ObRawExpr* param_expr1, ObRawExpr* param_expr2, ObOpRawExpr*& add_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_ADD, add_expr))) {
LOG_WARN("create add expr failed", K(ret));
} else if (OB_ISNULL(add_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null", K(ret), K(add_expr));
} else if (OB_FAIL(add_expr->add_param_expr(param_expr1))) {
LOG_WARN("add text expr to add expr failed", K(ret));
} else if (OB_FAIL(add_expr->add_param_expr(param_expr2))) {
LOG_WARN("add pattern expr to add expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::build_minus_expr(
ObRawExprFactory& expr_factory, ObRawExpr* param_expr1, ObRawExpr* param_expr2, ObOpRawExpr*& minus_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_MINUS, minus_expr))) {
LOG_WARN("create minus expr failed", K(ret));
} else if (OB_ISNULL(minus_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("minus expr is null", K(ret), K(minus_expr));
} else if (OB_FAIL(minus_expr->add_param_expr(param_expr1))) {
LOG_WARN("add text expr to minus expr failed", K(ret));
} else if (OB_FAIL(minus_expr->add_param_expr(param_expr2))) {
LOG_WARN("add pattern expr to minus expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::build_date_add_expr(ObRawExprFactory& expr_factory, ObRawExpr* param_expr1, ObRawExpr* param_expr2,
ObRawExpr* param_expr3, ObSysFunRawExpr*& date_add_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2) || OB_ISNULL(param_expr3)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(param_expr3), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_DATE_ADD, date_add_expr))) {
LOG_WARN("create to_type expr failed", K(ret));
} else if (OB_ISNULL(date_add_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("date add expr is null", K(ret), K(date_add_expr));
} else if (OB_FAIL(date_add_expr->set_param_exprs(param_expr1, param_expr2, param_expr3))) {
LOG_WARN("add param expr failed", K(ret));
} else {
ObString func_name = ObString::make_string("date_add");
date_add_expr->set_func_name(func_name);
}
return ret;
}
int ObRawExprUtils::build_date_sub_expr(ObRawExprFactory& expr_factory, ObRawExpr* param_expr1, ObRawExpr* param_expr2,
ObRawExpr* param_expr3, ObSysFunRawExpr*& date_sub_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2) || OB_ISNULL(param_expr3)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(param_expr3), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_DATE_SUB, date_sub_expr))) {
LOG_WARN("create to_type expr failed", K(ret));
} else if (OB_ISNULL(date_sub_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("date sub expr is null", K(ret), K(date_sub_expr));
} else if (OB_FAIL(date_sub_expr->set_param_exprs(param_expr1, param_expr2, param_expr3))) {
LOG_WARN("add param expr failed", K(ret));
} else {
ObString func_name = ObString::make_string("date_sub");
date_sub_expr->set_func_name(func_name);
}
return ret;
}
int ObRawExprUtils::build_common_binary_op_expr(ObRawExprFactory& expr_factory, const ObItemType expect_op_type,
ObRawExpr* param_expr1, ObRawExpr* param_expr2, ObRawExpr*& expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* op_expr = NULL;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(expect_op_type, op_expr))) {
LOG_WARN("create op expr failed", K(ret));
} else if (OB_ISNULL(op_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null", K(ret), K(op_expr));
} else if (OB_FAIL(op_expr->add_param_expr(param_expr1))) {
LOG_WARN("add text expr to add expr failed", K(ret));
} else if (OB_FAIL(op_expr->add_param_expr(param_expr2))) {
LOG_WARN("add pattern expr to add expr failed", K(ret));
} else {
expr = op_expr;
}
return ret;
}
int ObRawExprUtils::build_case_when_expr(ObRawExprFactory& expr_factory, ObRawExpr* when_expr, ObRawExpr* then_expr,
ObRawExpr* default_expr, ObRawExpr*& case_when_expr)
{
int ret = OB_SUCCESS;
ObCaseOpRawExpr* c_case_when_expr = NULL;
if (OB_ISNULL(when_expr) || OB_ISNULL(then_expr) || OB_ISNULL(default_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(when_expr), K(then_expr), K(default_expr), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_CASE, c_case_when_expr))) {
LOG_WARN("create add expr failed", K(ret));
} else if (OB_ISNULL(c_case_when_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(c_case_when_expr));
} else if (OB_FAIL(c_case_when_expr->add_when_param_expr(when_expr))) {
LOG_WARN("failed to add when param expr", K(ret));
} else if (OB_FAIL(c_case_when_expr->add_then_param_expr(then_expr))) {
LOG_WARN("failed to add then expr", K(ret));
} else {
c_case_when_expr->set_default_param_expr(default_expr);
case_when_expr = c_case_when_expr;
}
return ret;
}
int ObRawExprUtils::build_is_not_expr(ObRawExprFactory& expr_factory, ObRawExpr* param_expr1, ObRawExpr* param_expr2,
ObRawExpr* param_expr3, ObRawExpr*& is_not_expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* not_expr = NULL;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2) || OB_ISNULL(param_expr3)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(param_expr3), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_IS_NOT, not_expr))) {
LOG_WARN("failed to create a new expr", K(ret));
} else if (OB_ISNULL(not_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("not_expr is null", K(ret), K(not_expr));
} else if (OB_FAIL(not_expr->set_param_exprs(param_expr1, param_expr2, param_expr3))) {
LOG_WARN("failed to set param for not expr", K(ret), K(not_expr));
} else {
is_not_expr = not_expr;
}
return ret;
}
int ObRawExprUtils::build_is_not_null_expr(
ObRawExprFactory& expr_factory, ObRawExpr* param_expr, ObRawExpr*& is_not_null_expr)
{
int ret = OB_SUCCESS;
ObConstRawExpr* null_expr = NULL;
ObConstRawExpr* flag_expr = NULL;
ObOpRawExpr* is_not_expr = NULL;
is_not_null_expr = NULL;
if (OB_ISNULL(param_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr), K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_IS_NOT, is_not_expr))) {
LOG_WARN("failed to create a new expr", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_NULL, null_expr))) {
LOG_WARN("failed to create const null expr", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_BOOL, flag_expr))) {
LOG_WARN("failed to create flag bool expr", K(ret));
} else if (OB_ISNULL(is_not_expr) || OB_ISNULL(null_expr) || OB_ISNULL(flag_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to create not null expr", K(ret));
} else {
ObObjParam null_val;
null_val.set_null();
null_val.set_param_meta();
null_expr->set_param(null_val);
null_expr->set_value(null_val);
ObObjParam flag_val;
flag_val.set_bool(false);
flag_val.set_param_meta();
flag_expr->set_param(flag_val);
flag_expr->set_value(flag_val);
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(is_not_expr->set_param_exprs(param_expr, null_expr, flag_expr))) {
LOG_WARN("failed to set param for not_null op", K(ret), K(*is_not_expr));
} else {
is_not_null_expr = is_not_expr;
}
return ret;
}
int ObRawExprUtils::process_window_complex_agg_expr(ObRawExprFactory& expr_factory, const ObItemType func_type,
ObWinFunRawExpr* win_func, ObRawExpr*& window_agg_expr, ObIArray<ObWinFunRawExpr*>* win_exprs)
{
int ret = OB_SUCCESS;
bool is_stack_overflow = false;
if (OB_ISNULL(win_func) || OB_ISNULL(window_agg_expr) || OB_ISNULL(win_exprs)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("get unexpected null", K(ret), K(win_func), K(window_agg_expr), K(win_exprs));
} else if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
LOG_WARN("check stack overflow failed", K(ret), K(is_stack_overflow));
} else if (is_stack_overflow) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow));
} else if (ObOptimizerUtil::find_item(*win_exprs, window_agg_expr)) {
/*do nothing*/
} else if (T_FUN_SUM == func_type || T_FUN_COUNT == func_type || T_FUN_KEEP_SUM == func_type ||
T_FUN_KEEP_COUNT == func_type) {
ObWinFunRawExpr* win_func_expr = NULL;
ObAggFunRawExpr* agg_expr = static_cast<ObAggFunRawExpr*>(window_agg_expr);
if (agg_expr->is_param_distinct() && (win_func->has_order_items() || win_func->has_frame_orig())) {
ret = OB_ORDERBY_CLAUSE_NOT_ALLOWED;
} else if (OB_FAIL(expr_factory.create_raw_expr(T_WINDOW_FUNCTION, win_func_expr))) {
LOG_WARN("failed to create window function expr", K(ret));
} else if (OB_ISNULL(win_func_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("win_func_expr is null", K(ret), K(win_func_expr));
} else if (OB_FAIL(win_func_expr->assign(*win_func))) {
LOG_WARN("failed to assigned win func expr.", K(ret));
} else if (FALSE_IT(win_func_expr->set_agg_expr(agg_expr))) {
LOG_WARN("failed to set agg expr.", K(ret));
} else if (FALSE_IT(window_agg_expr = win_func_expr)) {
LOG_WARN("failed to replace the agg expr.", K(ret));
} else if (FALSE_IT(win_func_expr->set_func_type(func_type))) {
LOG_WARN("failed to set func type.", K(ret));
} else if (OB_FAIL(win_exprs->push_back(win_func_expr))) {
LOG_WARN("failed to push back win func epxr.", K(ret));
} else { /*do nothing */
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < window_agg_expr->get_param_count(); i++) {
ObRawExpr*& sub_expr = window_agg_expr->get_param_expr(i);
if (OB_ISNULL(sub_expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("error argument.", K(ret));
} else if (OB_FAIL(process_window_complex_agg_expr(
expr_factory, sub_expr->get_expr_type(), win_func, sub_expr, win_exprs))) {
LOG_WARN("failed to process window complex agg node.", K(ret));
} else { /*do nothing*/
}
}
}
return ret;
}
int ObRawExprUtils::build_common_aggr_expr(ObRawExprFactory& expr_factory, ObSQLSessionInfo* session_info,
const ObItemType expect_op_type, ObRawExpr* param_expr, ObAggFunRawExpr*& aggr_expr)
{
int ret = OB_SUCCESS;
aggr_expr = NULL;
if (OB_ISNULL(param_expr) || OB_ISNULL(session_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(param_expr), K(session_info));
} else if (OB_FAIL(expr_factory.create_raw_expr(expect_op_type, aggr_expr))) {
LOG_WARN("create ObAggFunRawExpr failed", K(ret));
} else if (OB_ISNULL(aggr_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("agg_expr is null", K(ret), K(aggr_expr));
} else if (OB_FAIL(aggr_expr->add_real_param_expr(param_expr))) {
LOG_WARN("failed to add param expr to agg expr", K(ret));
} else if (OB_FAIL(aggr_expr->formalize(session_info))) {
LOG_WARN("failed to extract info", K(ret));
} else { /*do nothing */
}
return ret;
}
// only use for limit_expr/offset_expr, for constructing case when limit_expr < 0 then 0 else limit_expr end
int ObRawExprUtils::build_case_when_expr_for_limit(
ObRawExprFactory& expr_factory, ObRawExpr* limit_expr, ObRawExpr*& expected_case_when_expr)
{
int ret = OB_SUCCESS;
expected_case_when_expr = NULL;
ObRawExpr* case_when_expr = NULL;
ObRawExpr* less_expr = NULL;
ObConstRawExpr* zero_expr = NULL;
if (OB_ISNULL(limit_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(build_const_int_expr(expr_factory, ObIntType, 0, zero_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(build_common_binary_op_expr(expr_factory, T_OP_LT, limit_expr, zero_expr, less_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(build_case_when_expr(expr_factory, less_expr, zero_expr, limit_expr, case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else {
expected_case_when_expr = case_when_expr;
}
return ret;
}
int ObRawExprUtils::build_not_expr(ObRawExprFactory& expr_factory, ObRawExpr* expr, ObRawExpr*& not_expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* new_expr = NULL;
if (OB_ISNULL(expr)) {
LOG_WARN("expr has null", K(ret));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_NOT, new_expr))) {
LOG_WARN("failed to create a new expr", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to create not expr", K(ret));
} else if (OB_FAIL(new_expr->set_param_expr(expr))) {
LOG_WARN("failed to set param for not op", K(ret), K(*not_expr));
} else {
not_expr = new_expr;
}
return ret;
}
int ObRawExprUtils::build_or_exprs(
ObRawExprFactory& expr_factory, const ObIArray<ObRawExpr*>& exprs, ObRawExpr*& or_expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* new_expr = NULL;
or_expr = NULL;
if (exprs.count() == 0) {
or_expr = NULL;
} else if (exprs.count() == 1) {
or_expr = exprs.at(0);
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_OR, new_expr))) {
LOG_WARN("failed to create a new expr", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to create or expr", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
ObRawExpr* expr = exprs.at(i);
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("exprs has null child", K(i));
} else if (OB_FAIL(new_expr->add_param_expr(expr))) {
LOG_WARN("add param expr to or expr failed", K(ret));
} else { /*do nothing*/
}
}
if (OB_SUCC(ret)) {
or_expr = new_expr;
} else { /*do nothing*/
}
}
return ret;
}
int ObRawExprUtils::build_and_expr(
ObRawExprFactory& expr_factory, const ObIArray<ObRawExpr*>& exprs, ObRawExpr*& and_expr)
{
int ret = OB_SUCCESS;
ObOpRawExpr* new_expr = NULL;
and_expr = NULL;
if (exprs.count() == 0) {
and_expr = NULL;
} else if (exprs.count() == 1) {
and_expr = exprs.at(0);
} else if (OB_FAIL(expr_factory.create_raw_expr(T_OP_AND, new_expr))) {
LOG_WARN("failed to create a new expr", K(ret));
} else if (OB_ISNULL(new_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to create or expr", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
ObRawExpr* expr = exprs.at(i);
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("exprs has null child", K(i));
} else if (OB_FAIL(new_expr->add_param_expr(expr))) {
LOG_WARN("add param expr to or expr failed", K(ret));
} else { /*do nothing*/
}
}
if (OB_SUCC(ret)) {
and_expr = new_expr;
} else { /*do nothing*/
}
}
return ret;
}
int ObRawExprUtils::new_parse_node(
ParseNode*& node, ObRawExprFactory& expr_factory, ObItemType type, int num, ObString str_val)
{
int ret = OB_SUCCESS;
char* str_value = NULL;
if (OB_FAIL(new_parse_node(node, expr_factory, type, num))) {
LOG_WARN("fail to alloc new node", K(ret));
} else if (str_val.length() <= 0) {
/*nothing*/
} else if (OB_ISNULL(str_value = static_cast<char*>(expr_factory.get_allocator().alloc(str_val.length())))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to alloc buf", K(ret));
} else {
MEMCPY(str_value, str_val.ptr(), str_val.length());
node->str_value_ = str_value;
node->str_len_ = str_val.length();
}
return ret;
}
int ObRawExprUtils::new_parse_node(ParseNode*& node, ObRawExprFactory& expr_factory, ObItemType type, int num)
{
int ret = OB_SUCCESS;
ObIAllocator* alloc_buf = &(expr_factory.get_allocator());
node = (ParseNode*)alloc_buf->alloc(sizeof(ParseNode));
if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("allocate parse node failed", K(ret), K(node));
} else {
node->type_ = type;
node->num_child_ = num;
node->param_num_ = 0;
node->is_neg_ = 0;
node->is_hidden_const_ = 0;
node->is_date_unit_ = 0;
node->is_tree_not_param_ = 0;
node->value_ = INT64_MAX;
node->str_len_ = 0;
node->str_value_ = NULL;
node->text_len_ = 0;
node->raw_text_ = NULL;
node->pos_ = 0;
if (num > 0) {
int64_t alloc_size = sizeof(ParseNode*) * num;
node->children_ = (ParseNode**)alloc_buf->alloc(alloc_size);
if (OB_ISNULL(node->children_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("allocate children buffer failed", K(ret), K(node->children_));
}
} else {
node->children_ = NULL;
}
}
return ret;
}
int ObRawExprUtils::build_rownum_expr(ObRawExprFactory& expr_factory, ObRawExpr*& rownum_expr)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* rownum = NULL;
rownum_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_SYS_ROWNUM, rownum))) {
LOG_WARN("failed to create raw expr", K(ret));
} else if (OB_ISNULL(rownum)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null expr", K(ret));
} else {
rownum->set_func_name(ObString::make_string("rownum"));
rownum->set_data_type(ObNumberType);
rownum_expr = rownum;
}
return ret;
}
int ObRawExprUtils::build_to_outfile_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo* session_info,
const ObSelectIntoItem* into_item, const ObIArray<ObRawExpr*>& exprs, ObRawExpr*& to_outfile_expr)
{
int ret = OB_SUCCESS;
to_outfile_expr = NULL;
ObOpRawExpr* new_expr = NULL;
ObConstRawExpr* filed_expr = NULL;
ObConstRawExpr* line_expr = NULL;
char* closed_cht_buf = NULL;
ObConstRawExpr* closed_cht_expr = NULL;
ObRawExpr* is_optional_expr = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_OP_TO_OUTFILE_ROW, new_expr))) {
LOG_WARN("fail to create raw expr", K(ret));
} else if (OB_FAIL(build_const_string_expr(expr_factory,
ObVarcharType,
into_item->filed_str_.get_varchar(),
into_item->filed_str_.get_collation_type(),
filed_expr))) {
LOG_WARN("fail to create string expr", K(ret));
} else if (OB_FAIL(build_const_string_expr(expr_factory,
ObVarcharType,
into_item->line_str_.get_varchar(),
into_item->line_str_.get_collation_type(),
line_expr))) {
LOG_WARN("fail to create string expr", K(ret));
} else if (OB_ISNULL(closed_cht_buf = static_cast<char*>(expr_factory.get_allocator().alloc(1)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to alloc buf", K(ret));
} else if (FALSE_IT(closed_cht_buf[0] = into_item->closed_cht_)) {
// do nothing
} else if (OB_FAIL(build_const_string_expr(expr_factory,
ObVarcharType,
into_item->closed_cht_ == 0 ? ObString() : ObString(1, closed_cht_buf),
into_item->filed_str_.get_collation_type(),
closed_cht_expr))) {
LOG_WARN("fail to create string expr", K(ret));
} else if (OB_FAIL(build_const_bool_expr(&expr_factory, is_optional_expr, into_item->is_optional_))) {
LOG_WARN("fail to create bool expr", K(ret));
} else if (new_expr->add_param_expr(filed_expr)) {
LOG_WARN("fail to add filed_expr", K(ret));
} else if (new_expr->add_param_expr(line_expr)) {
LOG_WARN("fail to add line_expr", K(ret));
} else if (new_expr->add_param_expr(closed_cht_expr)) {
LOG_WARN("fail to add closed_cht_expr", K(ret));
} else if (new_expr->add_param_expr(is_optional_expr)) {
LOG_WARN("fail to add is_optional_expr", K(ret));
} else {
for (int i = 0; i < exprs.count() && OB_SUCC(ret); ++i) {
if (OB_FAIL(new_expr->add_param_expr(exprs.at(i)))) {
LOG_WARN("fail to add param expr", K(i), K(ret));
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(new_expr->formalize(session_info))) {
LOG_WARN("failed to formalize expr", K(ret));
} else {
to_outfile_expr = new_expr;
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase