8000 Fix ruleutils.c's dumping of whole-row Vars in more contexts. · postgres/postgres@4aee39d · GitHub
[go: up one dir, main page]

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-
10000 {
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)
0