aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-12-01 11:38:06 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2022-12-01 11:38:15 -0500
commita711b36e5b88e786f541b6c5671f28e997e68415 (patch)
treeb7a8c8b31f6fc0af2d81b0a542a16581886924c9
parentf79cca5bfd2250c56e93f32a21bd3cd39be07724 (diff)
downloadpostgresql-a711b36e5b88e786f541b6c5671f28e997e68415.tar.gz
postgresql-a711b36e5b88e786f541b6c5671f28e997e68415.zip
Fix under-parenthesized display of AT TIME ZONE constructs.
In commit 40c24bfef, I forgot to use get_rule_expr_paren() for the arguments of AT TIME ZONE, resulting in possibly not printing parens for expressions that need it. But get_rule_expr_paren() wouldn't have gotten it right anyway, because isSimpleNode() hadn't been taught that COERCE_SQL_SYNTAX parent nodes don't guarantee sufficient parentheses. Improve all that. Also use this methodology for F_IS_NORMALIZED, so that we don't print useless parens for that. In passing, remove a comment that was obsoleted later. Per report from Duncan Sands. Back-patch to v14 where this code came in. (Before that, we didn't try to print AT TIME ZONE that way, so there was no bug just ugliness.) Discussion: https://postgr.es/m/f41566aa-a057-6628-4b7c-b48770ecb84a@deepbluecap.com
-rw-r--r--src/backend/utils/adt/ruleutils.c28
-rw-r--r--src/test/regress/expected/create_view.out8
-rw-r--r--src/test/regress/sql/create_view.sql1
3 files changed, 20 insertions, 17 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index d583b8e6f15..8e36745b181 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -8290,11 +8290,12 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
{
case T_FuncExpr:
{
- /* special handling for casts */
+ /* special handling for casts and COERCE_SQL_SYNTAX */
CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
if (type == COERCE_EXPLICIT_CAST ||
- type == COERCE_IMPLICIT_CAST)
+ type == COERCE_IMPLICIT_CAST ||
+ type == COERCE_SQL_SYNTAX)
return false;
return true; /* own parentheses */
}
@@ -8342,11 +8343,12 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
return false;
case T_FuncExpr:
{
- /* special handling for casts */
+ /* special handling for casts and COERCE_SQL_SYNTAX */
CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
if (type == COERCE_EXPLICIT_CAST ||
- type == COERCE_IMPLICIT_CAST)
+ type == COERCE_IMPLICIT_CAST ||
+ type == COERCE_SQL_SYNTAX)
return false;
return true; /* own parentheses */
}
@@ -10117,9 +10119,11 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
case F_TIMEZONE_TEXT_TIMETZ:
/* AT TIME ZONE ... note reversed argument order */
appendStringInfoChar(buf, '(');
- get_rule_expr((Node *) lsecond(expr->args), context, false);
+ get_rule_expr_paren((Node *) lsecond(expr->args), context, false,
+ (Node *) expr);
appendStringInfoString(buf, " AT TIME ZONE ");
- get_rule_expr((Node *) linitial(expr->args), context, false);
+ get_rule_expr_paren((Node *) linitial(expr->args), context, false,
+ (Node *) expr);
appendStringInfoChar(buf, ')');
return true;
@@ -10171,9 +10175,10 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
case F_IS_NORMALIZED:
/* IS xxx NORMALIZED */
- appendStringInfoString(buf, "((");
- get_rule_expr((Node *) linitial(expr->args), context, false);
- appendStringInfoString(buf, ") IS");
+ appendStringInfoString(buf, "(");
+ get_rule_expr_paren((Node *) linitial(expr->args), context, false,
+ (Node *) expr);
+ appendStringInfoString(buf, " IS");
if (list_length(expr->args) == 2)
{
Const *con = (Const *) lsecond(expr->args);
@@ -10194,11 +10199,6 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
appendStringInfoChar(buf, ')');
return true;
- /*
- * XXX EXTRACT, a/k/a date_part(), is intentionally not covered
- * yet. Add it after we change the return type to numeric.
- */
-
case F_NORMALIZE:
/* NORMALIZE() */
appendStringInfoString(buf, "NORMALIZE(");
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 001191c012d..11814bfd06f 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1922,6 +1922,7 @@ select pg_get_viewdef('tt20v', true);
-- reverse-listing of various special function syntaxes required by SQL
create view tt201v as
select
+ ('2022-12-01'::date + '1 day'::interval) at time zone 'UTC' as atz,
extract(day from now()) as extr,
(now(), '1 day'::interval) overlaps
(current_timestamp(2), '1 day'::interval) as o,
@@ -1944,10 +1945,11 @@ select
select pg_get_viewdef('tt201v', true);
pg_get_viewdef
-----------------------------------------------------------------------------------------------
- SELECT EXTRACT(day FROM now()) AS extr, +
+ SELECT (('12-01-2022'::date + '@ 1 day'::interval) AT TIME ZONE 'UTC'::text) AS atz, +
+ EXTRACT(day FROM now()) AS extr, +
((now(), '@ 1 day'::interval) OVERLAPS (CURRENT_TIMESTAMP(2), '@ 1 day'::interval)) AS o,+
- (('foo'::text) IS NORMALIZED) AS isn, +
- (('foo'::text) IS NFKC NORMALIZED) AS isnn, +
+ ('foo'::text IS NORMALIZED) AS isn, +
+ ('foo'::text IS NFKC NORMALIZED) AS isnn, +
NORMALIZE('foo'::text) AS n, +
NORMALIZE('foo'::text, NFKD) AS nfkd, +
OVERLAY('foo'::text PLACING 'bar'::text FROM 2) AS ovl, +
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index 44a6775f907..2e0288c5705 100644
--- a/src/test/regress/sql/create_view.sql
+++ b/src/test/regress/sql/create_view.sql
@@ -703,6 +703,7 @@ select pg_get_viewdef('tt20v', true);
create view tt201v as
select
+ ('2022-12-01'::date + '1 day'::interval) at time zone 'UTC' as atz,
extract(day from now()) as extr,
(now(), '1 day'::interval) overlaps
(current_timestamp(2), '1 day'::interval) as o,