Skip to content

Commit 3a1bfe2

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 790d6ed commit 3a1bfe2

File tree

3 files changed

+56
-23
lines changed

3 files changed

+56
-23
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ static void get_rule_expr(Node *node, deparse_context *context,
420420
bool showimplicit);
421421
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
422422
bool showimplicit);
423+
static void get_rule_list_toplevel(List *lst, deparse_context *context,
424+
bool showimplicit);
423425
static void get_rule_expr_funccall(Node *node, deparse_context *context,
424426
bool showimplicit);
425427
static bool looks_like_function(Node *node);
@@ -6205,7 +6207,7 @@ get_insert_query_def(Query *query, deparse_context *context)
62056207
/* Add the single-VALUES expression list */
62066208
appendContextKeyword(context, "VALUES (",
62076209
-PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6208-
get_rule_expr((Node *) strippedexprs, context, false);
6210+
get_rule_list_toplevel(strippedexprs, context, false);
62096211
appendStringInfoChar(buf, ')');
62106212
}
62116213
else
@@ -8389,23 +8391,15 @@ get_rule_expr(Node *node, deparse_context *context,
83898391
case T_RowCompareExpr:
83908392
{
83918393
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
8392-
ListCell *arg;
8393-
char *sep;
83948394

83958395
/*
83968396
* SQL99 allows "ROW" to be omitted when there is more than
8397-
* one column, but for simplicity we always print it.
8397+
* one column, but for simplicity we always print it. Within
8398+
* a ROW expression, whole-row Vars need special treatment, so
8399+
* use get_rule_list_toplevel.
83988400
*/
83998401
appendStringInfoString(buf, "(ROW(");
8400-
sep = "";
8401-
foreach(arg, rcexpr->largs)
8402-
{
8403-
Node *e = (Node *) lfirst(arg);
8404-
8405-
appendStringInfoString(buf, sep);
8406-
get_rule_expr(e, context, true);
8407-
sep = ", ";
8408-
}
8402+
get_rule_list_toplevel(rcexpr->largs, context, true);
84098403

84108404
/*
84118405
* We assume that the name of the first-column operator will
@@ -8418,15 +8412,7 @@ get_rule_expr(Node *node, deparse_context *context,
84188412
generate_operator_name(linitial_oid(rcexpr->opnos),
84198413
exprType(linitial(rcexpr->largs)),
84208414
exprType(linitial(rcexpr->rargs))));
8421-
sep = "";
8422-
foreach(arg, rcexpr->rargs)
8423-
{
8424-
Node *e = (Node *) lfirst(arg);
8425-
8426-
appendStringInfoString(buf, sep);
8427-
get_rule_expr(e, context, true);
8428-
sep = ", ";
8429-
}
8415+
get_rule_list_toplevel(rcexpr->rargs, context, true);
84308416
appendStringInfoString(buf, "))");
84318417
}
84328418
break;
@@ -8971,6 +8957,32 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
89718957
get_rule_expr(node, context, showimplicit);
89728958
}
89738959

8960+
/*
8961+
* get_rule_list_toplevel - Parse back a list of toplevel expressions
8962+
*
8963+
* Apply get_rule_expr_toplevel() to each element of a List.
8964+
*
8965+
* This adds commas between the expressions, but caller is responsible
8966+
* for printing surrounding decoration.
8967+
*/
8968+
static void
8969+
get_rule_list_toplevel(List *lst, deparse_context *context,
8970+
bool showimplicit)
8971+
{
8972+
const char *sep;
8973+
ListCell *lc;
8974+
8975+
sep = "";
8976+
foreach(lc, lst)
8977+
{
8978+
Node *e = (Node *) lfirst(lc);
8979+
8980+
appendStringInfoString(context->buf, sep);
8981+
get_rule_expr_toplevel(e, context, showimplicit);
8982+
sep = ", ";
8983+
}
8984+
}
8985+
89748986
/*
89758987
* get_rule_expr_funccall - Parse back a function-call expression
89768988
*

src/test/regress/expected/create_view.out

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,22 @@ select * from int8_tbl i where i.* in (values(i.*::int8_tbl));
16121612
4567890123456789 | -4567890123456789
16131613
(5 rows)
16141614

1615+
create table tt15v_log(o tt15v, n tt15v, incr bool);
1616+
create rule updlog as on update to tt15v do also
1617+
insert into tt15v_log values(old, new, row(old,old) < row(new,new));
1618+
\d+ tt15v
1619+
View "testviewschm2.tt15v"
1620+
Column | Type | Collation | Nullable | Default | Storage | Description
1621+
--------+-----------------+-----------+----------+---------+----------+-------------
1622+
row | nestedcomposite | | | | extended |
1623+
View definition:
1624+
SELECT ROW(i.*::int8_tbl)::nestedcomposite AS "row"
1625+
FROM int8_tbl i;
1626+
Rules:
1627+
updlog AS
1628+
ON UPDATE TO tt15v DO INSERT INTO tt15v_log (o, n, incr)
1629+
VALUES (old.*::tt15v, new.*::tt15v, (ROW(old.*::tt15v, old.*::tt15v) < ROW(new.*::tt15v, new.*::tt15v)))
1630+
16151631
-- check unique-ification of overlength names
16161632
create view tt18v as
16171633
select * from int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
@@ -1756,4 +1772,4 @@ select pg_get_ruledef(oid, true) from pg_rewrite
17561772
DROP SCHEMA temp_view_test CASCADE;
17571773
NOTICE: drop cascades to 27 other objects
17581774
DROP SCHEMA testviewschm2 CASCADE;
1759-
NOTICE: drop cascades to 63 other objects
1775+
NOTICE: drop cascades to 64 other objects

src/test/regress/sql/create_view.sql

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

551+
create table tt15v_log(o tt15v, n tt15v, incr bool);
552+
create rule updlog as on update to tt15v do also
553+
insert into tt15v_log values(old, new, row(old,old) < row(new,new));
554+
\d+ tt15v
555+
551556
-- check unique-ification of overlength names
552557

553558
create view tt18v as

0 commit comments

Comments
 (0)