summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-01-13 17:49:26 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2022-01-13 17:49:26 -0500
commit3433a1fc76762675170c7d2455ea29e575918898 (patch)
tree9f4e4d3dfd8e501e466f8cf6cbb0621aee9b239d /src
parent9a8b1b6777178c76c48043c3d7bfbe911d2ee577 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/ruleutils.c56
-rw-r--r--src/test/regress/expected/create_view.out18
-rw-r--r--src/test/regress/sql/create_view.sql5
3 files changed, 56 insertions, 23 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index c7c9bd67659..4897f271a4b 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -419,6 +419,8 @@ static void get_rule_expr(Node *node, deparse_context *context,
bool showimplicit);
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
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,
bool showimplicit);
static bool looks_like_function(Node *node);
@@ -6085,7 +6087,7 @@ get_insert_query_def(Query *query, deparse_context *context)
/* Add the single-VALUES expression list */
appendContextKeyword(context, "VALUES (",
-PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
- get_rule_expr((Node *) strippedexprs, context, false);
+ get_rule_list_toplevel(strippedexprs, context, false);
appendStringInfoChar(buf, ')');
}
else
@@ -8278,23 +8280,15 @@ get_rule_expr(Node *node, deparse_context *context,
case T_RowCompareExpr:
{
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
- ListCell *arg;
- char *sep;
/*
* 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(");
- sep = "";
- foreach(arg, rcexpr->largs)
- {
- Node *e = (Node *) lfirst(arg);
-
- appendStringInfoString(buf, sep);
- get_rule_expr(e, context, true);
- sep = ", ";
- }
+ get_rule_list_toplevel(rcexpr->largs, context, true);
/*
* We assume that the name of the first-column operator will
@@ -8307,15 +8301,7 @@ get_rule_expr(Node *node, deparse_context *context,
generate_operator_name(linitial_oid(rcexpr->opnos),
exprType(linitial(rcexpr->largs)),
exprType(linitial(rcexpr->rargs))));
- sep = "";
- foreach(arg, rcexpr->rargs)
- {
- Node *e = (Node *) lfirst(arg);
-
- appendStringInfoString(buf, sep);
- get_rule_expr(e, context, true);
- sep = ", ";
- }
+ get_rule_list_toplevel(rcexpr->rargs, context, true);
appendStringInfoString(buf, "))");
}
break;
@@ -8846,6 +8832,32 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
}
/*
+ * 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
*
* Same as get_rule_expr(), except that we guarantee that the output will
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index aaf9af07f7f..dbfac5f6072 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -1612,6 +1612,22 @@ select * from int8_tbl i where i.* in (values(i.*::int8_tbl));
4567890123456789 | -4567890123456789
(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
create view tt18v as
select * from int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
@@ -1756,4 +1772,4 @@ select pg_get_ruledef(oid, true) from pg_rewrite
DROP SCHEMA temp_view_test CASCADE;
NOTICE: drop cascades to 27 other objects
DROP SCHEMA testviewschm2 CASCADE;
-NOTICE: drop cascades to 63 other objects
+NOTICE: drop cascades to 64 other objects
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index 40c24fe5c2c..657fef3c7f8 100644
--- a/src/test/regress/sql/create_view.sql
+++ b/src/test/regress/sql/create_view.sql
@@ -548,6 +548,11 @@ select * from tt17v;
select pg_get_viewdef('tt17v', true);
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
create view tt18v as