summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/prep/prepunion.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/prep/prepunion.c')
-rw-r--r--src/backend/optimizer/prep/prepunion.c129
1 files changed, 35 insertions, 94 deletions
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index a33213ef59d..cc44825be00 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -4,13 +4,17 @@
* Routines to plan set-operation queries. The filename is a leftover
* from a time when only UNIONs were implemented.
*
+ * There are two code paths in the planner for set-operation queries.
+ * If a subquery consists entirely of simple UNION ALL operations, it
+ * is converted into an "append relation". Otherwise, it is handled
+ * by the general code in this module (plan_set_operations and its
+ * subroutines). There is some support code here for the append-relation
+ * case, but most of the heavy lifting for that is done elsewhere,
+ * notably in prepjointree.c and allpaths.c.
+ *
* There is also some code here to support planning of queries that use
- * inheritance (SELECT FROM foo*). Although inheritance is radically
- * different from set operations as far as the parser representation of
- * a query is concerned, we try to handle it identically to the UNION ALL
- * case during planning: both are converted to "append rels". (Note that
- * UNION ALL is special-cased: other kinds of set operations go through
- * a completely different code path.)
+ * inheritance (SELECT FROM foo*). Inheritance trees are converted into
+ * append relations, and thenceforth share code with the UNION ALL case.
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
@@ -18,7 +22,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.129 2006/01/31 21:39:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.130 2006/02/03 21:08:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -64,12 +68,13 @@ static List *generate_setop_tlist(List *colTypes, int flag,
static List *generate_append_tlist(List *colTypes, bool flag,
List *input_plans,
List *refnames_tlist);
-static bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK);
static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte,
Index rti);
-static void make_translation_lists(Relation oldrelation, Relation newrelation,
- Index newvarno,
- List **col_mappings, List **translated_vars);
+static void make_inh_translation_lists(Relation oldrelation,
+ Relation newrelation,
+ Index newvarno,
+ List **col_mappings,
+ List **translated_vars);
static Node *adjust_appendrel_attrs_mutator(Node *node,
AppendRelInfo *context);
static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid);
@@ -659,41 +664,6 @@ generate_append_tlist(List *colTypes, bool flag,
return tlist;
}
-/*
- * Does tlist have same datatypes as requested colTypes?
- *
- * Resjunk columns are ignored if junkOK is true; otherwise presence of
- * a resjunk column will always cause a 'false' result.
- */
-static bool
-tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
-{
- ListCell *l;
- ListCell *curColType = list_head(colTypes);
-
- foreach(l, tlist)
- {
- TargetEntry *tle = (TargetEntry *) lfirst(l);
-
- if (tle->resjunk)
- {
- if (!junkOK)
- return false;
- }
- else
- {
- if (curColType == NULL)
- return false;
- if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
- return false;
- curColType = lnext(curColType);
- }
- }
- if (curColType != NULL)
- return false;
- return true;
-}
-
/*
* find_all_inheritors -
@@ -896,9 +866,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
appinfo->child_relid = childRTindex;
appinfo->parent_reltype = oldrelation->rd_rel->reltype;
appinfo->child_reltype = newrelation->rd_rel->reltype;
- make_translation_lists(oldrelation, newrelation, childRTindex,
- &appinfo->col_mappings,
- &appinfo->translated_vars);
+ make_inh_translation_lists(oldrelation, newrelation, childRTindex,
+ &appinfo->col_mappings,
+ &appinfo->translated_vars);
appinfo->parent_reloid = parentOID;
appinfos = lappend(appinfos, appinfo);
@@ -933,7 +903,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
}
/*
- * make_translation_lists
+ * make_inh_translation_lists
* Build the lists of translations from parent Vars to child Vars for
* an inheritance child. We need both a column number mapping list
* and a list of Vars representing the child columns.
@@ -941,9 +911,9 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
* For paranoia's sake, we match type as well as attribute name.
*/
static void
-make_translation_lists(Relation oldrelation, Relation newrelation,
- Index newvarno,
- List **col_mappings, List **translated_vars)
+make_inh_translation_lists(Relation oldrelation, Relation newrelation,
+ Index newvarno,
+ List **col_mappings, List **translated_vars)
{
List *numbers = NIL;
List *vars = NIL;
@@ -1123,8 +1093,18 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
}
else
{
- /* XXX copy some code from ResolveNew */
- Assert(false);/* not done yet */
+ /*
+ * Build a RowExpr containing the translated variables.
+ */
+ RowExpr *rowexpr;
+ List *fields;
+
+ fields = (List *) copyObject(context->translated_vars);
+ rowexpr = makeNode(RowExpr);
+ rowexpr->args = fields;
+ rowexpr->row_typeid = var->vartype;
+ rowexpr->row_format = COERCE_IMPLICIT_CAST;
+ return (Node *) rowexpr;
}
}
/* system attributes don't need any other translation */
@@ -1338,45 +1318,6 @@ adjust_appendrel_attr_needed(RelOptInfo *oldrel, AppendRelInfo *appinfo,
}
/*
- * adjust_other_rel_attr_needed
- * Adjust an attr_needed[] array to reference a member rel instead of
- * the original appendrel
- *
- * This is exactly like adjust_appendrel_attr_needed except that we disregard
- * appinfo->col_mappings and instead assume that the mapping of user
- * attributes is one-to-one. This is appropriate for generating an attr_needed
- * array that describes another relation to be joined with a member rel.
- */
-Relids *
-adjust_other_rel_attr_needed(RelOptInfo *oldrel, AppendRelInfo *appinfo,
- AttrNumber new_min_attr, AttrNumber new_max_attr)
-{
- Relids *new_attr_needed;
- Index parent_relid = appinfo->parent_relid;
- Index child_relid = appinfo->child_relid;
- int parent_attr;
-
- /* Create empty result array */
- Assert(new_min_attr <= oldrel->min_attr);
- Assert(new_max_attr >= oldrel->max_attr);
- new_attr_needed = (Relids *)
- palloc0((new_max_attr - new_min_attr + 1) * sizeof(Relids));
- /* Process user attributes and system attributes */
- for (parent_attr = oldrel->min_attr; parent_attr <= oldrel->max_attr;
- parent_attr++)
- {
- Relids attrneeded;
-
- attrneeded = oldrel->attr_needed[parent_attr - oldrel->min_attr];
- attrneeded = adjust_relid_set(attrneeded,
- parent_relid, child_relid);
- new_attr_needed[parent_attr - new_min_attr] = attrneeded;
- }
-
- return new_attr_needed;
-}
-
-/*
* Adjust the targetlist entries of an inherited UPDATE operation
*
* The expressions have already been fixed, but we have to make sure that