diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 11c00244cf98c3a8b3487544510569b7bbd25e73..9cc4f269518e2d0342f54856a9e2c48bb4d8066f 100755 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -2432,6 +2432,14 @@ static bool _equalDropSynonymStmt(DropSynonymStmt* a, DropSynonymStmt* b) return true; } +static bool _equalRownum(Rownum* a, Rownum* b) +{ + COMPARE_SCALAR_FIELD(rownumcollid); + COMPARE_LOCATION_FIELD(location); + + return true; +} + /* * Stuff from pg_list.h */ @@ -3428,6 +3436,9 @@ bool equal(const void* a, const void* b) case T_DropSynonymStmt: retval = _equalDropSynonymStmt((DropSynonymStmt*)a, (DropSynonymStmt*)b); break; + case T_Rownum: + retval = _equalRownum((Rownum*)a, (Rownum*)b); + break; default: ereport(ERROR, diff --git a/src/common/backend/parser/parse_expr.cpp b/src/common/backend/parser/parse_expr.cpp index e1312395eaafb5544d89871e23c8c3a65d448a3f..730567722c2a7b773bcbb24801efd8782d7942b1 100644 --- a/src/common/backend/parser/parse_expr.cpp +++ b/src/common/backend/parser/parse_expr.cpp @@ -444,7 +444,11 @@ static Node* replaceExprAliasIfNecessary(ParseState* pstate, char* colname, Colu (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("Alias \"%s\" reference with window function included is not supported.", colname), parser_errposition(pstate, cref->location))); - + } else if (contain_rownum_expr((Node*)tle->expr)) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("Alias \"%s\" reference with ROWNUM included is invalid.", colname), + parser_errposition(pstate, cref->location))); } else if (contain_volatile_functions((Node*)tle->expr)) { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 47c69cc0bffba3de1ce36ca9bcb2b39ac6bebdd0..b37449dce10cd759fdaed2240ab6afee79649ea7 100755 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -106,6 +106,12 @@ extern List* extract_function_outarguments(Oid funcid, List* parameters, List* f extern bool need_adjust_agg_inner_func_type(Aggref* aggref); extern bool contain_rownum_walker(Node *node, void *context); + +static inline bool contain_rownum_expr(Node *node) +{ + return contain_rownum_walker(node, NULL); +} + extern List* get_quals_lists(Node *jtnode); #endif /* CLAUSES_H */ diff --git a/src/test/regress/expected/xc_rownum.out b/src/test/regress/expected/xc_rownum.out index 72f0d177c63af27cbba83292630f2ac97ab6bd3d..ed13b49c4d56f2e96a67ba66f18592cbc4dfbc99 100644 --- a/src/test/regress/expected/xc_rownum.out +++ b/src/test/regress/expected/xc_rownum.out @@ -211,7 +211,47 @@ select rownum, name from (select name from distributors where rownum <= 4 inters 2 | westward (2 rows) +--test group by +select rownum from distributors group by rownum; + rownum +-------- + 3 + 1 + 2 + 4 +(4 rows) + +select rownum rn from distributors group by rn; + rn +---- + 3 + 1 + 2 + 4 +(4 rows) + +select rownum + 1 from dual group by rownum; + ?column? +---------- + 2 +(1 row) + +select rownum + 1 rn from dual group by rn; + rn +---- + 2 +(1 row) +--test alias name after where +select rownum rn, name from distributors where rn<3; +ERROR: Alias "rn" reference with ROWNUM included is invalid. +LINE 1: select rownum rn, name from distributors where rn<3; + ^ +select rownum rowno2, * from (select rownum rowno1, * from distributors order by id desc) where rowno2 < 2; +ERROR: Alias "rowno2" reference with ROWNUM included is invalid. +LINE 1: ...wno1, * from distributors order by id desc) where rowno2 < 2... + ^ + --test except and minus --create test table create table except_table (a int, b int); diff --git a/src/test/regress/sql/xc_rownum.sql b/src/test/regress/sql/xc_rownum.sql index becf4892eb9365d1a4d54bfb5a288891d4fe7297..1494a197f1138c99608f0010fec2da006c693c48 100644 --- a/src/test/regress/sql/xc_rownum.sql +++ b/src/test/regress/sql/xc_rownum.sql @@ -80,6 +80,14 @@ select rownum, name from (select name from distributors intersect all select nam select rownum, name from (select name from distributors intersect all select name from actors order by 1) as result where rownum < 3; select rownum, name from (select name from distributors intersect all select name from actors order by 1) as result where rownum < 6; select rownum, name from (select name from distributors where rownum <= 4 intersect all select name from actors where rownum <= 4 order by 1) as result; +--test group by +select rownum from distributors group by rownum; +select rownum rn from distributors group by rn; +select rownum + 1 from dual group by rownum; +select rownum + 1 rn from dual group by rn; +--test alias name after where +select rownum rn, name from distributors where rn<3; +select rownum rowno2, * from (select rownum rowno1, * from distributors order by id desc) where rowno2 < 2; --test except and minus --create test table