Commit 4aee39dd authored by Tom Lane's avatar Tom Lane

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

Commit 7745bc35 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
parent 3c1ffd02
...@@ -438,6 +438,8 @@ static void get_rule_expr(Node *node, deparse_context *context, ...@@ -438,6 +438,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);
...@@ -6580,7 +6582,7 @@ get_insert_query_def(Query *query, deparse_context *context) ...@@ -6580,7 +6582,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
...@@ -8944,23 +8946,15 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -8944,23 +8946,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
...@@ -8973,15 +8967,7 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -8973,15 +8967,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;
...@@ -9526,6 +9512,32 @@ get_rule_expr_toplevel(Node *node, deparse_context *context, ...@@ -9526,6 +9512,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
* *
......
...@@ -1681,6 +1681,22 @@ select * from int8_tbl i where i.* in (values(i.*::int8_tbl)); ...@@ -1681,6 +1681,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
...@@ -1994,7 +2010,7 @@ drop cascades to view aliased_view_2 ...@@ -1994,7 +2010,7 @@ drop cascades to view aliased_view_2
drop cascades to view aliased_view_3 drop cascades to view aliased_view_3
drop cascades to view aliased_view_4 drop cascades to view aliased_view_4
DROP SCHEMA testviewschm2 CASCADE; DROP SCHEMA testviewschm2 CASCADE;
NOTICE: drop cascades to 73 other objects NOTICE: drop cascades to 74 other objects
DETAIL: drop cascades to table t1 DETAIL: drop cascades to table t1
drop cascades to view temporal1 drop cascades to view temporal1
drop cascades to view temporal2 drop cascades to view temporal2
...@@ -2058,6 +2074,7 @@ drop cascades to type nestedcomposite ...@@ -2058,6 +2074,7 @@ drop cascades to type nestedcomposite
drop cascades to view tt15v drop cascades to view tt15v
drop cascades to view tt16v drop cascades to view tt16v
drop cascades to view tt17v drop cascades to view tt17v
drop cascades to table tt15v_log
drop cascades to view tt18v drop cascades to view tt18v
drop cascades to view tt19v drop cascades to view tt19v
drop cascades to view tt20v drop cascades to view tt20v
......
...@@ -565,6 +565,11 @@ select * from tt17v; ...@@ -565,6 +565,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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment