From 843888c953c3aa83901d6597331dc59dcbb129f1 Mon Sep 17 00:00:00 2001 From: xianyu-w <707512433@qq.com> Date: Fri, 17 Mar 2023 02:40:51 +0000 Subject: [PATCH] Fix dblink bugs --- src/sql/ob_dml_stmt_printer.cpp | 2 +- src/sql/resolver/expr/ob_raw_expr_printer.cpp | 49 +++++-- src/sql/resolver/expr/ob_raw_expr_printer.h | 2 + src/sql/resolver/expr/ob_raw_expr_util.cpp | 137 ++++++++++-------- src/sql/resolver/expr/ob_raw_expr_util.h | 5 + src/sql/rewrite/ob_transform_dblink.cpp | 66 ++++++--- src/sql/rewrite/ob_transform_dblink.h | 2 + src/sql/rewrite/ob_transformer_impl.cpp | 10 ++ 8 files changed, 176 insertions(+), 97 deletions(-) diff --git a/src/sql/ob_dml_stmt_printer.cpp b/src/sql/ob_dml_stmt_printer.cpp index 12890b9c03..b7585af506 100644 --- a/src/sql/ob_dml_stmt_printer.cpp +++ b/src/sql/ob_dml_stmt_printer.cpp @@ -1112,7 +1112,7 @@ int ObDMLStmtPrinter::print_where() } else if (condition_exprs_size > 0 && stmt_->get_semi_info_size() > 0) { DATA_PRINTF(" and "); } - if (OB_FAIL(print_semi_info_to_subquery())) { + if (OB_SUCC(ret) && OB_FAIL(print_semi_info_to_subquery())) { LOG_WARN("failed to print semi info to subquery", K(ret)); } } diff --git a/src/sql/resolver/expr/ob_raw_expr_printer.cpp b/src/sql/resolver/expr/ob_raw_expr_printer.cpp index 1144f69494..1ad951574a 100644 --- a/src/sql/resolver/expr/ob_raw_expr_printer.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_printer.cpp @@ -207,14 +207,17 @@ int ObRawExprPrinter::print(ObConstRawExpr *expr) } else if (print_params_.for_dblink_ && T_QUESTIONMARK == expr->get_expr_type()) { int64_t idx = expr->get_value().get_unknown(); bool is_bool_expr = false; + bool is_null_type = ob_is_null(expr->get_result_type().get_type()); if (expr->is_exec_param_expr()) { ObExecParamRawExpr *exec_expr = static_cast(expr); if (OB_FAIL(ObRawExprUtils::check_is_bool_expr(exec_expr->get_ref_expr(), is_bool_expr))) { LOG_WARN("failed to check is bool expr", K(ret)); } } + + /** To preserve the type information of questionmark when it is NULL, print a cast*/ if (OB_FAIL(ret)) { - } else if (is_bool_expr) { + } else if (is_bool_expr && OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, "1 = "))) { /** * For SQL like "select * from T1 where C1 = 1 and C1 = 2", * because the where clause is always false, @@ -223,19 +226,18 @@ int ObRawExprPrinter::print(ObConstRawExpr *expr) * by rewriting startup_filter as "0 = 1" or "1 = 1". * */ - if (OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, "1 = "))) { - LOG_WARN("fail to print startup filter", K(ret)); - } else if (OB_NOT_NULL(param_store_) && 0 <= idx && idx < param_store_->count()) { - OZ (param_store_->at(idx).print_sql_literal(buf_, buf_len_, *pos_, print_params_)); - } else if (OB_FAIL(ObLinkStmtParam::write(buf_, buf_len_, *pos_, expr->get_value().get_unknown()))) { - LOG_WARN("fail to write param to buf", K(ret)); - } - } else { - if (OB_NOT_NULL(param_store_) && 0 <= idx && idx < param_store_->count()) { - OZ (param_store_->at(idx).print_sql_literal(buf_, buf_len_, *pos_, print_params_)); - } else if (OB_FAIL(ObLinkStmtParam::write(buf_, buf_len_, *pos_, expr->get_value().get_unknown()))) { - LOG_WARN("fail to write param to buf", K(ret)); - } + LOG_WARN("fail to print 1 =", K(ret)); + } else if (!is_null_type && OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, "cast("))) { + LOG_WARN("fail to print cast(", K(ret)); + } else if (OB_NOT_NULL(param_store_) && 0 <= idx && idx < param_store_->count()) { + OZ (param_store_->at(idx).print_sql_literal(buf_, buf_len_, *pos_, print_params_)); + } else if (OB_FAIL(ObLinkStmtParam::write(buf_, buf_len_, *pos_, expr->get_value().get_unknown()))) { + LOG_WARN("fail to write param to buf", K(ret)); + } + if (OB_SUCC(ret) && !is_null_type) { + DATA_PRINTF(" as "); + OZ(print_type(expr->get_result_type())); + DATA_PRINTF(")"); } } else if (OB_NOT_NULL(param_store_) && T_QUESTIONMARK == expr->get_expr_type()) { int64_t idx = expr->get_value().get_unknown(); @@ -2505,7 +2507,7 @@ int ObRawExprPrinter::print(ObSysFunRawExpr *expr) if (OB_SUCC(ret)) { PRINT_EXPR(expr->get_param_expr(0)); DATA_PRINTF(" as "); - if (OB_FAIL(print_cast_type(expr->get_param_expr(1)))) { + if (OB_SUCC(ret) && OB_FAIL(print_cast_type(expr->get_param_expr(1)))) { LOG_WARN("fail to print cast_type", K(ret)); } } @@ -3918,6 +3920,23 @@ int ObRawExprPrinter::pre_check_treat_opt(ObRawExpr *expr, bool &is_treat) return ret; } +int ObRawExprPrinter::print_type(const ObExprResType &dst_type) +{ + int ret = OB_SUCCESS; + ObConstRawExpr *type_expr = NULL; + ObArenaAllocator allocator("PrintType"); + ObRawExprFactory expr_factory(allocator); + + + if (OB_FAIL(ObRawExprUtils::create_type_expr(expr_factory, type_expr, + dst_type, /*avoid_zero_len*/true))) { + LOG_WARN("create type expr failed", K(ret)); + } else if (OB_FAIL(print_cast_type(type_expr))) { + LOG_WARN("failed to print cast type", K(ret)); + } + return ret; +} + int ObRawExprPrinter::print_cast_type(ObRawExpr *expr) { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/expr/ob_raw_expr_printer.h b/src/sql/resolver/expr/ob_raw_expr_printer.h index 4948dd65de..28d0b9c402 100644 --- a/src/sql/resolver/expr/ob_raw_expr_printer.h +++ b/src/sql/resolver/expr/ob_raw_expr_printer.h @@ -142,6 +142,8 @@ private: int print_order_items(ObWinFunRawExpr *expr); int print_window_clause(ObWinFunRawExpr *expr); + int print_type(const ObExprResType &dst_type); + int inner_print_fun_params(ObSysFunRawExpr &expr); // disallow copy diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index 9b0dd520d9..f9723241a8 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -6840,77 +6840,18 @@ int ObRawExprUtils::create_real_cast_expr(ObRawExprFactory &expr_factory, { int ret = OB_SUCCESS; ObConstRawExpr *dst_expr = NULL; - ParseNode parse_node; - memset(&parse_node, 0, sizeof(ParseNode)); - 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(create_type_expr(expr_factory, dst_expr, dst_type))) { + LOG_WARN("create 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 { ObString func_name = ObString::make_string(N_CAST); - parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = static_cast(dst_type.get_type()); - parse_node.int16_values_[OB_NODE_CAST_COLL_IDX] = static_cast( - 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 (lib::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()) { - // TODO: @shaoge 针对ObIntervalYMType和ObIntervalDSType,parse_node的设置需要写case验证 - if (dst_type.get_scale() == -1) { - // scale=-1 is invalid, update to default value - ObCompatibilityMode compatibility_mode = get_compatibility_mode(); - parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = - ObAccuracy::DDL_DEFAULT_ACCURACY2[compatibility_mode] - [ObIntervalYMType] - .get_scale(); - } else { - parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = - dst_type.get_scale(); // year - } - } else if (ObIntervalDSType == dst_type.get_type()) { - ObCompatibilityMode compatibility_mode = get_compatibility_mode(); - parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = (dst_type.get_scale() / 10); // day - if (dst_type.get_scale() == -1) { - // scale=-1 is invalid, update to default value - parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = 0; - } else { - parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = (dst_type.get_scale() % 10);// second - } - } else if ((ObTimestampNanoType == dst_type.get_type() || - ObTimestampTZType == dst_type.get_type() || - ObTimestampLTZType == dst_type.get_type()) && - dst_type.get_scale() == -1) { - // scale=-1 is invalid, update to default value - ObCompatibilityMode compatibility_mode = get_compatibility_mode(); - parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = dst_type.get_precision(); - parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = - ObAccuracy::DDL_DEFAULT_ACCURACY2[compatibility_mode] - [dst_type.get_type()] - .get_scale(); - } 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(); @@ -6925,6 +6866,80 @@ int ObRawExprUtils::create_real_cast_expr(ObRawExprFactory &expr_factory, return ret; } +int ObRawExprUtils::create_type_expr(ObRawExprFactory &expr_factory, + ObConstRawExpr *&type_expr, + const ObExprResType &dst_type, + bool avoid_zero_len) +{ + int ret = OB_SUCCESS; + ObConstRawExpr *dst_expr = NULL; + ParseNode parse_node; + memset(&parse_node, 0, sizeof(ParseNode)); + ObObj val; + if (OB_FAIL(expr_factory.create_raw_expr(T_INT, dst_expr))) { + LOG_WARN("create dest type expr failed", K(ret)); + } else { + parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX] = static_cast(dst_type.get_type()); + parse_node.int16_values_[OB_NODE_CAST_COLL_IDX] = static_cast( + 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] = (avoid_zero_len && dst_type.get_length() == 0) ? + 1 : dst_type.get_length(); + if (lib::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()) { + // TODO: @shaoge 针对ObIntervalYMType和ObIntervalDSType,parse_node的设置需要写case验证 + if (dst_type.get_scale() == -1) { + // scale=-1 is invalid, update to default value + ObCompatibilityMode compatibility_mode = get_compatibility_mode(); + parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = + ObAccuracy::DDL_DEFAULT_ACCURACY2[compatibility_mode] + [ObIntervalYMType] + .get_scale(); + } else { + parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = + dst_type.get_scale(); // year + } + } else if (ObIntervalDSType == dst_type.get_type()) { + ObCompatibilityMode compatibility_mode = get_compatibility_mode(); + parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = (dst_type.get_scale() / 10); // day + if (dst_type.get_scale() == -1) { + // scale=-1 is invalid, update to default value + parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = 0; + } else { + parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = (dst_type.get_scale() % 10);// second + } + } else if ((ObTimestampNanoType == dst_type.get_type() || + ObTimestampTZType == dst_type.get_type() || + ObTimestampLTZType == dst_type.get_type()) && + dst_type.get_scale() == -1) { + // scale=-1 is invalid, update to default value + ObCompatibilityMode compatibility_mode = get_compatibility_mode(); + parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX] = dst_type.get_precision(); + parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX] = + ObAccuracy::DDL_DEFAULT_ACCURACY2[compatibility_mode] + [dst_type.get_type()] + .get_scale(); + } 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); + type_expr = dst_expr; + } + return ret; +} + int ObRawExprUtils::build_add_expr(ObRawExprFactory &expr_factory, ObRawExpr *param_expr1, ObRawExpr *param_expr2, diff --git a/src/sql/resolver/expr/ob_raw_expr_util.h b/src/sql/resolver/expr/ob_raw_expr_util.h index 584016239e..d09cc299d9 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.h +++ b/src/sql/resolver/expr/ob_raw_expr_util.h @@ -1059,6 +1059,11 @@ public: ObColumnRefRawExpr *&spk_expr); static int check_contain_case_when_exprs(const ObRawExpr *raw_expr, bool &contain); + static int create_type_expr(ObRawExprFactory &expr_factory, + ObConstRawExpr *&type_expr, + const ObExprResType &dst_type, + bool avoid_zero_len = false); + private : static int create_real_cast_expr(ObRawExprFactory &expr_factory, diff --git a/src/sql/rewrite/ob_transform_dblink.cpp b/src/sql/rewrite/ob_transform_dblink.cpp index e291c478ee..ce388592b1 100644 --- a/src/sql/rewrite/ob_transform_dblink.cpp +++ b/src/sql/rewrite/ob_transform_dblink.cpp @@ -1064,6 +1064,26 @@ int ObTransformDBlink::get_from_item_idx(ObDMLStmt *stmt, return ret; } +int ObTransformDBlink::check_can_pushdown(ObDMLStmt *stmt, const LinkTableHelper &helper, bool &can_push) +{ + int ret = OB_SUCCESS; + bool is_on_null_side = false; + JoinedTable *joined_table = helper.parent_table_; + TableItem *table = NULL; + if (NULL != joined_table) { + if (OB_UNLIKELY(1 != helper.table_items_.count()) || + OB_ISNULL(table = helper.table_items_.at(0)) || + OB_UNLIKELY(table != joined_table->left_table_ && table != joined_table->right_table_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected push down tables", K(ret)); + } else if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, table->table_id_, is_on_null_side))) { + LOG_WARN("failed to check table on null side", K(ret)); + } + } + can_push = !is_on_null_side; + return ret; +} + int ObTransformDBlink::collect_pushdown_conditions(ObDMLStmt *stmt, ObIArray &helpers) { int ret = OB_SUCCESS; @@ -1074,27 +1094,33 @@ int ObTransformDBlink::collect_pushdown_conditions(ObDMLStmt *stmt, ObIArrayget_condition_size(); ++j) { - ObRawExpr *expr = stmt->get_condition_expr(j); - if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect null expr", K(ret)); - } else if (!expr->get_relation_ids().is_subset(table_ids)) { - //do nothing - } else if (OB_FAIL(has_none_pushdown_expr(expr, - helpers.at(i).dblink_id_, - has_special_expr))) { - LOG_WARN("failed to check has none push down expr", K(ret)); - } else if (has_special_expr) { - //do nothing - } else if (OB_FAIL(helpers.at(i).conditions_.push_back(expr))) { - LOG_WARN("failed to push back expr", K(ret)); + } else { + bool has_special_expr = false; + for (int64_t j = 0; OB_SUCC(ret) && j < stmt->get_condition_size(); ++j) { + ObRawExpr *expr = stmt->get_condition_expr(j); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null expr", K(ret)); + } else if (!expr->get_relation_ids().is_subset(table_ids)) { + //do nothing + } else if (OB_FAIL(has_none_pushdown_expr(expr, + helpers.at(i).dblink_id_, + has_special_expr))) { + LOG_WARN("failed to check has none push down expr", K(ret)); + } else if (has_special_expr) { + //do nothing + } else if (OB_FAIL(helpers.at(i).conditions_.push_back(expr))) { + LOG_WARN("failed to push back expr", K(ret)); + } } } } diff --git a/src/sql/rewrite/ob_transform_dblink.h b/src/sql/rewrite/ob_transform_dblink.h index 66615e2014..cdb0ae7741 100644 --- a/src/sql/rewrite/ob_transform_dblink.h +++ b/src/sql/rewrite/ob_transform_dblink.h @@ -131,6 +131,8 @@ private: int get_from_item_idx(ObDMLStmt *stmt, ObRawExpr *expr, ObIArray &idxs); + int check_can_pushdown(ObDMLStmt *stmt, const LinkTableHelper &helper, bool &can_push); + int collect_pushdown_conditions(ObDMLStmt *stmt, ObIArray &helpers); int has_none_pushdown_expr(ObIArray &exprs, diff --git a/src/sql/rewrite/ob_transformer_impl.cpp b/src/sql/rewrite/ob_transformer_impl.cpp index 8a4d0ee7cd..6678ae863a 100644 --- a/src/sql/rewrite/ob_transformer_impl.cpp +++ b/src/sql/rewrite/ob_transformer_impl.cpp @@ -431,6 +431,16 @@ int ObTransformerImpl::choose_rewrite_rules(ObDMLStmt *stmt, uint64_t &need_type } if (func.contain_link_table_) { disable_list |= (~ObTransformRule::ALL_HEURISTICS_RULES); + + // Below rules might generate filter which contains constant values which has implicit types, + // which can not be printed in the link sql. + // example: + // create table t (c1 varchar(10), c2 char(10)) + // select * from t where c1 = 'a' and c2 = c1; + // => select * from t where c1 = 'a' and c2 = implicit cast('a' as varchar); + ObTransformRule::add_trans_type(disable_list, PREDICATE_MOVE_AROUND); + ObTransformRule::add_trans_type(disable_list, CONST_PROPAGATE); + ObTransformRule::add_trans_type(disable_list, SIMPLIFY_EXPR); } need_types = ObTransformRule::ALL_TRANSFORM_RULES & (~disable_list); }