From 7dcf2baa4ea3ad335430f8c8d0831ab89445dffb Mon Sep 17 00:00:00 2001 From: obdev Date: Sun, 11 Jul 2021 19:45:11 +0800 Subject: [PATCH] Fix query push down and add subquery handling --- src/sql/resolver/dml/ob_dml_stmt.cpp | 17 ++++++ src/sql/resolver/dml/ob_dml_stmt.h | 1 + .../rewrite/ob_transform_query_push_down.cpp | 56 +++++++++++++++++++ .../rewrite/ob_transform_query_push_down.h | 4 +- src/sql/rewrite/ob_transform_utils.cpp | 17 +++++- 5 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/sql/resolver/dml/ob_dml_stmt.cpp b/src/sql/resolver/dml/ob_dml_stmt.cpp index 438236090..908cb7edd 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.cpp +++ b/src/sql/resolver/dml/ob_dml_stmt.cpp @@ -3084,6 +3084,23 @@ bool ObDMLStmt::has_link_table() const return bret; } +int ObDMLStmt::get_table_rel_ids(const TableItem &target, + ObSqlBitSet<> &table_set) const +{ + int ret = OB_SUCCESS; + if (target.is_joined_table()) { + const JoinedTable &cur_table = static_cast(target); + for (int64_t i = 0; OB_SUCC(ret) && i < cur_table.single_table_ids_.count(); ++i) { + if (OB_FAIL(table_set.add_member(get_table_bit_index(cur_table.single_table_ids_.at(i))))) { + LOG_WARN("failed to add member", K(ret), K(cur_table.single_table_ids_.at(i))); + } + } + } else if (OB_FAIL(table_set.add_member(get_table_bit_index(target.table_id_)))) { + LOG_WARN("failed to add member", K(ret), K(target.table_id_)); + } + return ret; +} + int ObDMLStmt::get_relation_exprs(ObIArray& rel_array, int32_t ignore_scope /* = 0*/) const { 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 b04a24876..96956b1cd 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.h +++ b/src/sql/resolver/dml/ob_dml_stmt.h @@ -887,6 +887,7 @@ public: virtual int clear_sharable_expr_reference(); virtual int get_from_subquery_stmts(common::ObIArray& child_stmts) const; int is_referred_by_partitioning_expr(const ObRawExpr* expr, bool& is_referred); + int get_table_rel_ids(const TableItem &target, ObSqlBitSet<> &table_set) const; int64_t get_table_size() const { return table_items_.count(); diff --git a/src/sql/rewrite/ob_transform_query_push_down.cpp b/src/sql/rewrite/ob_transform_query_push_down.cpp index af73ec1a5..fb51dee4d 100644 --- a/src/sql/rewrite/ob_transform_query_push_down.cpp +++ b/src/sql/rewrite/ob_transform_query_push_down.cpp @@ -342,6 +342,10 @@ int ObTransformQueryPushDown::check_select_item_push_down(ObSelectStmt* select_s if (OB_ISNULL(select_stmt) || OB_ISNULL(view_stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("stmt is NULL", K(select_stmt), K(view_stmt), K(ret)); + } else if (OB_FAIL(check_select_item_subquery(*select_stmt, *view_stmt, check_status))) { + LOG_WARN("failed to check select item has subquery", K(ret)); + } else if (!check_status) { + can_be = false; } else if (view_stmt->is_contains_assignment() || select_stmt->is_contains_assignment()) { can_be = false; } else if (OB_FAIL(is_select_item_same(select_stmt, view_stmt, check_status, select_offset, const_select_items))) { @@ -358,6 +362,58 @@ int ObTransformQueryPushDown::check_select_item_push_down(ObSelectStmt* select_s return ret; } +int ObTransformQueryPushDown::check_select_item_subquery(ObSelectStmt &select_stmt, + ObSelectStmt &view, + bool &can_be) +{ + int ret = OB_SUCCESS; + can_be = true; + ObSEArray column_exprs_from_subquery; + ObRawExpr *expr = NULL; + TableItem *table = NULL; + ObSqlBitSet<> table_set; + if (OB_UNLIKELY(1 != select_stmt.get_table_items().count()) + || OB_ISNULL(table = select_stmt.get_table_item(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect select stmt", K(ret), K(select_stmt.get_from_item_size()), K(table)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < view.get_select_item_size(); ++i) { + if (OB_ISNULL(expr = view.get_select_item(i).expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null expr", K(ret)); + } else if (!expr->has_flag(CNT_SUB_QUERY)) { + /* do nothing */ + } else if (OB_ISNULL(expr = select_stmt.get_column_expr_by_id(table->table_id_, + i + OB_APP_MIN_COLUMN_ID))) { + /* do nothing */ + } else if (OB_FAIL(column_exprs_from_subquery.push_back(expr))) { + LOG_WARN("failed to push back column expr", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (column_exprs_from_subquery.empty()) { + /* do nothing */ + } else if (OB_FAIL(select_stmt.get_table_rel_ids(*table, table_set))) { + LOG_WARN("failed to get rel ids", K(ret)); + } else { + ObIArray &subquery_exprs = select_stmt.get_subquery_exprs(); + ObSEArray ignore_stmts; + ObSEArray column_exprs; + for (int64_t i = 0; OB_SUCC(ret) && can_be && i < subquery_exprs.count(); ++i) { + column_exprs.reuse(); + if(OB_FAIL(ObTransformUtils::extract_column_exprs(subquery_exprs.at(i), + select_stmt.get_current_level(), + table_set, ignore_stmts, + column_exprs))) { + LOG_WARN("extract column exprs failed", K(ret)); + } else if (ObOptimizerUtil::overlap(column_exprs, column_exprs_from_subquery)) { + can_be = false; + } + } + } + return ret; +} + int ObTransformQueryPushDown::check_where_condition_push_down( ObSelectStmt* select_stmt, ObSelectStmt* view_stmt, bool& transform_having, bool& can_be) { diff --git a/src/sql/rewrite/ob_transform_query_push_down.h b/src/sql/rewrite/ob_transform_query_push_down.h index 525b56ef3..956230a83 100644 --- a/src/sql/rewrite/ob_transform_query_push_down.h +++ b/src/sql/rewrite/ob_transform_query_push_down.h @@ -56,7 +56,9 @@ private: int check_select_item_push_down(ObSelectStmt* select_stmt, ObSelectStmt* view_stmt, common::ObIArray& select_offset, common::ObIArray& const_select_items, bool& can_be); - int check_select_item_has_subquery(ObSelectStmt& view, bool& has); + int check_select_item_subquery(ObSelectStmt &select_stmt, + ObSelectStmt &view, + bool &can_be); int adjust_stmt_hints(ObSelectStmt* select_stmt, ObSelectStmt* view_stmt); diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index e1495de70..f4c60c4f1 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -4594,6 +4594,7 @@ int ObTransformUtils::extract_column_exprs(ObDMLStmt* stmt, const int64_t stmt_l { int ret = OB_SUCCESS; ObSEArray relation_exprs; + ObSEArray child_stmts; bool is_stack_overflow = false; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; @@ -4609,7 +4610,19 @@ int ObTransformUtils::extract_column_exprs(ObDMLStmt* stmt, const int64_t stmt_l LOG_WARN("failed to get relation exprs", K(ret)); } else if (OB_FAIL(SMART_CALL(extract_column_exprs(relation_exprs, stmt_level, table_set, ignore_stmts, columns)))) { LOG_WARN("failed to extract column exprs", K(ret)); - } else { /*do nothing*/ + } else if (OB_FAIL(stmt->get_from_subquery_stmts(child_stmts))) { + LOG_WARN("get child stmt failed", K(ret)); + } else { + 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("invalid stmt", K(ret)); + } else if (OB_FAIL(SMART_CALL(extract_column_exprs(child_stmt, stmt_level, table_set, + ignore_stmts, columns)))) { + LOG_WARN("failed to extract column exprs", K(ret)); + } + } } return ret; } @@ -6545,7 +6558,7 @@ int ObTransformUtils::convert_select_expr_to_column_expr(const common::ObIArray< ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to find select expr inner stmt", K(ret)); } else if (OB_ISNULL(col = outer_stmt.get_column_expr_by_id(table_id, column_id))) { - LOG_WARN("failed to get column expr by id", K(ret)); + //do nothing } else if (OB_FAIL(column_exprs.push_back(col))) { LOG_WARN("failed to push back column expr", K(ret)); }