From 772c61d04b0ac1ab6ec06be1c382c99140c9650c Mon Sep 17 00:00:00 2001 From: chimyue Date: Mon, 22 Apr 2024 06:19:31 +0000 Subject: [PATCH] fix mview fast refresh bug when query contain special expr --- src/sql/resolver/dml/ob_dml_stmt.cpp | 20 +++++++++++++++++ src/sql/resolver/dml/ob_dml_stmt.h | 1 + src/sql/resolver/mv/ob_mv_checker.cpp | 31 +++++++++++++++++++++++---- src/sql/resolver/mv/ob_mv_checker.h | 1 + 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/sql/resolver/dml/ob_dml_stmt.cpp b/src/sql/resolver/dml/ob_dml_stmt.cpp index b2f81b362..22a915003 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.cpp +++ b/src/sql/resolver/dml/ob_dml_stmt.cpp @@ -3681,6 +3681,26 @@ int ObDMLStmt::has_special_expr(const ObExprInfoFlag flag, bool &has) const return ret; } +int ObDMLStmt::has_special_exprs(const ObSqlBitSet<> &flags, bool &has) const +{ + int ret = OB_SUCCESS; + ObSEArray exprs; + has = false; + if (OB_FAIL(get_relation_exprs(exprs))) { + LOG_WARN("failed to get relation exprs", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && !has && i < exprs.count(); i++) { + if (OB_ISNULL(exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (exprs.at(i)->get_expr_info().overlap(flags)) { + has = true; + } + } + } + return ret; +} + int ObDMLStmt::rebuild_tables_hash() { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/dml/ob_dml_stmt.h b/src/sql/resolver/dml/ob_dml_stmt.h index 49e8aef0a..c62ad2e6e 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.h +++ b/src/sql/resolver/dml/ob_dml_stmt.h @@ -1106,6 +1106,7 @@ public: int get_udf_exprs(common::ObIArray &exprs) const; int has_rand(bool &has_rand) const { return has_special_expr(CNT_RAND_FUNC, has_rand); } virtual int has_special_expr(const ObExprInfoFlag, bool &has) const; + int has_special_exprs(const ObSqlBitSet<> &flags, bool &has) const; const TransposeItem *get_transpose_item() const { return transpose_item_; } void set_transpose_item(const TransposeItem *transpose_item) { transpose_item_ = transpose_item; } const ObUnpivotInfo get_unpivot_info() const diff --git a/src/sql/resolver/mv/ob_mv_checker.cpp b/src/sql/resolver/mv/ob_mv_checker.cpp index 151435e38..239770a61 100644 --- a/src/sql/resolver/mv/ob_mv_checker.cpp +++ b/src/sql/resolver/mv/ob_mv_checker.cpp @@ -122,11 +122,10 @@ int ObMVChecker::check_mv_stmt_refresh_type_basic(const ObSelectStmt &stmt, bool if (OB_SUCC(ret)) { bool has_rownum = false; bool has_special_expr = false; - const ObExprInfoFlag flag = CNT_RAND_FUNC; if (OB_FAIL(stmt.has_rownum(has_rownum))) { LOG_WARN("failed to check has rownum", K(ret)); - } else if (OB_FAIL(stmt.has_special_expr(flag, has_special_expr))) { - LOG_WARN("failed to check has special expr", K(ret)); + } else if (OB_FAIL(check_mv_stmt_use_special_expr(stmt, has_special_expr))) { + LOG_WARN("failed to check mv stmt use special expr", K(ret)); } else if (has_special_expr || has_rownum || stmt.has_ora_rowscn()) { is_valid = false; append_fast_refreshable_note("rownum/ora_rowscn/rand_func not support"); @@ -153,6 +152,30 @@ int ObMVChecker::check_mv_stmt_refresh_type_basic(const ObSelectStmt &stmt, bool return ret; } +int ObMVChecker::check_mv_stmt_use_special_expr(const ObSelectStmt &stmt, bool &has_special_expr) +{ + int ret = OB_SUCCESS; + ObSqlBitSet<> flags; + ObExprInfoFlag flag_arr[] = { CNT_RAND_FUNC, + CNT_STATE_FUNC, + CNT_SEQ_EXPR, + CNT_VOLATILE_CONST, + CNT_DYNAMIC_USER_VARIABLE, + CNT_CUR_TIME, + /* add new check flag above CNT_ASSOCIATED_FLAG_END */ + CNT_ASSOCIATED_FLAG_END }; + for (int64_t i = 0; OB_SUCC(ret) && CNT_ASSOCIATED_FLAG_END != flag_arr[i] ; ++i) { + if (OB_FAIL(flags.add_member(flag_arr[i]))) { + LOG_WARN("failed to add member", K(ret), K(i), K(flag_arr[i])); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(stmt.has_special_exprs(flags, has_special_expr))) { + LOG_WARN("failed to check has special exprs", K(ret)); + } + return ret; +} + int ObMVChecker::check_mv_duplicated_exprs(const ObSelectStmt &stmt, bool &has_dup_exprs) { int ret = OB_SUCCESS; @@ -657,7 +680,7 @@ int ObMVChecker::check_mjv_refresh_type(const ObSelectStmt &stmt, ObMVRefreshabl } else if (OB_FAIL(check_select_contains_all_tables_primary_key(stmt, select_valid))) { LOG_WARN("failed to check check select contains all tables primary key", K(ret)); } else if (!select_valid) { - append_fast_refreshable_note("outer join not support"); + append_fast_refreshable_note("base table primary key need in select for MJV"); } else { refresh_type = OB_MV_FAST_REFRESH_SIMPLE_MJV; } diff --git a/src/sql/resolver/mv/ob_mv_checker.h b/src/sql/resolver/mv/ob_mv_checker.h index c516e0f32..154bc86dd 100644 --- a/src/sql/resolver/mv/ob_mv_checker.h +++ b/src/sql/resolver/mv/ob_mv_checker.h @@ -80,6 +80,7 @@ private: int check_mv_join_type(const ObSelectStmt &stmt, bool &join_type_valid); bool is_mv_join_type_valid(const TableItem *table); int check_select_contains_all_tables_primary_key(const ObSelectStmt &stmt, bool &contain_all_rowkey); + int check_mv_stmt_use_special_expr(const ObSelectStmt &stmt, bool &has_special_expr); int check_mv_dependency_mlog_tables(const ObSelectStmt &stmt, bool &is_valid); int check_mv_duplicated_exprs(const ObSelectStmt &stmt, bool &has_dup_exprs); bool check_mlog_table_valid(const share::schema::ObTableSchema *table_schema,