Skip to content

Commit 4aee39d

Browse files
committed
Fix ruleutils.c's dumping of whole-row Vars in more contexts.
Commit 7745bc3 intended to ensure that whole-row Vars would be printed with "::type" decoration in all contexts where plain "var.*" notation would result in star-expansion, notably in ROW() and VALUES() constructs. However, it missed the case of INSERT with a single-row VALUES, as reported by Timur Khanjanov. Nosing around ruleutils.c, I found a second oversight: the code for RowCompareExpr generates ROW() notation without benefit of an actual RowExpr, and naturally it wasn't in sync :-(. (The code for FieldStore also does this, but we don't expect that to generate strictly parsable SQL anyway, so I left it alone.) Back-patch to all supported branches. Discussion: https://postgr.es/m/efaba6f9-4190-56be-8ff2-7a1674f9194f@intrans.baku.az
1 parent 3c1ffd0 commit 4aee39d

File tree

3 files changed

+57
-23
lines changed

3 files changed

+57
-23
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ static void get_rule_expr(Node *node, deparse_context *context,
438438
bool showimplicit);
439439
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
440440
bool showimplicit);
441+
static void get_rule_list_toplevel(List *lst, deparse_context *context,
442+
bool showimplicit);
441443
static void get_rule_expr_funccall(Node *node, deparse_context *context,
442444
bool showimplicit);
443445
static bool looks_like_function(Node *node);
@@ -6580,7 +6582,7 @@ get_insert_query_def(Query *query, deparse_context *context)
65806582
/* Add the single-VALUES expression list */
65816583
appendContextKeyword(context, "VALUES (",
65826584
-PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6583-
get_rule_expr((Node *) strippedexprs, context, false);
6585+
get_rule_list_toplevel(strippedexprs, context, false);
65846586
appendStringInfoChar(buf, ')');
65856587
}
65866588
else
@@ -8944,23 +8946,15 @@ get_rule_expr(Node *node, deparse_context *context,
89448946
case T_RowCompareExpr:
89458947
{
89468948
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
8947-
ListCell *arg;
8948-
char *sep;
89498949

89508950
/*
89518951
* SQL99 allows "ROW" to be omitted when there is more than
8952-
* one column, but for simplicity we always print it.
8952+
* one column, but for simplicity we always print it. Within
8953+
* a ROW expression, whole-row Vars need special treatment, so
8954+
* use get_rule_list_toplevel.
89538955
*/
89548956
appendStringInfoString(buf, "(ROW(");
8955-
sep = "";
8956-
foreach(arg, rcexpr->largs)
8957-
{
8958-
Node *e = (Node *) lfirst(arg);
8959-
8960-
appendStringInfoString(buf, sep);
8961-
get_rule_expr(e, context, true);
8962-
sep = ", ";
8963-
}
8957+
get_rule_list_toplevel(rcexpr->largs, context, true);
89648958

89658959
/*
89668960
* We assume that the name of the first-column operator will
@@ -8973,15 +8967,7 @@ get_rule_expr(Node *node, deparse_context *context,
89738967
generate_operator_name(linitial_oid(rcexpr->opnos),
89748968
exprType(linitial(rcexpr->largs)),
89758969
exprType(linitial(rcexpr->rargs))));
8976-
sep = "";
8977-
foreach(arg, rcexpr->rargs)
8978-
{
8979-
Node *e = (Node *) lfirst(arg);
8980-
8981-
appendStringInfoString(buf, sep);
8982-
get_rule_expr(e, context, true);
8983-
sep = ", ";
8984-
}
8970+
get_rule_list_toplevel(rcexpr->rargs, context, true);
89858971
appendStringInfoString(buf, "))");
89868972
}
89878973
break;
@@ -9526,6 +9512,32 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
95269512
get_rule_expr(node, context, showimplicit);
95279513
}
95289514

9515+
/*
9516+
* get_rule_list_toplevel - Parse back a list of toplevel expressions
9517+
*
9518+
* Apply get_rule_expr_toplevel() to each element of a List.
9519+
*
9520+
* This adds commas between the expressions, but caller is responsible
9521+
* for printing surrounding decoration.
9522+
*/
9523+
static void
9524+
get_rule_list_toplevel(List *lst, deparse_context *context,
9525+
bool showimplicit)
9526+
{
9527+
const char *sep;
9528+
ListCell *lc;
9529+
9530+
sep = "";
9531+
foreach(lc, lst)
9532+
{
9533+
Node *e = (Node *) lfirst(lc);
9534+
9535+
appendStringInfoString(context->buf, sep);
9536+
get_rule_expr_toplevel(e, context, showimplicit);
9537+
sep = ", ";
9538+
}
9539+
}
9540+
95299541
/*
95309542
* get_rule_expr_funccall - Parse back a function-call expression
95319543
*

src/test/regress/expected/create_view.out

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,22 @@ select * from int8_tbl i where i.* in (values(i.*::int8_tbl));
16811681
4567890123456789 | -4567890123456789
16821682
(5 rows)
16831683

1684+
create table tt15v_log(o tt15v, n tt15v, incr bool);
1685+
create rule updlog as on update to tt15v do also
1686+
insert into tt15v_log values(old, new, row(old,old) < row(new,new));
1687+
\d+ tt15v
1688+
View "testviewschm2.tt15v"
1689+
Column | Type | Collation | Nullable | Default | Storage | Description
1690+
--------+-----------------+-----------+----------+---------+----------+-------------
1691+
row | nestedcomposite | | | | extended |
1692+
View definition:
1693+
SELECT ROW(i.*::int8_tbl)::nestedcomposite AS "row"
1694+
FROM int8_tbl i;
1695+
Rules:
1696+
updlog AS
1697+
ON UPDATE TO tt15v DO INSERT INTO tt15v_log (o, n, incr)
1698+
VALUES (old.*::tt15v, new.*::tt15v, (ROW(old.*::tt15v, old.*::tt15v) < ROW(new.*::tt15v, new.*::tt15v)))
1699+
16841700
-- check unique-ification of overlength names
16851701
create view tt18v as
16861702
select * from int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
@@ -1994,7 +2010,7 @@ drop cascades to view aliased_view_2
19942010
drop cascades to view aliased_view_3
19952011
drop cascades to view aliased_view_4
19962012
DROP SCHEMA testviewschm2 CASCADE;
1997-
NOTICE: drop cascades to 73 other objects
2013+
NOTICE: drop cascades to 74 other objects
19982014
DETAIL: drop cascades to table t1
19992015
drop cascades to view temporal1
20002016
drop cascades to view temporal2
@@ -2058,6 +2074,7 @@ drop cascades to type nestedcomposite
20582074
drop cascades to view tt15v
20592075
drop cascades to view tt16v
20602076
drop cascades to view tt17v
2077+
drop cascades to table tt15v_log
20612078
drop cascades to view tt18v
20622079
drop cascades to view tt19v
20632080
drop cascades to view tt20v

src/test/regress/sql/create_view.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,11 @@ select * from tt17v;
565565
select pg_get_viewdef('tt17v', true);
566566
select * from int8_tbl i where i.* in (values(i.*::int8_tbl));
567567

568+
create table tt15v_log(o tt15v, n tt15v, incr bool);
569+
create rule updlog as on update to tt15v do also
570+
insert into tt15v_log values(old, new, row(old,old) < row(new,new));
571+
\d+ tt15v
572+
568573
-- check unique-ification of overlength names
569574

570575
create view tt18v as

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy