1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-23 14:01:44 +03:00

Fix ruleutils.c's dumping of whole-row Vars in more contexts.

Commit 7745bc352 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
This commit is contained in:
Tom Lane
2022-01-13 17:49:26 -05:00
parent 790d6edf63
commit 3a1bfe2565
3 changed files with 56 additions and 23 deletions

View File

@ -420,6 +420,8 @@ static void get_rule_expr(Node *node, deparse_context *context,
bool showimplicit); bool showimplicit);
static void get_rule_expr_toplevel(Node *node, deparse_context *context, static void get_rule_expr_toplevel(Node *node, deparse_context *context,
bool showimplicit); bool showimplicit);
static void get_rule_list_toplevel(List *lst, deparse_context *context,
bool showimplicit);
static void get_rule_expr_funccall(Node *node, deparse_context *context, static void get_rule_expr_funccall(Node *node, deparse_context *context,
bool showimplicit); bool showimplicit);
static bool looks_like_function(Node *node); static bool looks_like_function(Node *node);
@ -6205,7 +6207,7 @@ get_insert_query_def(Query *query, deparse_context *context)
/* Add the single-VALUES expression list */ /* Add the single-VALUES expression list */
appendContextKeyword(context, "VALUES (", appendContextKeyword(context, "VALUES (",
-PRETTYINDENT_STD, PRETTYINDENT_STD, 2); -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
get_rule_expr((Node *) strippedexprs, context, false); get_rule_list_toplevel(strippedexprs, context, false);
appendStringInfoChar(buf, ')'); appendStringInfoChar(buf, ')');
} }
else else
@ -8389,23 +8391,15 @@ get_rule_expr(Node *node, deparse_context *context,
case T_RowCompareExpr: case T_RowCompareExpr:
{ {
RowCompareExpr *rcexpr = (RowCompareExpr *) node; RowCompareExpr *rcexpr = (RowCompareExpr *) node;
ListCell *arg;
char *sep;
/* /*
* SQL99 allows "ROW" to be omitted when there is more than * SQL99 allows "ROW" to be omitted when there is more than
* one column, but for simplicity we always print it. * one column, but for simplicity we always print it. Within
* a ROW expression, whole-row Vars need special treatment, so
* use get_rule_list_toplevel.
*/ */
appendStringInfoString(buf, "(ROW("); appendStringInfoString(buf, "(ROW(");
sep = ""; get_rule_list_toplevel(rcexpr->largs, context, true);
foreach(arg, rcexpr->largs)
{
Node *e = (Node *) lfirst(arg);
appendStringInfoString(buf, sep);
get_rule_expr(e, context, true);
sep = ", ";
}
/* /*
* We assume that the name of the first-column operator will * We assume that the name of the first-column operator will
@ -8418,15 +8412,7 @@ get_rule_expr(Node *node, deparse_context *context,
generate_operator_name(linitial_oid(rcexpr->opnos), generate_operator_name(linitial_oid(rcexpr->opnos),
exprType(linitial(rcexpr->largs)), exprType(linitial(rcexpr->largs)),
exprType(linitial(rcexpr->rargs)))); exprType(linitial(rcexpr->rargs))));
sep = ""; get_rule_list_toplevel(rcexpr->rargs, context, true);
foreach(arg, rcexpr->rargs)
{
Node *e = (Node *) lfirst(arg);
appendStringInfoString(buf, sep);
get_rule_expr(e, context, true);
sep = ", ";
}
appendStringInfoString(buf, "))"); appendStringInfoString(buf, "))");
} }
break; break;
@ -8971,6 +8957,32 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
get_rule_expr(node, context, showimplicit); get_rule_expr(node, context, showimplicit);
} }
/*
* get_rule_list_toplevel - Parse back a list of toplevel expressions
*
* Apply get_rule_expr_toplevel() to each element of a List.
*
* This adds commas between the expressions, but caller is responsible
* for printing surrounding decoration.
*/
static void
get_rule_list_toplevel(List *lst, deparse_context *context,
bool showimplicit)
{
const char *sep;
ListCell *lc;
sep = "";
foreach(lc, lst)
{
Node *e = (Node *) lfirst(lc);
appendStringInfoString(context->buf, sep);
get_rule_expr_toplevel(e, context, showimplicit);
sep = ", ";
}
}
/* /*
* get_rule_expr_funccall - Parse back a function-call expression * get_rule_expr_funccall - Parse back a function-call expression
* *

View File

@ -1612,6 +1612,22 @@ select * from int8_tbl i where i.* in (values(i.*::int8_tbl));
4567890123456789 | -4567890123456789 4567890123456789 | -4567890123456789
(5 rows) (5 rows)
create table tt15v_log(o tt15v, n tt15v, incr bool);
create rule updlog as on update to tt15v do also
insert into tt15v_log values(old, new, row(old,old) < row(new,new));
\d+ tt15v
View "testviewschm2.tt15v"
Column | Type | Collation | Nullable | Default | Storage | Description
--------+-----------------+-----------+----------+---------+----------+-------------
row | nestedcomposite | | | | extended |
View definition:
SELECT ROW(i.*::int8_tbl)::nestedcomposite AS "row"
FROM int8_tbl i;
Rules:
updlog AS
ON UPDATE TO tt15v DO INSERT INTO tt15v_log (o, n, incr)
VALUES (old.*::tt15v, new.*::tt15v, (ROW(old.*::tt15v, old.*::tt15v) < ROW(new.*::tt15v, new.*::tt15v)))
-- check unique-ification of overlength names -- check unique-ification of overlength names
create view tt18v as create view tt18v as
select * from int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy select * from int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
@ -1756,4 +1772,4 @@ select pg_get_ruledef(oid, true) from pg_rewrite
DROP SCHEMA temp_view_test CASCADE; DROP SCHEMA temp_view_test CASCADE;
NOTICE: drop cascades to 27 other objects NOTICE: drop cascades to 27 other objects
DROP SCHEMA testviewschm2 CASCADE; DROP SCHEMA testviewschm2 CASCADE;
NOTICE: drop cascades to 63 other objects NOTICE: drop cascades to 64 other objects

View File

@ -548,6 +548,11 @@ select * from tt17v;
select pg_get_viewdef('tt17v', true); select pg_get_viewdef('tt17v', true);
select * from int8_tbl i where i.* in (values(i.*::int8_tbl)); select * from int8_tbl i where i.* in (values(i.*::int8_tbl));
create table tt15v_log(o tt15v, n tt15v, incr bool);
create rule updlog as on update to tt15v do also
insert into tt15v_log values(old, new, row(old,old) < row(new,new));
\d+ tt15v
-- check unique-ification of overlength names -- check unique-ification of overlength names
create view tt18v as create view tt18v as