提交 d6fa1441 编写于 作者: S st0 提交者: LINGuanRen

fix CTE in mysql mode bug

上级 568b45a8
......@@ -201,6 +201,7 @@ print $fh_header '/**
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
// DO NOT EDIT. This file is automatically generated from `ob_errno.def\'.
#ifndef OCEANBASE_LIB_OB_ERRNO_H_
......
......@@ -12101,7 +12101,7 @@ static struct ObStrErrorInit
ERROR_NAME[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = "OB_ERR_CTE_NEED_QUERY_BLOCKS";
ERROR_CAUSE[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = "Internal Error";
ERROR_SOLUTION[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = "Contact OceanBase Support";
MYSQL_ERRNO[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = -1;
MYSQL_ERRNO[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = 3574;
SQLSTATE[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = "HY000";
STR_ERROR[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = "Recursive Common Table Expression should have one or more non-recursive query blocks followed by one or more recursive ones";
STR_USER_ERROR[-OB_ERR_CTE_NEED_QUERY_BLOCKS] = "Recursive Common Table Expression should have one or more non-recursive query blocks followed by one or more recursive ones: %s";
......@@ -14009,6 +14009,8 @@ static struct ObStrErrorInit
ORACLE_STR_ERROR[-OB_ARCHIVE_LOG_NOT_CONTINUES_WITH_DATA] = "ORA-00600: internal error code, arguments: -9064, the archive log and backup data are not continuous";
ORACLE_STR_USER_ERROR[-OB_ARCHIVE_LOG_NOT_CONTINUES_WITH_DATA] = "ORA-00600: internal error code, arguments: -9064, the archive log and backup data are not continuous";
ERROR_NAME[-OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED] = "OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED";
ERROR_CAUSE[-OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED] = "Internal Error";
ERROR_SOLUTION[-OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED] = "Contact OceanBase Support";
MYSQL_ERRNO[-OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED] = -1;
SQLSTATE[-OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED] = "HY000";
STR_ERROR[-OB_BACKUP_DELETE_BACKUP_PIECE_NOT_ALLOWED] = "deleting backup piece is not allowed";
......@@ -1325,7 +1325,7 @@ DEFINE_ERROR_EXT(OB_ERR_WINDOW_NAME_IS_NOT_DEFINE, -5929, -1, "HY000", "Window n
DEFINE_ORACLE_ERROR(OB_ERR_OPEN_CURSORS_EXCEEDED, -5930, -1, "HY000", "maximum open cursors exceeded", 1000, "maximum open cursors exceeded");
DEFINE_ORACLE_ERROR(OB_ERR_ARG_INVALID, -5931, -1, "HY000", "argument is null, invalid, or out of range", 21560, "argument %.*s is null, invalid, or out of range");
DEFINE_ORACLE_ERROR(OB_ERR_ILL_NAME_STRING, -5932, -1, "HY000", "unexpected name string", 21560, "unexpected name string '%.*s'");
DEFINE_ERROR_EXT(OB_ERR_CTE_NEED_QUERY_BLOCKS, -5976, -1, "HY000", "Recursive Common Table Expression should have one or more non-recursive query blocks followed by one or more recursive ones", "Recursive Common Table Expression should have one or more non-recursive query blocks followed by one or more recursive ones: %s");
DEFINE_ERROR_EXT(OB_ERR_CTE_NEED_QUERY_BLOCKS, -5976, 3574, "HY000", "Recursive Common Table Expression should have one or more non-recursive query blocks followed by one or more recursive ones", "Recursive Common Table Expression should have one or more non-recursive query blocks followed by one or more recursive ones: %s");
DEFINE_ERROR_EXT(OB_ERR_INCORRECT_VALUE_FOR_FUNCTION, -5936, ER_WRONG_VALUE_FOR_TYPE, "HY000", "Incorrect value for function", "Incorrect %.*s value: '%.*s' for function %.*s");
DEFINE_ERROR_EXT(OB_ERR_USER_EXCEED_RESOURCE, -5967, 1226, "42000", "User has exceeded the resource", "User '%.*s' has exceeded the '%s' resource (current value: %lu)");
......
......@@ -825,7 +825,7 @@ int ObSelectStmtPrinter::print_for_update()
int ObSelectStmtPrinter::print_with()
{
int ret = OB_SUCCESS;
DATA_PRINTF("WITH ");
DATA_PRINTF(is_oracle_mode() ? "WITH " : "WITH RECURSIVE");
if (OB_SUCC(ret)) {
const ObSelectStmt* select_stmt = static_cast<const ObSelectStmt*>(stmt_);
const common::ObIArray<TableItem*>& cte_tables = select_stmt->get_CTE_table_items();
......
......@@ -4816,15 +4816,16 @@ int ObOptimizerUtil::is_lossless_column_cast(const ObRawExpr* expr, bool& is_los
}
int ObOptimizerUtil::gen_set_target_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, ObSelectStmt& left_stmt, ObSelectStmt& right_stmt, ObSelectStmt* select_stmt)
ObRawExprFactory* expr_factory, ObSelectStmt& left_stmt, ObSelectStmt& right_stmt,
ObSelectStmt* select_stmt, const bool to_left_type /* false */)
{
int ret = OB_SUCCESS;
ObSEArray<ObSelectStmt*, 1> left_stmts;
ObSEArray<ObSelectStmt*, 1> right_stmts;
if (OB_FAIL(left_stmts.push_back(&left_stmt)) || OB_FAIL(right_stmts.push_back(&right_stmt))) {
LOG_WARN("failed to pushback stmt", K(ret));
} else if (OB_FAIL(
gen_set_target_list(allocator, session_info, expr_factory, left_stmts, right_stmts, select_stmt))) {
} else if (OB_FAIL(gen_set_target_list(
allocator, session_info, expr_factory, left_stmts, right_stmts, select_stmt, to_left_type))) {
LOG_WARN("failed to get set target list", K(ret));
}
return ret;
......@@ -4832,7 +4833,7 @@ int ObOptimizerUtil::gen_set_target_list(ObIAllocator* allocator, ObSQLSessionIn
int ObOptimizerUtil::gen_set_target_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, ObIArray<ObSelectStmt*>& left_stmts, ObIArray<ObSelectStmt*>& right_stmts,
ObSelectStmt* select_stmt)
ObSelectStmt* select_stmt, const bool to_left_type /* false */)
{
int ret = OB_SUCCESS;
UNUSED(allocator);
......@@ -4847,7 +4848,8 @@ int ObOptimizerUtil::gen_set_target_list(ObIAllocator* allocator, ObSQLSessionIn
select_stmt->is_set_distinct(),
left_stmts,
right_stmts,
&res_types))) {
&res_types,
to_left_type))) {
LOG_WARN("failed to try add cast to set child list", K(ret));
} else if (OB_ISNULL(child_stmt = select_stmt->get_set_query(0)) ||
OB_UNLIKELY(res_types.count() != child_stmt->get_select_item_size())) {
......@@ -5031,7 +5033,7 @@ int ObOptimizerUtil::get_set_res_types(ObIAllocator* allocator, ObSQLSessionInfo
int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, const bool is_distinct, ObIArray<ObSelectStmt*>& left_stmts,
ObIArray<ObSelectStmt*>& right_stmts, ObIArray<ObExprResType>* res_types)
ObIArray<ObSelectStmt*>& right_stmts, ObIArray<ObExprResType>* res_types, const bool to_left_type /* false */)
{
int ret = OB_SUCCESS;
ObExprResType res_type;
......@@ -5107,6 +5109,8 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator* allocator, ObS
}
const ObLengthSemantics length_semantics = session_info->get_actual_nls_length_semantics();
if (OB_FAIL(ret)) {
} else if (to_left_type) {
res_type = left_type;
} else if (OB_FAIL(types.push_back(left_type)) || OB_FAIL(types.push_back(right_type))) {
LOG_WARN("failed to push back", K(ret));
} else if (OB_FAIL(session_info->get_collation_connection(coll_type))) {
......@@ -5114,6 +5118,8 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator* allocator, ObS
} else if (OB_FAIL(dummy_op.aggregate_result_type_for_merge(
res_type, &types.at(0), 2, coll_type, is_oracle_mode(), length_semantics, session_info))) {
LOG_WARN("failed to aggregate result type for merge", K(ret));
}
if (OB_FAIL(ret)) {
} else if (ObMaxType == res_type.get_type()) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_WARN("column type incompatible", K(left_type), K(right_type));
......
......@@ -588,11 +588,12 @@ public:
static int is_lossless_column_cast(const ObRawExpr* expr, bool& is_lossless);
static int gen_set_target_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, ObSelectStmt& left_stmt, ObSelectStmt& right_stmt, ObSelectStmt* select_stmt);
ObRawExprFactory* expr_factory, ObSelectStmt& left_stmt, ObSelectStmt& right_stmt,
ObSelectStmt* select_stmt, const bool to_left_type = false);
static int gen_set_target_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, ObIArray<ObSelectStmt*>& left_stmts, ObIArray<ObSelectStmt*>& right_stmts,
ObSelectStmt* select_stmt);
ObSelectStmt* select_stmt, const bool to_left_type = false);
static int gen_set_target_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, ObSelectStmt* select_stmt);
......@@ -602,7 +603,8 @@ public:
static int try_add_cast_to_set_child_list(ObIAllocator* allocator, ObSQLSessionInfo* session_info,
ObRawExprFactory* expr_factory, const bool is_distinct, ObIArray<ObSelectStmt*>& left_stmts,
ObIArray<ObSelectStmt*>& right_stmts, ObIArray<ObExprResType>* res_types);
ObIArray<ObSelectStmt*>& right_stmts, ObIArray<ObExprResType>* res_types,
const bool to_left_type = false);
static int add_cast_to_set_list(ObSQLSessionInfo* session_info, ObRawExprFactory* expr_factory,
ObIArray<ObSelectStmt*>& stmts, const ObExprResType& res_type, const int64_t idx);
......
......@@ -172,8 +172,13 @@ int ObSelectResolver::do_resolve_set_query_in_cte(const ParseNode& parse_tree)
select_stmt->add_set_query(left_select_stmt);
select_stmt->add_set_query(right_select_stmt);
select_stmt->set_calc_found_rows(left_select_stmt->is_calc_found_rows());
if (OB_FAIL(ObOptimizerUtil::gen_set_target_list(
allocator_, session_info_, params_.expr_factory_, *left_select_stmt, *right_select_stmt, select_stmt))) {
if (OB_FAIL(ObOptimizerUtil::gen_set_target_list(allocator_,
session_info_,
params_.expr_factory_,
*left_select_stmt,
*right_select_stmt,
select_stmt,
!is_oracle_mode()))) {
LOG_WARN("failed to gen set target list.", K(ret));
} else if (!right_resolver.cte_ctx_.is_recursive()) {
/*do nothing*/
......@@ -2169,9 +2174,9 @@ int ObSelectResolver::resolve_with_clause(const ParseNode* node, bool same_level
} else {
int num_child = node->num_child_;
if (node->value_ == 0)
params_.has_recursive_word = false;
params_.has_recursive_word_ = false;
else
params_.has_recursive_word = true;
params_.has_recursive_word_ = true;
for (int64_t i = 0; OB_SUCC(ret) && i < num_child; ++i) {
// alias tblname [(alia colname1, alia colname2)](subquery) [search clause][cycle clause]
ParseNode* child_node = node->children_[i];
......@@ -2186,7 +2191,13 @@ int ObSelectResolver::resolve_with_clause(const ParseNode* node, bool same_level
if (OB_FAIL(select_stmt->check_CTE_name_exist(table_name, duplicate_name))) {
LOG_WARN("check cte name failed", K(ret));
} else if (duplicate_name) {
// do nothing, oracle ignore the same define cte name.
if (is_oracle_mode()) {
// do nothing, oracle ignore the same define cte name.
} else {
ret = OB_ERR_NONUNIQ_TABLE;
LOG_WARN("not unique cte table name", K(ret));
LOG_USER_ERROR(OB_ERR_NONUNIQ_TABLE, table_name.length(), table_name.ptr());
}
} else if (OB_FAIL(resolve_with_clause_subquery(*child_node, table_item))) {
LOG_WARN("resolver with_clause_as's subquery failed", K(ret));
} else if (OB_FAIL(select_stmt->add_cte_table_item(table_item, duplicate_name))) {
......@@ -3132,10 +3143,7 @@ int ObSelectResolver::resolve_recursive_cte_table(const ParseNode& parse_tree, T
{
int ret = OB_SUCCESS;
ObSelectStmt* base_stmt = cte_ctx_.left_select_stmt_;
if (cte_ctx_.cte_col_names_.empty()) {
ret = OB_ERR_NEED_COLUMN_ALIAS_LIST_IN_RECURSIVE_CTE;
LOG_WARN("recursive WITH clause must have column alias list", K(ret));
} else if (OB_ISNULL(base_stmt) && cte_ctx_.is_set_left_resolver_) {
if (OB_ISNULL(base_stmt) && cte_ctx_.is_set_left_resolver_) {
ret = OB_ERR_NEED_INIT_BRANCH_IN_RECURSIVE_CTE;
LOG_WARN("recursive WITH clause needs an initialization branch", K(ret));
} else if (OB_ISNULL(base_stmt)) {
......@@ -3318,8 +3326,11 @@ int ObSelectResolver::resolve_basic_table(const ParseNode& parse_tree, TableItem
ObString tblname(table_node->str_len_, table_node->str_value_);
if (cte_ctx_.is_with_resolver() && ObCharset::case_insensitive_equal(cte_ctx_.current_cte_table_name_, tblname) &&
tblname.length() && no_defined_database_name) {
TableItem* item = NULL;
if (OB_FAIL(resolve_recursive_cte_table(parse_tree, item))) {
TableItem *item = NULL;
if (!params_.has_recursive_word_) {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("cte table shows in union stmt without recursive keyword", K(ret));
} else if (OB_FAIL(resolve_recursive_cte_table(parse_tree, item))) {
LOG_WARN("revolve recursive set query's right child failed", K(ret));
} else if (cte_ctx_.more_than_two_branch()) {
ret = OB_ERR_NEED_ONLY_TWO_BRANCH_IN_RECURSIVE_CTE;
......@@ -5504,9 +5515,12 @@ int ObSelectResolver::identify_anchor_member(
need_swap_childa = true;
if (is_oracle_mode()){
ret = OB_SUCCESS;
} else if (params_.has_recursive_word) {
} else if (params_.has_recursive_word_) {
ret = OB_ERR_CTE_NEED_QUERY_BLOCKS; // mysql error: Recursive Common Table Expression 'cte' should have one or
// more non-recursive query blocks followed by one or more recursive ones
} else {
ret = OB_TABLE_NOT_EXIST;
LOG_WARN("cte table shows in left union stmt without recursive keyword", K(ret));
}
} else {
LOG_WARN("Failed to find anchor member", K(ret));
......
......@@ -288,7 +288,7 @@ struct ObResolverParams {
is_multi_table_insert_(false),
is_resolve_table_function_expr_(false),
has_cte_param_list_(false),
has_recursive_word(false),
has_recursive_word_(false),
is_column_ref_(true)
{}
bool is_force_trace_log()
......@@ -343,7 +343,7 @@ public:
bool is_multi_table_insert_; // used to mark is multi table insert
bool is_resolve_table_function_expr_; // used to mark resolve table function expr.
bool has_cte_param_list_;
bool has_recursive_word;
bool has_recursive_word_;
bool is_column_ref_; // used to mark normal column ref
};
} // end namespace sql
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册