diff --git a/src/sql/resolver/dml/ob_select_resolver.cpp b/src/sql/resolver/dml/ob_select_resolver.cpp index 0e2edf5dc..ca3d93cc1 100644 --- a/src/sql/resolver/dml/ob_select_resolver.cpp +++ b/src/sql/resolver/dml/ob_select_resolver.cpp @@ -1002,6 +1002,7 @@ int ObSelectResolver::resolve_normal_query(const ParseNode &parse_tree) const ParseNode *group_by = NULL; const ParseNode *having = NULL; ObSelectStmt *select_stmt = get_select_stmt(); + bool has_rollup = false; CK(OB_NOT_NULL(select_stmt), OB_NOT_NULL(session_info_), OB_NOT_NULL(select_stmt->get_query_ctx())); @@ -1023,6 +1024,7 @@ int ObSelectResolver::resolve_normal_query(const ParseNode &parse_tree) OZ( search_connect_group_by_clause(parse_tree, start_with, connect_by, group_by, having) ); if (OB_SUCC(ret) && OB_NOT_NULL(group_by)) { set_has_group_by_clause(); + OZ (check_rollup_clause(group_by, has_rollup)); } if (OB_SUCC(ret) && (start_with != NULL || connect_by != NULL)) { select_stmt->set_hierarchical_query(true); @@ -1044,11 +1046,19 @@ int ObSelectResolver::resolve_normal_query(const ParseNode &parse_tree) if (!is_oracle_mode()) { // mysql resolve: from->where->select_item->group by->having->order by count_name_win_expr = select_stmt->get_window_func_count(); + if (has_rollup) { + expr_resv_ctx_.set_new_scope(); + } OZ( resolve_field_list(*(parse_tree.children_[PARSE_SELECT_SELECT]))); } /* resolve group by clause */ OZ( resolve_group_clause(group_by) ); + + if (has_rollup && is_oracle_mode()) { + expr_resv_ctx_.set_new_scope(); + } + /* resolve having clause */ OZ( resolve_having_clause(having) ); @@ -3605,6 +3615,30 @@ int ObSelectResolver::resolve_group_clause(const ParseNode *node) return ret; } +int ObSelectResolver::check_rollup_clause(const ParseNode *node, bool &has_rollup) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(node) || OB_ISNULL(node->children_) || + OB_UNLIKELY(T_GROUPBY_CLAUSE != node->type_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid resolver arguments", K(ret), K(node)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) { + const ParseNode *child_node = node->children_[i]; + if (OB_ISNULL(child_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(child_node)); + } else if (child_node->type_ == T_ROLLUP_LIST || + child_node->type_ == T_CUBE_LIST || + child_node->type_ == T_GROUPING_SETS_LIST || + child_node->type_ == T_WITH_ROLLUP_CLAUSE) { + has_rollup = true; + } + } + } + return ret; +} + int ObSelectResolver::resolve_group_by_list(const ParseNode *node, common::ObIArray &groupby_exprs, common::ObIArray &rollup_exprs, diff --git a/src/sql/resolver/dml/ob_select_resolver.h b/src/sql/resolver/dml/ob_select_resolver.h index 498ad87aa..aa5dd620d 100644 --- a/src/sql/resolver/dml/ob_select_resolver.h +++ b/src/sql/resolver/dml/ob_select_resolver.h @@ -147,6 +147,8 @@ protected: ObSelectStmt *select_stmt, bool &has_explicit_dir, bool is_groupby_expr); + int check_rollup_clause(const ParseNode *node, bool &has_rollup); + int resolve_group_by_list(const ParseNode *node, common::ObIArray &groupby_exprs, common::ObIArray &rollup_exprs, diff --git a/src/sql/rewrite/ob_transform_query_push_down.cpp b/src/sql/rewrite/ob_transform_query_push_down.cpp index 0dfb63d68..14f4c3a0d 100644 --- a/src/sql/rewrite/ob_transform_query_push_down.cpp +++ b/src/sql/rewrite/ob_transform_query_push_down.cpp @@ -544,6 +544,17 @@ int ObTransformQueryPushDown::check_select_item_push_down(ObSelectStmt *select_s } else { can_be = true; } + if (OB_SUCC(ret) && select_stmt->has_rollup()) { + for (int64_t i = 0; OB_SUCC(ret) && can_be && i < select_exprs.count(); ++i) { + if (OB_ISNULL(select_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select expr is null", K(ret)); + } else { + can_be = !select_exprs.at(i)->is_const_expr() && + !select_exprs.at(i)->has_flag(CNT_SUB_QUERY); + } + } + } return ret; } diff --git a/src/sql/rewrite/ob_transform_view_merge.cpp b/src/sql/rewrite/ob_transform_view_merge.cpp index b45ccebe6..5e09ff56d 100644 --- a/src/sql/rewrite/ob_transform_view_merge.cpp +++ b/src/sql/rewrite/ob_transform_view_merge.cpp @@ -597,6 +597,7 @@ int ObTransformViewMerge::check_can_be_merged(ObDMLStmt *parent_stmt, { int ret = OB_SUCCESS; can_be = true; + bool has_rollup = false; if (OB_ISNULL(parent_stmt) || OB_ISNULL(child_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); @@ -604,6 +605,8 @@ int ObTransformViewMerge::check_can_be_merged(ObDMLStmt *parent_stmt, LOG_WARN("failed to check", K(ret)); } else if (!can_be) { } else { + has_rollup = parent_stmt->is_select_stmt() && + static_cast(parent_stmt)->has_rollup(); //select expr不能包含subquery for (int64_t i = 0; OB_SUCC(ret) && can_be && i < child_stmt->get_select_item_size(); i++) { ObRawExpr *expr = child_stmt->get_select_item(i).expr_; @@ -613,6 +616,9 @@ int ObTransformViewMerge::check_can_be_merged(ObDMLStmt *parent_stmt, } else if (expr->has_flag(CNT_SUB_QUERY)) { can_be = false; OPT_TRACE("view`s select expr contain subquery, can not merge"); + } else if (expr->is_const_expr() && has_rollup) { + can_be = false; + OPT_TRACE("const expr can not be merged into rollup stmt"); } } //stmt不能包含rand函数 https://work.aone.alibaba-inc.com/issue/35875561