diff options
Diffstat (limited to 'src/backend/optimizer/prep/prepunion.c')
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 98 |
1 files changed, 61 insertions, 37 deletions
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index cff5a865316..e361fb8ce96 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -49,6 +49,12 @@ #include "utils/selfuncs.h" +typedef struct +{ + PlannerInfo *root; + AppendRelInfo *appinfo; +} adjust_appendrel_attrs_context; + static Plan *recurse_set_operations(Node *setOp, PlannerInfo *root, double tuple_fraction, List *colTypes, List *colCollations, @@ -99,7 +105,7 @@ static void make_inh_translation_list(Relation oldrelation, static Bitmapset *translate_col_privs(const Bitmapset *parent_privs, List *translated_vars); static Node *adjust_appendrel_attrs_mutator(Node *node, - AppendRelInfo *context); + adjust_appendrel_attrs_context *context); static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid); static List *adjust_inherited_tlist(List *tlist, AppendRelInfo *context); @@ -1569,9 +1575,13 @@ translate_col_privs(const Bitmapset *parent_privs, * maybe we should try to fold the two routines together. */ Node * -adjust_appendrel_attrs(Node *node, AppendRelInfo *appinfo) +adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo) { Node *result; + adjust_appendrel_attrs_context context; + + context.root = root; + context.appinfo = appinfo; /* * Must be prepared to start with a Query or a bare expression tree. @@ -1582,7 +1592,7 @@ adjust_appendrel_attrs(Node *node, AppendRelInfo *appinfo) newnode = query_tree_mutator((Query *) node, adjust_appendrel_attrs_mutator, - (void *) appinfo, + (void *) &context, QTW_IGNORE_RC_SUBQUERIES); if (newnode->resultRelation == appinfo->parent_relid) { @@ -1596,14 +1606,17 @@ adjust_appendrel_attrs(Node *node, AppendRelInfo *appinfo) result = (Node *) newnode; } else - result = adjust_appendrel_attrs_mutator(node, appinfo); + result = adjust_appendrel_attrs_mutator(node, &context); return result; } static Node * -adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) +adjust_appendrel_attrs_mutator(Node *node, + adjust_appendrel_attrs_context *context) { + AppendRelInfo *appinfo = context->appinfo; + if (node == NULL) return NULL; if (IsA(node, Var)) @@ -1611,22 +1624,22 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) Var *var = (Var *) copyObject(node); if (var->varlevelsup == 0 && - var->varno == context->parent_relid) + var->varno == appinfo->parent_relid) { - var->varno = context->child_relid; - var->varnoold = context->child_relid; + var->varno = appinfo->child_relid; + var->varnoold = appinfo->child_relid; if (var->varattno > 0) { Node *newnode; - if (var->varattno > list_length(context->translated_vars)) + if (var->varattno > list_length(appinfo->translated_vars)) elog(ERROR, "attribute %d of relation \"%s\" does not exist", - var->varattno, get_rel_name(context->parent_reloid)); - newnode = copyObject(list_nth(context->translated_vars, + var->varattno, get_rel_name(appinfo->parent_reloid)); + newnode = copyObject(list_nth(appinfo->translated_vars, var->varattno - 1)); if (newnode == NULL) elog(ERROR, "attribute %d of relation \"%s\" does not exist", - var->varattno, get_rel_name(context->parent_reloid)); + var->varattno, get_rel_name(appinfo->parent_reloid)); return newnode; } else if (var->varattno == 0) @@ -1637,19 +1650,19 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) * step to convert the tuple layout to the parent's rowtype. * Otherwise we have to generate a RowExpr. */ - if (OidIsValid(context->child_reltype)) + if (OidIsValid(appinfo->child_reltype)) { - Assert(var->vartype == context->parent_reltype); - if (context->parent_reltype != context->child_reltype) + Assert(var->vartype == appinfo->parent_reltype); + if (appinfo->parent_reltype != appinfo->child_reltype) { ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr); r->arg = (Expr *) var; - r->resulttype = context->parent_reltype; + r->resulttype = appinfo->parent_reltype; r->convertformat = COERCE_IMPLICIT_CAST; r->location = -1; /* Make sure the Var node has the right type ID, too */ - var->vartype = context->child_reltype; + var->vartype = appinfo->child_reltype; return (Node *) r; } } @@ -1657,16 +1670,27 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) { /* * Build a RowExpr containing the translated variables. + * + * In practice var->vartype will always be RECORDOID here, + * so we need to come up with some suitable column names. + * We use the parent RTE's column names. + * + * Note: we can't get here for inheritance cases, so there + * is no need to worry that translated_vars might contain + * some dummy NULLs. */ RowExpr *rowexpr; List *fields; + RangeTblEntry *rte; - fields = (List *) copyObject(context->translated_vars); + rte = rt_fetch(appinfo->parent_relid, + context->root->parse->rtable); + fields = (List *) copyObject(appinfo->translated_vars); rowexpr = makeNode(RowExpr); rowexpr->args = fields; rowexpr->row_typeid = var->vartype; rowexpr->row_format = COERCE_IMPLICIT_CAST; - rowexpr->colnames = NIL; + rowexpr->colnames = copyObject(rte->eref->colnames); rowexpr->location = -1; return (Node *) rowexpr; @@ -1680,16 +1704,16 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) { CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node); - if (cexpr->cvarno == context->parent_relid) - cexpr->cvarno = context->child_relid; + if (cexpr->cvarno == appinfo->parent_relid) + cexpr->cvarno = appinfo->child_relid; return (Node *) cexpr; } if (IsA(node, RangeTblRef)) { RangeTblRef *rtr = (RangeTblRef *) copyObject(node); - if (rtr->rtindex == context->parent_relid) - rtr->rtindex = context->child_relid; + if (rtr->rtindex == appinfo->parent_relid) + rtr->rtindex = appinfo->child_relid; return (Node *) rtr; } if (IsA(node, JoinExpr)) @@ -1701,8 +1725,8 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) adjust_appendrel_attrs_mutator, (void *) context); /* now fix JoinExpr's rtindex (probably never happens) */ - if (j->rtindex == context->parent_relid) - j->rtindex = context->child_relid; + if (j->rtindex == appinfo->parent_relid) + j->rtindex = appinfo->child_relid; return (Node *) j; } if (IsA(node, PlaceHolderVar)) @@ -1716,8 +1740,8 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) /* now fix PlaceHolderVar's relid sets */ if (phv->phlevelsup == 0) phv->phrels = adjust_relid_set(phv->phrels, - context->parent_relid, - context->child_relid); + appinfo->parent_relid, + appinfo->child_relid); return (Node *) phv; } /* Shouldn't need to handle planner auxiliary nodes here */ @@ -1749,20 +1773,20 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) /* adjust relid sets too */ newinfo->clause_relids = adjust_relid_set(oldinfo->clause_relids, - context->parent_relid, - context->child_relid); + appinfo->parent_relid, + appinfo->child_relid); newinfo->required_relids = adjust_relid_set(oldinfo->required_relids, - context->parent_relid, - context->child_relid); + appinfo->parent_relid, + appinfo->child_relid); newinfo->nullable_relids = adjust_relid_set(oldinfo->nullable_relids, - context->parent_relid, - context->child_relid); + appinfo->parent_relid, + appinfo->child_relid); newinfo->left_relids = adjust_relid_set(oldinfo->left_relids, - context->parent_relid, - context->child_relid); + appinfo->parent_relid, + appinfo->child_relid); newinfo->right_relids = adjust_relid_set(oldinfo->right_relids, - context->parent_relid, - context->child_relid); + appinfo->parent_relid, + appinfo->child_relid); /* * Reset cached derivative fields, since these might need to have |