Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitda9a28f

Browse files
committed
Fix ruleutils issues with dropped cols in functions-returning-composite.
Due to lack of concern for the case in the dependency code, it'spossible to drop a column of a composite type even though storedqueries have references to the dropped column via functions-in-FROMthat return the composite type. There are "soft" references,namely FROM-clause aliases for such columns, and "hard" references,that is actual Vars referring to them. The right fix for hardreferences is to add dependencies preventing the drop; somethingwe've known for many years and not done (and this commit still doesn'taddress it). A "soft" reference shouldn't prevent a drop though.We've been around on this before (cf.9b35ddc,2c4debb), butnobody had noticed that the current behavior can result in dump/reloadfailures, because ruleutils.c can print more column aliases than theunderlying composite type now has. So we need to rejigger thecolumn-alias-handling code to treat such columns as dropped and notprint aliases for them.Rather than writing new code for this, I used expandRTE() which alreadyknows how to figure out which function result columns are dropped.I'd initially thought maybe we could use expandRTE() in all cases, butthat fails for EXPLAIN's purposes, because the planner strips a lot ofRTE infrastructure that expandRTE() needs. So this patch just uses itfor unplanned function RTEs and otherwise does things the old way.If there is a hard reference (Var), then removing the column aliascauses us to fail to print the Var, since there's no longer a nameto print. Failing seems less desirable than printing a made-upname, so I made it print "?dropped?column?" instead.Per report from Timo Stolz. Back-patch to all supported branches.Discussion:https://postgr.es/m/5c91267e-3b6d-5795-189c-d15a55d61dbb@nullachtvierzehn.de
1 parentbe2e842 commitda9a28f

File tree

4 files changed

+68
-22
lines changed

4 files changed

+68
-22
lines changed

‎src/backend/parser/parse_relation.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3164,6 +3164,9 @@ expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
31643164
*
31653165
* "*" is returned if the given attnum is InvalidAttrNumber --- this case
31663166
* occurs when a Var represents a whole tuple of a relation.
3167+
*
3168+
* It is caller's responsibility to not call this on a dropped attribute.
3169+
* (You will get some answer for such cases, but it might not be sensible.)
31673170
*/
31683171
char*
31693172
get_rte_attribute_name(RangeTblEntry*rte,AttrNumberattnum)

‎src/backend/utils/adt/ruleutils.c

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include"parser/parse_func.h"
5454
#include"parser/parse_node.h"
5555
#include"parser/parse_oper.h"
56+
#include"parser/parse_relation.h"
5657
#include"parser/parser.h"
5758
#include"parser/parsetree.h"
5859
#include"rewrite/rewriteHandler.h"
@@ -4222,9 +4223,9 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
42224223
intj;
42234224

42244225
/*
4225-
*ExtracttheRTE's "real" column names. This is comparable to
4226-
*get_rte_attribute_name, except that it's important to disregard dropped
4227-
*columns. We put NULL into the arrayforadroppedcolumn.
4226+
*Construct an array ofthecurrent "real" column names of the RTE.
4227+
*real_colnames[] will be indexed by physical column number, with NULL
4228+
*entriesfor droppedcolumns.
42284229
*/
42294230
if (rte->rtekind==RTE_RELATION)
42304231
{
@@ -4251,19 +4252,43 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
42514252
}
42524253
else
42534254
{
4254-
/* Otherwise use the column names from eref */
4255+
/* Otherwise get the column names from eref or expandRTE() */
4256+
List*colnames;
42554257
ListCell*lc;
42564258

4257-
ncolumns=list_length(rte->eref->colnames);
4259+
/*
4260+
* Functions returning composites have the annoying property that some
4261+
* of the composite type's columns might have been dropped since the
4262+
* query was parsed. If possible, use expandRTE() to handle that
4263+
* case, since it has the tedious logic needed to find out about
4264+
* dropped columns. However, if we're explaining a plan, then we
4265+
* don't have rte->functions because the planner thinks that won't be
4266+
* needed later, and that breaks expandRTE(). So in that case we have
4267+
* to rely on rte->eref, which may lead us to report a dropped
4268+
* column's old name; that seems close enough for EXPLAIN's purposes.
4269+
*
4270+
* For non-RELATION, non-FUNCTION RTEs, we can just look at rte->eref,
4271+
* which should be sufficiently up-to-date: no other RTE types can
4272+
* have columns get dropped from under them after parsing.
4273+
*/
4274+
if (rte->rtekind==RTE_FUNCTION&&rte->functions!=NIL)
4275+
{
4276+
/* Since we're not creating Vars, rtindex etc. don't matter */
4277+
expandRTE(rte,1,0,-1, true/* include dropped */ ,
4278+
&colnames,NULL);
4279+
}
4280+
else
4281+
colnames=rte->eref->colnames;
4282+
4283+
ncolumns=list_length(colnames);
42584284
real_colnames= (char**)palloc(ncolumns*sizeof(char*));
42594285

42604286
i=0;
4261-
foreach(lc,rte->eref->colnames)
4287+
foreach(lc,colnames)
42624288
{
42634289
/*
4264-
* If the column name shown in eref is an empty string, then it's
4265-
* a column that was dropped at the time of parsing the query, so
4266-
* treat it as dropped.
4290+
* If the column name we find here is an empty string, then it's a
4291+
* dropped column, so change to NULL.
42674292
*/
42684293
char*cname=strVal(lfirst(lc));
42694294

@@ -7192,9 +7217,16 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
71927217
elog(ERROR,"invalid attnum %d for relation \"%s\"",
71937218
attnum,rte->eref->aliasname);
71947219
attname=colinfo->colnames[attnum-1];
7195-
if (attname==NULL)/* dropped column? */
7196-
elog(ERROR,"invalid attnum %d for relation \"%s\"",
7197-
attnum,rte->eref->aliasname);
7220+
7221+
/*
7222+
* If we find a Var referencing a dropped column, it seems better to
7223+
* print something (anything) than to fail. In general this should
7224+
* not happen, but there are specific cases involving functions
7225+
* returning named composite types where we don't sufficiently enforce
7226+
* that you can't drop a column that's referenced in some view.
7227+
*/
7228+
if (attname==NULL)
7229+
attname="?dropped?column?";
71987230
}
71997231
else
72007232
{

‎src/test/regress/expected/create_view.out

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,17 +1546,26 @@ select * from tt14v;
15461546
begin;
15471547
-- this perhaps should be rejected, but it isn't:
15481548
alter table tt14t drop column f3;
1549-
-- f3 is still in the view ...
1549+
--columnf3 is still in the view, sort of ...
15501550
select pg_get_viewdef('tt14v', true);
1551-
pg_get_viewdef
1552-
--------------------------------
1553-
SELECT t.f1, +
1554-
t.f3,+
1555-
t.f4 +
1556-
FROM tt14f() t(f1,f3,f4);
1551+
pg_get_viewdef
1552+
---------------------------------
1553+
SELECT t.f1,+
1554+
t."?dropped?column?" AS f3,+
1555+
t.f4+
1556+
FROM tt14f() t(f1, f4);
15571557
(1 row)
15581558

1559-
-- but will fail at execution
1559+
-- ... and you can even EXPLAIN it ...
1560+
explain (verbose, costs off) select * from tt14v;
1561+
QUERY PLAN
1562+
----------------------------------------
1563+
Function Scan on testviewschm2.tt14f t
1564+
Output: t.f1, t.f3, t.f4
1565+
Function Call: tt14f()
1566+
(3 rows)
1567+
1568+
-- but it will fail at execution
15601569
select f1, f4 from tt14v;
15611570
f1 | f4
15621571
-----+----

‎src/test/regress/sql/create_view.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,9 +526,11 @@ begin;
526526
-- this perhaps should be rejected, but it isn't:
527527
altertable tt14t drop column f3;
528528

529-
-- f3 is still in the view ...
529+
--columnf3 is still in the view, sort of ...
530530
select pg_get_viewdef('tt14v', true);
531-
-- but will fail at execution
531+
-- ... and you can even EXPLAIN it ...
532+
explain (verbose, costs off)select*from tt14v;
533+
-- but it will fail at execution
532534
select f1, f4from tt14v;
533535
select*from tt14v;
534536

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp