Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 43c2175

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 dfc0cb3 commit 43c2175

File tree

3 files changed

+57
-23
lines changed

3 files changed

+57
-23
lines changed

src/backend/utils/adt/ruleutils.c

+34-22
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);
@@ -6632,7 +6634,7 @@ get_insert_query_def(Query *query, deparse_context *context)
66326634
/* Add the single-VALUES expression list */
66336635
appendContextKeyword(context, "VALUES (",
66346636
-PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6635-
get_rule_expr((Node *) strippedexprs, context, false);
6637+
get_rule_list_toplevel(strippedexprs, context, false);
66366638
appendStringInfoChar(buf, ')');
66376639
}
66386640
else
@@ -8996,23 +8998,15 @@ get_rule_expr(Node *node, deparse_context *context,
89968998
case T_RowCompareExpr:
89978999
{
89989000
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
8999-
ListCell *arg;
9000-
char *sep;
90019001

90029002
/*
90039003
* SQL99 allows "ROW" to be omitted when there is more than
9004-
* one column, but for simplicity we always print it.
9004+
* one column, but for simplicity we always print it. Within
9005+
* a ROW expression, whole-row Vars need special treatment, so
9006+
* use get_rule_list_toplevel.
90059007
*/
90069008
appendStringInfoString(buf, "(ROW(");
9007-
sep = "";
9008-
foreach(arg, rcexpr->largs)
9009-
{
9010-
Node *e = (Node *) lfirst(arg);
9011-
9012-
appendStringInfoString(buf, sep);
9013-
get_rule_expr(e, context, true);
9014-
sep = ", ";
9015-
}
9009+
get_rule_list_toplevel(rcexpr->largs, context, true);
90169010

90179011
/*
90189012
* We assume that the name of the first-column operator will
@@ -9025,15 +9019,7 @@ get_rule_expr(Node *node, deparse_context *context,
90259019
generate_operator_name(linitial_oid(rcexpr->opnos),
90269020
exprType(linitial(rcexpr->largs)),
90279021
exprType(linitial(rcexpr->rargs))));
9028-
sep = "";
9029-
foreach(arg, rcexpr->rargs)
9030-
{
9031-
Node *e = (Node *) lfirst(arg);
9032-
9033-
appendStringInfoString(buf, sep);
9034-
get_rule_expr(e, context, true);
9035-
sep = ", ";
9036-
}
9022+
get_rule_list_toplevel(rcexpr->rargs, context, true);
90379023
appendStringInfoString(buf, "))");
90389024
}
90399025
break;
@@ -9578,6 +9564,32 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
95789564
get_rule_expr(node, context, showimplicit);
95799565
}
95809566

9567+
/*
9568+
* get_rule_list_toplevel - Parse back a list of toplevel expressions
9569+
*
9570+
* Apply get_rule_expr_toplevel() to each element of a List.
9571+
*
9572+
* This adds commas between the expressions, but caller is responsible
9573+
* for printing surrounding decoration.
9574+
*/
9575+
static void
9576+
get_rule_list_toplevel(List *lst, deparse_context *context,
9577+
bool showimplicit)
9578+
{
9579+
const char *sep;
9580+
ListCell *lc;
9581+
9582+
sep = "";
9583+
foreach(lc, lst)
9584+
{
9585+
Node *e = (Node *) lfirst(lc);
9586+
9587+
appendStringInfoString(context->buf, sep);
9588+
get_rule_expr_toplevel(e, context, showimplicit);
9589+
sep = ", ";
9590+
}
9591+
}
9592+
95819593
/*
95829594
* get_rule_expr_funccall - Parse back a function-call expression
95839595
*

src/test/regress/expected/create_view.out

+18-1
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

+5
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)