diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 9dc0b3c917..1268ac1dd0 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -5374,19 +5374,20 @@ get_select_query_def(Query *query, deparse_context *context, } /* - * Detect whether query looks like SELECT ... FROM VALUES(); - * if so, return the VALUES RTE. Otherwise return NULL. + * Detect whether query looks like SELECT ... FROM VALUES(), + * with no need to rename the output columns of the VALUES RTE. + * If so, return the VALUES RTE. Otherwise return NULL. */ static RangeTblEntry * -get_simple_values_rte(Query *query) +get_simple_values_rte(Query *query, TupleDesc resultDesc) { RangeTblEntry *result = NULL; ListCell *lc; /* - * We want to return true even if the Query also contains OLD or NEW rule - * RTEs. So the idea is to scan the rtable and see if there is only one - * inFromCl RTE that is a VALUES RTE. + * We want to detect a match even if the Query also contains OLD or NEW + * rule RTEs. So the idea is to scan the rtable and see if there is only + * one inFromCl RTE that is a VALUES RTE. */ foreach(lc, query->rtable) { @@ -5409,23 +5410,36 @@ get_simple_values_rte(Query *query) * parser/analyze.c will never generate a "bare" VALUES RTE --- they only * appear inside auto-generated sub-queries with very restricted * structure. However, DefineView might have modified the tlist by - * injecting new column aliases; so compare tlist resnames against the - * RTE's names to detect that. + * injecting new column aliases, or we might have some other column + * aliases forced by a resultDesc. We can only simplify if the RTE's + * column names match the names that get_target_list() would select. */ if (result) { ListCell *lcn; + int colno; if (list_length(query->targetList) != list_length(result->eref->colnames)) return NULL; /* this probably cannot happen */ + colno = 0; forboth(lc, query->targetList, lcn, result->eref->colnames) { TargetEntry *tle = (TargetEntry *) lfirst(lc); char *cname = strVal(lfirst(lcn)); + char *colname; if (tle->resjunk) return NULL; /* this probably cannot happen */ - if (tle->resname == NULL || strcmp(tle->resname, cname) != 0) + + /* compute name that get_target_list would use for column */ + colno++; + if (resultDesc && colno <= resultDesc->natts) + colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname); + else + colname = tle->resname; + + /* does it match the VALUES RTE? */ + if (colname == NULL || strcmp(colname, cname) != 0) return NULL; /* column name has been changed */ } } @@ -5453,7 +5467,7 @@ get_basic_select_query(Query *query, deparse_context *context, * VALUES part. This reverses what transformValuesClause() did at parse * time. */ - values_rte = get_simple_values_rte(query); + values_rte = get_simple_values_rte(query, resultDesc); if (values_rte) { get_values_def(values_rte->values_lists, context); diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 210e9cd146..6b0b8cbe3e 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -3023,6 +3023,18 @@ create view rule_v1 as values(1,2); View definition: VALUES (1,2); +alter table rule_v1 rename column column2 to q2; +\d+ rule_v1 + View "public.rule_v1" + Column | Type | Collation | Nullable | Default | Storage | Description +---------+---------+-----------+----------+---------+---------+------------- + column1 | integer | | | | plain | + q2 | integer | | | | plain | +View definition: + SELECT "*VALUES*".column1, + "*VALUES*".column2 AS q2 + FROM (VALUES (1,2)) "*VALUES*"; + drop view rule_v1; create view rule_v1(x) as values(1,2); \d+ rule_v1 diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql index a042e59546..b7d7f434b6 100644 --- a/src/test/regress/sql/rules.sql +++ b/src/test/regress/sql/rules.sql @@ -1047,6 +1047,8 @@ DROP TABLE rule_t1; -- create view rule_v1 as values(1,2); \d+ rule_v1 +alter table rule_v1 rename column column2 to q2; +\d+ rule_v1 drop view rule_v1; create view rule_v1(x) as values(1,2); \d+ rule_v1