Skip to content

Commit 29f7ce6

Browse files
committed
Fix deparsing FETCH FIRST <expr> ROWS WITH TIES
In the grammar, <expr> is a c_expr, which accepts only a limited set of integer literals and simple expressions without parens. The deparsing logic didn't quite match the grammar rule, and failed to use parens e.g. for "5::bigint". To fix, always surround the expression with parens. Would be nice to omit the parens in simple cases, but unfortunately it's non-trivial to detect such simple cases. Even if the expression is a simple literal 123 in the original query, after parse analysis it becomes a FuncExpr with COERCE_IMPLICIT_CAST rather than a simple Const. Reported-by: yonghao lee Backpatch-through: 13 Discussion: https://www.postgresql.org/message-id/18929-077d6b7093b176e2@postgresql.org
1 parent ad5eaf3 commit 29f7ce6

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5956,9 +5956,19 @@ get_select_query_def(Query *query, deparse_context *context)
59565956
{
59575957
if (query->limitOption == LIMIT_OPTION_WITH_TIES)
59585958
{
5959+
/*
5960+
* The limitCount arg is a c_expr, so it needs parens. Simple
5961+
* literals and function expressions would not need parens, but
5962+
* unfortunately it's hard to tell if the expression will be
5963+
* printed as a simple literal like 123 or as a typecast
5964+
* expression, like '-123'::int4. The grammar accepts the former
5965+
* without quoting, but not the latter.
5966+
*/
59595967
appendContextKeyword(context, " FETCH FIRST ",
59605968
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
5969+
appendStringInfoChar(buf, '(');
59615970
get_rule_expr(query->limitCount, context, false);
5971+
appendStringInfoChar(buf, ')');
59625972
appendStringInfoString(buf, " ROWS WITH TIES");
59635973
}
59645974
else

src/test/regress/expected/limit.out

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ View definition:
647647
WHERE thousand < 995
648648
ORDER BY thousand
649649
OFFSET 10
650-
FETCH FIRST 5 ROWS WITH TIES;
650+
FETCH FIRST (5) ROWS WITH TIES;
651651

652652
CREATE VIEW limit_thousand_v_2 AS SELECT thousand FROM onek WHERE thousand < 995
653653
ORDER BY thousand OFFSET 10 FETCH FIRST 5 ROWS ONLY;
@@ -679,15 +679,29 @@ View definition:
679679
FROM onek
680680
WHERE thousand < 995
681681
ORDER BY thousand
682-
FETCH FIRST (NULL::integer + 1) ROWS WITH TIES;
682+
FETCH FIRST ((NULL::integer + 1)) ROWS WITH TIES;
683683

684684
CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995
685-
ORDER BY thousand FETCH FIRST NULL ROWS ONLY;
685+
ORDER BY thousand FETCH FIRST (5::bigint) ROWS WITH TIES;
686686
\d+ limit_thousand_v_4
687687
View "public.limit_thousand_v_4"
688688
Column | Type | Collation | Nullable | Default | Storage | Description
689689
----------+---------+-----------+----------+---------+---------+-------------
690690
thousand | integer | | | | plain |
691+
View definition:
692+
SELECT thousand
693+
FROM onek
694+
WHERE thousand < 995
695+
ORDER BY thousand
696+
FETCH FIRST (5::bigint) ROWS WITH TIES;
697+
698+
CREATE VIEW limit_thousand_v_5 AS SELECT thousand FROM onek WHERE thousand < 995
699+
ORDER BY thousand FETCH FIRST NULL ROWS ONLY;
700+
\d+ limit_thousand_v_5
701+
View "public.limit_thousand_v_5"
702+
Column | Type | Collation | Nullable | Default | Storage | Description
703+
----------+---------+-----------+----------+---------+---------+-------------
704+
thousand | integer | | | | plain |
691705
View definition:
692706
SELECT thousand
693707
FROM onek

src/test/regress/sql/limit.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995
196196
ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES;
197197
\d+ limit_thousand_v_3
198198
CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995
199-
ORDER BY thousand FETCH FIRST NULL ROWS ONLY;
199+
ORDER BY thousand FETCH FIRST (5::bigint) ROWS WITH TIES;
200200
\d+ limit_thousand_v_4
201+
CREATE VIEW limit_thousand_v_5 AS SELECT thousand FROM onek WHERE thousand < 995
202+
ORDER BY thousand FETCH FIRST NULL ROWS ONLY;
203+
\d+ limit_thousand_v_5
201204
-- leave these views

0 commit comments

Comments
 (0)