diff --git a/src/common/backend/parser/parse_agg.cpp b/src/common/backend/parser/parse_agg.cpp index 2a0311f2d..5a29d8b5f 100755 --- a/src/common/backend/parser/parse_agg.cpp +++ b/src/common/backend/parser/parse_agg.cpp @@ -56,6 +56,7 @@ static void finalize_grouping_exprs( static bool finalize_grouping_exprs_walker(Node* node, check_ungrouped_columns_context* context); static List* expand_groupingset_node(GroupingSet* gs); +static void find_rownum_in_groupby_clauses(Rownum *rownumVar, check_ungrouped_columns_context* context); /* * transformAggregateCall - @@ -742,23 +743,7 @@ static bool check_ungrouped_columns_walker(Node* node, check_ungrouped_columns_c /* If There is ROWNUM, it must appear in the GROUP BY clause or be used in an aggregate function. */ if (IsA(node, Rownum)) { - Rownum *rownumVar = (Rownum *)node; - bool haveRownum = false; - if (!context->have_non_var_grouping || context->sublevels_up != 0) { - foreach (gl, context->groupClauses) { - Node *gnode = (Node *)((TargetEntry *)lfirst(gl))->expr; - if (IsA(gnode, Rownum)) { - haveRownum = true; - break; - } - } - - if (haveRownum == false) { - ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), - errmsg("ROWNUM must appear in the GROUP BY clause or be used in an aggregate function"), - parser_errposition(context->pstate, rownumVar->location))); - } - } + find_rownum_in_groupby_clauses((Rownum *)node, context); } /* * If we have an ungrouped Var of the original query level, we have a @@ -1493,3 +1478,25 @@ Oid resolve_aggregate_transtype(Oid aggfuncid, Oid aggtranstype, Oid* inputTypes } return aggtranstype; } + +static void find_rownum_in_groupby_clauses(Rownum *rownumVar, check_ungrouped_columns_context *context) +{ + bool haveRownum = false; + ListCell *gl = NULL; + + if (!context->have_non_var_grouping || context->sublevels_up != 0) { + foreach (gl, context->groupClauses) { + Node *gnode = (Node *)((TargetEntry *)lfirst(gl))->expr; + if (IsA(gnode, Rownum)) { + haveRownum = true; + break; + } + } + + if (haveRownum == false) { + ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), + errmsg("ROWNUM must appear in the GROUP BY clause or be used in an aggregate function"), + parser_errposition(context->pstate, rownumVar->location))); + } + } +} \ No newline at end of file diff --git a/src/gausskernel/optimizer/prep/prepnonjointree.cpp b/src/gausskernel/optimizer/prep/prepnonjointree.cpp index 2a3b99910..3149cdb2b 100755 --- a/src/gausskernel/optimizer/prep/prepnonjointree.cpp +++ b/src/gausskernel/optimizer/prep/prepnonjointree.cpp @@ -1941,7 +1941,11 @@ static void reduce_orderby_recurse(Query* query, Node* jtnode, bool reduce) /* Reduce orderby clause in subquery for join or from clause of more than one rte */ reduce_orderby_final(rte, reduce); } else if (IsA(jtnode, FromExpr)) { - /* If there is ROWNUM, can not reduce orderby clause in subquery */ + /* If there is ROWNUM, can not reduce orderby clause in subquery from fromlist. + * For example, If there is a SQL {select * from table_name where rownum < n union + * select * from (select * from table_name order by column_name desc) where rownum < n;}, + * can not reduce orderby clause here. + */ if (contain_rownum_walker(jtnode, NULL)) { return; } diff --git a/src/test/regress/expected/xc_rownum.out b/src/test/regress/expected/xc_rownum.out index 331e8485b..b9267f09c 100644 --- a/src/test/regress/expected/xc_rownum.out +++ b/src/test/regress/expected/xc_rownum.out @@ -1640,5 +1640,15 @@ explain select id from student where rownum < 3 union select id from (select id -> Seq Scan on student (cost=0.00..21.34 rows=1134 width=4) (9 rows) +select * from test where id < 2 union select * from (select * from test order by id desc) where rownum < 5; + id | testchar +----+---------- + 8 | test8 + 7 | test7 + 9 | test9 + 1 | test1 + 10 | test10 +(5 rows) + drop table student; drop table test; diff --git a/src/test/regress/sql/xc_rownum.sql b/src/test/regress/sql/xc_rownum.sql index ef3b8ffe6..c0a40a971 100644 --- a/src/test/regress/sql/xc_rownum.sql +++ b/src/test/regress/sql/xc_rownum.sql @@ -460,6 +460,7 @@ explain select id from test where rownum < 5 group by id; -- ROWNUM with UNION and ORDER BY explain select id from student where rownum < 3 union select id from (select id from student order by 1) where rownum < 5; +select * from test where id < 2 union select * from (select * from test order by id desc) where rownum < 5; drop table student; drop table test; \ No newline at end of file