Skip to content

Commit 0436679

Browse files
committed
Get rid of adjust_appendrel_attr_needed(), which has been broken ever since
we extended the appendrel mechanism to support UNION ALL optimization. The reason nobody noticed was that we are not actually using attr_needed data for appendrel children; hence it seems more reasonable to rip it out than fix it. Back-patch to 8.2 because an Assert failure is possible in corner cases. Per examination of an example from Jim Nasby. In HEAD, also get rid of AppendRelInfo.col_mappings, which is quite inadequate to represent UNION ALL situations; depend entirely on translated_vars instead.
1 parent ccc9073 commit 0436679

File tree

8 files changed

+46
-146
lines changed

8 files changed

+46
-146
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.410 2008/10/31 08:39:20 heikki Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.411 2008/11/11 18:13:32 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1640,7 +1640,6 @@ _copyAppendRelInfo(AppendRelInfo *from)
16401640
COPY_SCALAR_FIELD(child_relid);
16411641
COPY_SCALAR_FIELD(parent_reltype);
16421642
COPY_SCALAR_FIELD(child_reltype);
1643-
COPY_NODE_FIELD(col_mappings);
16441643
COPY_NODE_FIELD(translated_vars);
16451644
COPY_SCALAR_FIELD(parent_reloid);
16461645

src/backend/nodes/equalfuncs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Portions Copyright (c) 1994, Regents of the University of California
2323
*
2424
* IDENTIFICATION
25-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.335 2008/10/31 08:39:20 heikki Exp $
25+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.336 2008/11/11 18:13:32 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -806,7 +806,6 @@ _equalAppendRelInfo(AppendRelInfo *a, AppendRelInfo *b)
806806
COMPARE_SCALAR_FIELD(child_relid);
807807
COMPARE_SCALAR_FIELD(parent_reltype);
808808
COMPARE_SCALAR_FIELD(child_reltype);
809-
COMPARE_NODE_FIELD(col_mappings);
810809
COMPARE_NODE_FIELD(translated_vars);
811810
COMPARE_SCALAR_FIELD(parent_reloid);
812811

src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.343 2008/10/21 20:42:52 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.344 2008/11/11 18:13:32 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1628,7 +1628,6 @@ _outAppendRelInfo(StringInfo str, AppendRelInfo *node)
16281628
WRITE_UINT_FIELD(child_relid);
16291629
WRITE_OID_FIELD(parent_reltype);
16301630
WRITE_OID_FIELD(child_reltype);
1631-
WRITE_NODE_FIELD(col_mappings);
16321631
WRITE_NODE_FIELD(translated_vars);
16331632
WRITE_OID_FIELD(parent_reloid);
16341633
}

src/backend/optimizer/path/allpaths.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.175 2008/10/21 20:42:52 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.176 2008/11/11 18:13:32 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -382,14 +382,12 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
382382
}
383383

384384
/*
385-
* Copy the parent's attr_needed data as well, with appropriate
386-
* adjustment of relids and attribute numbers.
385+
* Note: we could compute appropriate attr_needed data for the
386+
* child's variables, by transforming the parent's attr_needed
387+
* through the translated_vars mapping. However, currently there's
388+
* no need because attr_needed is only examined for base relations
389+
* not otherrels. So we just leave the child's attr_needed empty.
387390
*/
388-
pfree(childrel->attr_needed);
389-
childrel->attr_needed =
390-
adjust_appendrel_attr_needed(rel, appinfo,
391-
childrel->min_attr,
392-
childrel->max_attr);
393391

394392
/*
395393
* Compute the child's access paths, and add the cheapest one to the

src/backend/optimizer/prep/prepjointree.c

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*
1818
* IDENTIFICATION
19-
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.58 2008/10/22 20:17:52 tgl Exp $
19+
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.59 2008/11/11 18:13:32 tgl Exp $
2020
*
2121
*-------------------------------------------------------------------------
2222
*/
@@ -54,9 +54,8 @@ static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
5454
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
5555
int parentRTindex, Query *setOpQuery,
5656
int childRToffset);
57-
static void make_setop_translation_lists(Query *query,
58-
Index newvarno,
59-
List **col_mappings, List **translated_vars);
57+
static void make_setop_translation_list(Query *query, Index newvarno,
58+
List **translated_vars);
6059
static bool is_simple_subquery(Query *subquery);
6160
static bool is_simple_union_all(Query *subquery);
6261
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
@@ -839,9 +838,8 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
839838
appinfo->child_relid = childRTindex;
840839
appinfo->parent_reltype = InvalidOid;
841840
appinfo->child_reltype = InvalidOid;
842-
make_setop_translation_lists(setOpQuery, childRTindex,
843-
&appinfo->col_mappings,
844-
&appinfo->translated_vars);
841+
make_setop_translation_list(setOpQuery, childRTindex,
842+
&appinfo->translated_vars);
845843
appinfo->parent_reloid = InvalidOid;
846844
root->append_rel_list = lappend(root->append_rel_list, appinfo);
847845

@@ -874,17 +872,16 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
874872
}
875873

876874
/*
877-
* make_setop_translation_lists
878-
* Build the lists of translations from parent Vars to child Vars for
879-
* a UNION ALL member. We need both a column number mapping list
880-
* and a list of Vars representing the child columns.
875+
* make_setop_translation_list
876+
* Build the list of translations from parent Vars to child Vars for
877+
* a UNION ALL member. (At this point it's just a simple list of
878+
* referencing Vars, but if we succeed in pulling up the member
879+
* subquery, the Vars will get replaced by pulled-up expressions.)
881880
*/
882881
static void
883-
make_setop_translation_lists(Query *query,
884-
Index newvarno,
885-
List **col_mappings, List **translated_vars)
882+
make_setop_translation_list(Query *query, Index newvarno,
883+
List **translated_vars)
886884
{
887-
List *numbers = NIL;
888885
List *vars = NIL;
889886
ListCell *l;
890887

@@ -895,15 +892,13 @@ make_setop_translation_lists(Query *query,
895892
if (tle->resjunk)
896893
continue;
897894

898-
numbers = lappend_int(numbers, tle->resno);
899895
vars = lappend(vars, makeVar(newvarno,
900896
tle->resno,
901897
exprType((Node *) tle->expr),
902898
exprTypmod((Node *) tle->expr),
903899
0));
904900
}
905901

906-
*col_mappings = numbers;
907902
*translated_vars = vars;
908903
}
909904

src/backend/optimizer/prep/prepunion.c

Lines changed: 21 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
*
2424
* IDENTIFICATION
25-
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.160 2008/10/22 20:17:52 tgl Exp $
25+
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.161 2008/11/11 18:13:32 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -91,11 +91,10 @@ static List *generate_append_tlist(List *colTypes, bool flag,
9191
static List *generate_setop_grouplist(SetOperationStmt *op, List *targetlist);
9292
static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte,
9393
Index rti);
94-
static void make_inh_translation_lists(Relation oldrelation,
95-
Relation newrelation,
96-
Index newvarno,
97-
List **col_mappings,
98-
List **translated_vars);
94+
static void make_inh_translation_list(Relation oldrelation,
95+
Relation newrelation,
96+
Index newvarno,
97+
List **translated_vars);
9998
static Node *adjust_appendrel_attrs_mutator(Node *node,
10099
AppendRelInfo *context);
101100
static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid);
@@ -1279,9 +1278,8 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
12791278
appinfo->child_relid = childRTindex;
12801279
appinfo->parent_reltype = oldrelation->rd_rel->reltype;
12811280
appinfo->child_reltype = newrelation->rd_rel->reltype;
1282-
make_inh_translation_lists(oldrelation, newrelation, childRTindex,
1283-
&appinfo->col_mappings,
1284-
&appinfo->translated_vars);
1281+
make_inh_translation_list(oldrelation, newrelation, childRTindex,
1282+
&appinfo->translated_vars);
12851283
appinfo->parent_reloid = parentOID;
12861284
appinfos = lappend(appinfos, appinfo);
12871285

@@ -1316,19 +1314,17 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
13161314
}
13171315

13181316
/*
1319-
* make_inh_translation_lists
1320-
* Build the lists of translations from parent Vars to child Vars for
1321-
* an inheritance child. We need both a column number mapping list
1322-
* and a list of Vars representing the child columns.
1317+
* make_inh_translation_list
1318+
* Build the list of translations from parent Vars to child Vars for
1319+
* an inheritance child.
13231320
*
13241321
* For paranoia's sake, we match type as well as attribute name.
13251322
*/
13261323
static void
1327-
make_inh_translation_lists(Relation oldrelation, Relation newrelation,
1328-
Index newvarno,
1329-
List **col_mappings, List **translated_vars)
1324+
make_inh_translation_list(Relation oldrelation, Relation newrelation,
1325+
Index newvarno,
1326+
List **translated_vars)
13301327
{
1331-
List *numbers = NIL;
13321328
List *vars = NIL;
13331329
TupleDesc old_tupdesc = RelationGetDescr(oldrelation);
13341330
TupleDesc new_tupdesc = RelationGetDescr(newrelation);
@@ -1347,8 +1343,7 @@ make_inh_translation_lists(Relation oldrelation, Relation newrelation,
13471343
att = old_tupdesc->attrs[old_attno];
13481344
if (att->attisdropped)
13491345
{
1350-
/* Just put 0/NULL into this list entry */
1351-
numbers = lappend_int(numbers, 0);
1346+
/* Just put NULL into this list entry */
13521347
vars = lappend(vars, NULL);
13531348
continue;
13541349
}
@@ -1362,7 +1357,6 @@ make_inh_translation_lists(Relation oldrelation, Relation newrelation,
13621357
*/
13631358
if (oldrelation == newrelation)
13641359
{
1365-
numbers = lappend_int(numbers, old_attno + 1);
13661360
vars = lappend(vars, makeVar(newvarno,
13671361
(AttrNumber) (old_attno + 1),
13681362
atttypid,
@@ -1405,15 +1399,13 @@ make_inh_translation_lists(Relation oldrelation, Relation newrelation,
14051399
elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
14061400
attname, RelationGetRelationName(newrelation));
14071401

1408-
numbers = lappend_int(numbers, new_attno + 1);
14091402
vars = lappend(vars, makeVar(newvarno,
14101403
(AttrNumber) (new_attno + 1),
14111404
atttypid,
14121405
atttypmod,
14131406
0));
14141407
}
14151408

1416-
*col_mappings = numbers;
14171409
*translated_vars = vars;
14181410
}
14191411

@@ -1682,70 +1674,6 @@ adjust_relid_set(Relids relids, Index oldrelid, Index newrelid)
16821674
return relids;
16831675
}
16841676

1685-
/*
1686-
* adjust_appendrel_attr_needed
1687-
* Adjust an attr_needed[] array to reference a member rel instead of
1688-
* the original appendrel
1689-
*
1690-
* oldrel: source of data (we use the attr_needed, min_attr, max_attr fields)
1691-
* appinfo: supplies parent_relid, child_relid, col_mappings
1692-
* new_min_attr, new_max_attr: desired bounds of new attr_needed array
1693-
*
1694-
* The relid sets are adjusted by substituting child_relid for parent_relid.
1695-
* (NOTE: oldrel is not necessarily the parent_relid relation!) We are also
1696-
* careful to map attribute numbers within the array properly. User
1697-
* attributes have to be mapped through col_mappings, but system attributes
1698-
* and whole-row references always have the same attno.
1699-
*
1700-
* Returns a palloc'd array with the specified bounds
1701-
*/
1702-
Relids *
1703-
adjust_appendrel_attr_needed(RelOptInfo *oldrel, AppendRelInfo *appinfo,
1704-
AttrNumber new_min_attr, AttrNumber new_max_attr)
1705-
{
1706-
Relids *new_attr_needed;
1707-
Index parent_relid = appinfo->parent_relid;
1708-
Index child_relid = appinfo->child_relid;
1709-
int parent_attr;
1710-
ListCell *lm;
1711-
1712-
/* Create empty result array */
1713-
new_attr_needed = (Relids *)
1714-
palloc0((new_max_attr - new_min_attr + 1) * sizeof(Relids));
1715-
/* Process user attributes, with appropriate attno mapping */
1716-
parent_attr = 1;
1717-
foreach(lm, appinfo->col_mappings)
1718-
{
1719-
int child_attr = lfirst_int(lm);
1720-
1721-
if (child_attr > 0)
1722-
{
1723-
Relids attrneeded;
1724-
1725-
Assert(parent_attr <= oldrel->max_attr);
1726-
Assert(child_attr <= new_max_attr);
1727-
attrneeded = oldrel->attr_needed[parent_attr - oldrel->min_attr];
1728-
attrneeded = adjust_relid_set(attrneeded,
1729-
parent_relid, child_relid);
1730-
new_attr_needed[child_attr - new_min_attr] = attrneeded;
1731-
}
1732-
parent_attr++;
1733-
}
1734-
/* Process system attributes, including whole-row references */
1735-
Assert(new_min_attr <= oldrel->min_attr);
1736-
for (parent_attr = oldrel->min_attr; parent_attr <= 0; parent_attr++)
1737-
{
1738-
Relids attrneeded;
1739-
1740-
attrneeded = oldrel->attr_needed[parent_attr - oldrel->min_attr];
1741-
attrneeded = adjust_relid_set(attrneeded,
1742-
parent_relid, child_relid);
1743-
new_attr_needed[parent_attr - new_min_attr] = attrneeded;
1744-
}
1745-
1746-
return new_attr_needed;
1747-
}
1748-
17491677
/*
17501678
* Adjust the targetlist entries of an inherited UPDATE operation
17511679
*
@@ -1778,24 +1706,24 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
17781706
foreach(tl, tlist)
17791707
{
17801708
TargetEntry *tle = (TargetEntry *) lfirst(tl);
1781-
int newattno;
1709+
Var *childvar;
17821710

17831711
if (tle->resjunk)
17841712
continue; /* ignore junk items */
17851713

1786-
/* Look up the translation of this column */
1714+
/* Look up the translation of this column: it must be a Var */
17871715
if (tle->resno <= 0 ||
1788-
tle->resno > list_length(context->col_mappings))
1716+
tle->resno > list_length(context->translated_vars))
17891717
elog(ERROR, "attribute %d of relation \"%s\" does not exist",
17901718
tle->resno, get_rel_name(context->parent_reloid));
1791-
newattno = list_nth_int(context->col_mappings, tle->resno - 1);
1792-
if (newattno <= 0)
1719+
childvar = (Var *) list_nth(context->translated_vars, tle->resno - 1);
1720+
if (childvar == NULL || !IsA(childvar, Var))
17931721
elog(ERROR, "attribute %d of relation \"%s\" does not exist",
17941722
tle->resno, get_rel_name(context->parent_reloid));
17951723

1796-
if (tle->resno != newattno)
1724+
if (tle->resno != childvar->varattno)
17971725
{
1798-
tle->resno = newattno;
1726+
tle->resno = childvar->varattno;
17991727
changed_it = true;
18001728
}
18011729
}

src/include/nodes/relation.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.163 2008/10/22 20:17:52 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.164 2008/11/11 18:13:32 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1239,27 +1239,14 @@ typedef struct AppendRelInfo
12391239
Oid parent_reltype; /* OID of parent's composite type */
12401240
Oid child_reltype; /* OID of child's composite type */
12411241

1242-
/*
1243-
* The N'th element of this list is the integer column number of the child
1244-
* column corresponding to the N'th column of the parent. A list element
1245-
* is zero if it corresponds to a dropped column of the parent (this is
1246-
* only possible for inheritance cases, not UNION ALL).
1247-
*/
1248-
List *col_mappings; /* list of child attribute numbers */
1249-
12501242
/*
12511243
* The N'th element of this list is a Var or expression representing the
12521244
* child column corresponding to the N'th column of the parent. This is
12531245
* used to translate Vars referencing the parent rel into references to
12541246
* the child. A list element is NULL if it corresponds to a dropped
12551247
* column of the parent (this is only possible for inheritance cases, not
1256-
* UNION ALL).
1257-
*
1258-
* This might seem redundant with the col_mappings data, but it is handy
1259-
* because flattening of sub-SELECTs that are members of a UNION ALL will
1260-
* cause changes in the expressions that need to be substituted for a
1261-
* parent Var. Adjusting this data structure lets us track what really
1262-
* needs to be substituted.
1248+
* UNION ALL). The list elements are always simple Vars for inheritance
1249+
* cases, but can be arbitrary expressions in UNION ALL cases.
12631250
*
12641251
* Notice we only store entries for user columns (attno > 0). Whole-row
12651252
* Vars are special-cased, and system columns (attno < 0) need no special

0 commit comments

Comments
 (0)