From af61c607574a0813bd20135c9c92f031ba51aa7c Mon Sep 17 00:00:00 2001 From: hy-guo Date: Fri, 8 Dec 2023 07:17:22 +0000 Subject: [PATCH] fix auto generated identifier is too long --- src/sql/ob_dml_stmt_printer.cpp | 2 +- .../resolver/ddl/ob_create_view_resolver.cpp | 2 + src/sql/resolver/dml/ob_select_resolver.cpp | 84 +++++++++++++++++++ src/sql/resolver/dml/ob_select_resolver.h | 4 + .../resolver/dml/ob_view_table_resolver.cpp | 34 ++------ 5 files changed, 98 insertions(+), 28 deletions(-) diff --git a/src/sql/ob_dml_stmt_printer.cpp b/src/sql/ob_dml_stmt_printer.cpp index ef2c34f1c..91d77515b 100644 --- a/src/sql/ob_dml_stmt_printer.cpp +++ b/src/sql/ob_dml_stmt_printer.cpp @@ -2065,7 +2065,7 @@ int ObDMLStmtPrinter::print_with() || TableItem::RECURSIVE_CTE == cte_table->cte_type_) { if (OB_FAIL(print_cte_define_title(cte_table))) { LOG_WARN("print column name failed", K(ret)); - } else if (OB_FAIL(print_subquery(cte_table->ref_query_, PRINT_BRACKET))) { + } else if (OB_FAIL(print_subquery(cte_table->ref_query_, PRINT_BRACKET | FORCE_COL_ALIAS))) { LOG_WARN("print table failed", K(ret)); } else if (OB_FAIL(print_search_and_cycle(cte_table->ref_query_))) { LOG_WARN("print search and cycle failed", K(ret)); diff --git a/src/sql/resolver/ddl/ob_create_view_resolver.cpp b/src/sql/resolver/ddl/ob_create_view_resolver.cpp index 4b097d887..25fa441b9 100644 --- a/src/sql/resolver/ddl/ob_create_view_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_view_resolver.cpp @@ -164,6 +164,8 @@ int ObCreateViewResolver::resolve(const ParseNode &parse_tree) } else { LOG_WARN("resolve select in create view failed", K(select_stmt_node), K(ret)); } + } else if (OB_FAIL(view_table_resolver.check_auto_gen_column_names())) { + LOG_WARN("fail to check auto gen column names", K(ret)); } else if (OB_FAIL(params_.query_ctx_->query_hint_.init_query_hint(params_.allocator_, params_.session_info_, view_table_resolver.get_select_stmt()))) { diff --git a/src/sql/resolver/dml/ob_select_resolver.cpp b/src/sql/resolver/dml/ob_select_resolver.cpp index b2eb863ca..67241f565 100644 --- a/src/sql/resolver/dml/ob_select_resolver.cpp +++ b/src/sql/resolver/dml/ob_select_resolver.cpp @@ -6471,6 +6471,90 @@ int ObSelectResolver::resolve_check_option_clause(const ParseNode *node) return ret; } +/* ObSelectResolver::check_auto_gen_column_names() + * + * For a long expr with no alias + * MySQL will rename the overlong auto generated alias to "Name_exp_x", + * but Oracle will throw "identifier is too long" error. + */ +int ObSelectResolver::check_auto_gen_column_names() { + int ret = OB_SUCCESS; + ObSelectStmt *select_stmt = get_select_stmt(); + if (OB_ISNULL(select_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select stmt is null", K(ret)); + } else if (OB_FAIL(recursive_check_auto_gen_column_names(select_stmt))) { + LOG_WARN("fail to check auto gen column names", K(ret)); + } + return ret; +} + +int ObSelectResolver::recursive_check_auto_gen_column_names(ObSelectStmt *select_stmt) { + int ret = OB_SUCCESS; + ObSEArray child_stmts; + if (OB_ISNULL(select_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select stmt is null", K(ret)); + } else if (OB_FAIL(select_stmt->get_child_stmts(child_stmts))) { + LOG_WARN("fail to get child stmts", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); i++) { + ObSelectStmt *child_stmt = child_stmts.at(i); + if (OB_ISNULL(child_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child select stmt is null", K(ret), K(i)); + } else if (OB_FAIL(SMART_CALL(recursive_check_auto_gen_column_names(child_stmt)))) { + LOG_WARN("fail to check child stmt", K(ret), K(i)); + } + } + + for (int64_t i = 0; OB_SUCC(ret) && i < select_stmt->get_select_item_size(); ++i) { + SelectItem *select_item = &(select_stmt->get_select_item(i)); + if (OB_ISNULL(select_item) || OB_ISNULL(select_item->expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select item expr is null", K(ret), K(select_item)); + } else if (select_item->alias_name_.length() > static_cast(OB_MAX_COLUMN_NAME_LENGTH)) { + if (lib::is_oracle_mode()) { + ret = OB_ERR_TOO_LONG_IDENT; + LOG_WARN("auto generated alias is too long", K(ret), K(select_item->alias_name_.length()), K(select_item->alias_name_)); + } else { + char temp_str_buf[OB_MAX_COLUMN_NAME_BUF_LENGTH] = { 0 }; + if (snprintf(temp_str_buf, sizeof(temp_str_buf), SYNTHETIC_FIELD_NAME "%ld", auto_name_id_++) < 0) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("failed to generate buffer for temp_str_buf", K(ret)); + } else { + ObString tmp_col_name = ObString::make_string(temp_str_buf); + ObString col_name; + if (OB_FAIL(ob_write_string(*allocator_, tmp_col_name, col_name))) { + LOG_WARN("Can not malloc space for constraint name", K(ret)); + } else if (OB_FALSE_IT(select_item->alias_name_.assign_ptr(col_name.ptr(), col_name.length()))) { + } else if (select_item->expr_->is_column_ref_expr()) { + ObColumnRefRawExpr *col_ref_expr = static_cast(select_item->expr_); + TableItem *table_item = NULL; + ObSelectStmt *ref_stmt = NULL; + SelectItem *ref_select_item = NULL; + if (OB_ISNULL(table_item = select_stmt->get_table_item_by_id(col_ref_expr->get_table_id()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table item is null", K(ret)); + } else if (OB_ISNULL(ref_stmt = table_item->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ref query stmt is null", K(ret)); + } else if (OB_ISNULL(ref_select_item = &ref_stmt->get_select_item(col_ref_expr->get_column_id() - OB_APP_MIN_COLUMN_ID))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select item is null", K(ret)); + } else if (OB_FAIL(ob_write_string(*allocator_, ref_select_item->alias_name_, col_name))) { + LOG_WARN("Can not malloc space for constraint name", K(ret)); + } else { + col_ref_expr->get_column_name().assign_ptr(col_name.ptr(), col_name.length()); + } + } + } + } + } + } + return ret; +} + int ObSelectResolver::check_rollup_items_valid(const ObIArray &rollup_items) { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/dml/ob_select_resolver.h b/src/sql/resolver/dml/ob_select_resolver.h index 4bfa1d11a..a426117f9 100644 --- a/src/sql/resolver/dml/ob_select_resolver.h +++ b/src/sql/resolver/dml/ob_select_resolver.h @@ -19,6 +19,8 @@ #include "sql/rewrite/ob_stmt_comparer.h" #include "common/ob_smart_call.h" +# define SYNTHETIC_FIELD_NAME "Name_exp_" + namespace oceanbase { namespace sql @@ -87,6 +89,7 @@ public: ObString &cycle_pseudo_column_name); void set_current_recursive_cte_table_item(TableItem *table_item) { current_recursive_cte_table_item_ = table_item; } void set_current_cte_involed_stmt(ObSelectStmt *stmt) { current_cte_involed_stmt_ = stmt; } + int check_auto_gen_column_names(); // function members TO_STRING_KV(K_(has_calc_found_rows), @@ -345,6 +348,7 @@ private: int resolve_shared_order_item(OrderItem &order_item, ObSelectStmt *select_stmt); int adjust_recursive_cte_table_columns(const ObSelectStmt* parent_stmt, ObSelectStmt *right_stmt); + int recursive_check_auto_gen_column_names(ObSelectStmt *select_stmt); protected: // data members /*these member is only for with clause*/ diff --git a/src/sql/resolver/dml/ob_view_table_resolver.cpp b/src/sql/resolver/dml/ob_view_table_resolver.cpp index b7a15b837..0036e1656 100644 --- a/src/sql/resolver/dml/ob_view_table_resolver.cpp +++ b/src/sql/resolver/dml/ob_view_table_resolver.cpp @@ -194,33 +194,13 @@ int ObViewTableResolver::set_select_item(SelectItem &select_item, bool is_auto_g } } else if (OB_FAIL(session_info_->get_collation_connection(cs_type))) { LOG_WARN("fail to get collation_connection", K(ret)); - } else { - // 如果子查询列没有别名,超过 64 的话系统则自动为其会生成一个列别名 - if (!is_create_view_ && !select_item.is_real_alias_ && is_auto_gen - && select_item.alias_name_.length() > static_cast( - OB_MAX_VIEW_COLUMN_NAME_LENGTH_MYSQL)) { - ObString tmp_col_name; - ObString col_name; - char temp_str_buf[number::ObNumber::MAX_PRINTABLE_SIZE]; - if (snprintf(temp_str_buf, sizeof(temp_str_buf), "Name_exp_%ld", auto_name_id_++) < 0) { - ret = OB_SIZE_OVERFLOW; - SQL_RESV_LOG(WARN, "failed to generate buffer for temp_str_buf", K(ret)); - } - if (OB_SUCC(ret)) { - tmp_col_name = ObString::make_string(temp_str_buf); - if (OB_FAIL(ob_write_string(*allocator_, tmp_col_name, col_name))) { - SQL_RESV_LOG(WARN, "Can not malloc space for constraint name", K(ret)); - } else { - select_item.alias_name_.assign_ptr(col_name.ptr(), col_name.length()); - } - } - } - if (OB_SUCC(ret) && OB_FAIL(ObSQLUtils::check_column_name(cs_type, select_item.alias_name_, true))) { - LOG_WARN("fail to make field name", K(ret)); - } - if (OB_SUCC(ret) && OB_FAIL(select_stmt->add_select_item(select_item))) { - LOG_WARN("add select item to select stmt failed", K(ret)); - } + } else if (select_item.is_real_alias_ + && OB_FAIL(ObSQLUtils::check_column_name(cs_type, select_item.alias_name_, true))) { + // Only check real alias here, + // auto generated alias will be checked in ObSelectResolver::check_auto_gen_column_names(). + LOG_WARN("fail to make field name", K(ret)); + } else if (OB_FAIL(select_stmt->add_select_item(select_item))) { + LOG_WARN("add select item to select stmt failed", K(ret)); } return ret; }