(2014/08/06 20:43), Etsuro Fujita wrote: >> (2014/06/30 22:48), Tom Lane wrote: >>> I wonder whether it isn't time to change that. It was coded like that >>> originally only because calculating the values would've been a waste of >>> cycles at the time. But this is at least the third place where it'd be >>> useful to have attr_needed for child rels.
> Attached is a WIP patch for that. I've revised the patch. Changes: * Make the code more readable * Revise the comments * Cleanup Please find attached an updated version of the patch. Thanks, Best regards, Etsuro Fujita
*** a/contrib/file_fdw/file_fdw.c --- b/contrib/file_fdw/file_fdw.c *************** *** 799,806 **** check_selective_binary_conversion(RelOptInfo *baserel, } /* Collect all the attributes needed for joins or final output. */ ! pull_varattnos((Node *) baserel->reltargetlist, baserel->relid, ! &attrs_used); /* Add all the attributes used by restriction clauses. */ foreach(lc, baserel->baserestrictinfo) --- 799,811 ---- } /* Collect all the attributes needed for joins or final output. */ ! for (i = baserel->min_attr; i <= baserel->max_attr; i++) ! { ! if (!bms_is_empty(baserel->attr_needed[i - baserel->min_attr])) ! attrs_used = ! bms_add_member(attrs_used, ! i - FirstLowInvalidHeapAttributeNumber); ! } /* Add all the attributes used by restriction clauses. */ foreach(lc, baserel->baserestrictinfo) *** a/src/backend/optimizer/path/allpaths.c --- b/src/backend/optimizer/path/allpaths.c *************** *** 577,588 **** set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, childrel->has_eclass_joins = rel->has_eclass_joins; /* ! * Note: we could compute appropriate attr_needed data for the child's ! * variables, by transforming the parent's attr_needed through the ! * translated_vars mapping. However, currently there's no need ! * because attr_needed is only examined for base relations not ! * otherrels. So we just leave the child's attr_needed empty. */ /* * Compute the child's size. --- 577,585 ---- childrel->has_eclass_joins = rel->has_eclass_joins; /* ! * Compute the child's attr_needed. */ + adjust_appendrel_attr_needed(rel, childrel, childRTE, appinfo); /* * Compute the child's size. *************** *** 2173,2178 **** remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel) --- 2170,2176 ---- { Bitmapset *attrs_used = NULL; ListCell *lc; + int i; /* * Do nothing if subquery has UNION/INTERSECT/EXCEPT: in principle we *************** *** 2193,2204 **** remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel) * Collect a bitmap of all the output column numbers used by the upper * query. * ! * Add all the attributes needed for joins or final output. Note: we must ! * look at reltargetlist, not the attr_needed data, because attr_needed ! * isn't computed for inheritance child rels, cf set_append_rel_size(). ! * (XXX might be worth changing that sometime.) */ ! pull_varattnos((Node *) rel->reltargetlist, rel->relid, &attrs_used); /* Add all the attributes used by un-pushed-down restriction clauses. */ foreach(lc, rel->baserestrictinfo) --- 2191,2205 ---- * Collect a bitmap of all the output column numbers used by the upper * query. * ! * Add all the attributes needed for joins or final output. */ ! for (i = rel->min_attr; i <= rel->max_attr; i++) ! { ! if (!bms_is_empty(rel->attr_needed[i - rel->min_attr])) ! attrs_used = ! bms_add_member(attrs_used, ! i - FirstLowInvalidHeapAttributeNumber); ! } /* Add all the attributes used by un-pushed-down restriction clauses. */ foreach(lc, rel->baserestrictinfo) *** a/src/backend/optimizer/path/indxpath.c --- b/src/backend/optimizer/path/indxpath.c *************** *** 1768,1779 **** check_index_only(RelOptInfo *rel, IndexOptInfo *index) * way out. */ ! /* ! * Add all the attributes needed for joins or final output. Note: we must ! * look at reltargetlist, not the attr_needed data, because attr_needed ! * isn't computed for inheritance child rels. ! */ ! pull_varattnos((Node *) rel->reltargetlist, rel->relid, &attrs_used); /* Add all the attributes used by restriction clauses. */ foreach(lc, rel->baserestrictinfo) --- 1768,1781 ---- * way out. */ ! /* Add all the attributes needed for joins or final output. */ ! for (i = rel->min_attr; i <= rel->max_attr; i++) ! { ! if (!bms_is_empty(rel->attr_needed[i - rel->min_attr])) ! attrs_used = ! bms_add_member(attrs_used, ! i - FirstLowInvalidHeapAttributeNumber); ! } /* Add all the attributes used by restriction clauses. */ foreach(lc, rel->baserestrictinfo) *** a/src/backend/optimizer/prep/prepunion.c --- b/src/backend/optimizer/prep/prepunion.c *************** *** 109,114 **** static Bitmapset *translate_col_privs(const Bitmapset *parent_privs, --- 109,122 ---- List *translated_vars); static Node *adjust_appendrel_attrs_mutator(Node *node, adjust_appendrel_attrs_context *context); + static void adjust_appendrel_attr_needed_inh(RelOptInfo *parent_rel, + RelOptInfo *child_rel, + RangeTblEntry *child_rte, + AppendRelInfo *appinfo); + static void adjust_appendrel_attr_needed_setop(RelOptInfo *parent_rel, + RelOptInfo *child_rel, + RangeTblEntry *child_rte, + AppendRelInfo *appinfo); static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid); static List *adjust_inherited_tlist(List *tlist, AppendRelInfo *context); *************** *** 1867,1872 **** adjust_appendrel_attrs_mutator(Node *node, --- 1875,2031 ---- } /* + * adjust_appendrel_attr_needed + * Compute the child's attr_needed by transforming the parent's attr_needed + * through the translated_vars mapping of the specified AppendRelInfo. + */ + void + adjust_appendrel_attr_needed(RelOptInfo *parent_rel, + RelOptInfo *child_rel, + RangeTblEntry *child_rte, + AppendRelInfo *appinfo) + { + if (OidIsValid(appinfo->parent_reloid)) + adjust_appendrel_attr_needed_inh(parent_rel, child_rel, + child_rte, appinfo); + else + adjust_appendrel_attr_needed_setop(parent_rel, child_rel, + child_rte, appinfo); + } + + /* + * adjust_appendrel_attr_needed for the inheritance case + */ + static void + adjust_appendrel_attr_needed_inh(RelOptInfo *parent_rel, + RelOptInfo *child_rel, + RangeTblEntry *child_rte, + AppendRelInfo *appinfo) + { + int i; + ListCell *lc; + + Assert(child_rte->rtekind == RTE_RELATION); + Assert(appinfo->parent_relid == parent_rel->relid); + Assert(appinfo->child_relid == child_rel->relid); + + /* + * System attributes and whole-row Vars have the same numbers in all tables. + */ + for (i = FirstLowInvalidHeapAttributeNumber + 1; i <= InvalidAttrNumber; i++) + { + int cndx = i - FirstLowInvalidHeapAttributeNumber - 1; + + child_rel->attr_needed[cndx] = + adjust_relid_set(parent_rel->attr_needed[cndx], + appinfo->parent_relid, appinfo->child_relid); + } + + /* + * Compute user attributes' attr_needed through the translated_vars mapping. + */ + i = InvalidAttrNumber; + foreach(lc, appinfo->translated_vars) + { + Var *var = (Var *) lfirst(lc); + int pndx; + int cndx; + + i++; + if (var == NULL) /* ignore dropped columns */ + continue; + Assert(IsA(var, Var)); + + pndx = i - FirstLowInvalidHeapAttributeNumber - 1; + cndx = var->varattno - FirstLowInvalidHeapAttributeNumber - 1; + child_rel->attr_needed[cndx] = + adjust_relid_set(parent_rel->attr_needed[pndx], + appinfo->parent_relid, appinfo->child_relid); + } + } + + /* + * adjust_appendrel_attr_needed for the UNION ALL case + */ + static void + adjust_appendrel_attr_needed_setop(RelOptInfo *parent_rel, + RelOptInfo *child_rel, + RangeTblEntry *child_rte, + AppendRelInfo *appinfo) + { + int i; + ListCell *lc; + int pndx; + bool whole_row; + + Assert(appinfo->parent_relid == parent_rel->relid); + Assert(appinfo->child_relid == child_rel->relid); + + if (child_rte->rtekind != RTE_RELATION) + { + for (i = child_rel->min_attr; i <= child_rel->max_attr; i++) + child_rel->attr_needed[i] = + adjust_relid_set(parent_rel->attr_needed[i], + appinfo->parent_relid, appinfo->child_relid); + return; + } + + /* + * Compute the child's attr_needed through the translated_vars mapping. + * + * Note: pull_up_subqueries might have changed the mapping so that their + * expansions contain arbitrary expressions. So we must cope with such. + */ + + /* Check if parent has whole-row reference */ + whole_row = !bms_is_empty(parent_rel->attr_needed[InvalidAttrNumber]); + + pndx = InvalidAttrNumber; + foreach(lc, appinfo->translated_vars) + { + Node *node = (Node *) lfirst(lc); + bool result; + + pndx++; + result = !bms_is_empty(parent_rel->attr_needed[pndx]); + if (result || whole_row) + { + Bitmapset *attrs_used = NULL; + Bitmapset *tmpset = NULL; + int j; + + pull_varattnos(node, child_rel->relid, &attrs_used); + tmpset = bms_copy(attrs_used); + while ((j = bms_first_member(tmpset)) >= 0) + { + int cndx = j - 1; + + if (result) + child_rel->attr_needed[cndx] = + bms_add_members(child_rel->attr_needed[cndx], + parent_rel->attr_needed[pndx]); + if (whole_row) + child_rel->attr_needed[cndx] = + bms_add_members(child_rel->attr_needed[cndx], + parent_rel->attr_needed[InvalidAttrNumber]); + } + bms_free(tmpset); + bms_free(attrs_used); + } + } + + /* Fix attr_needed's relid sets */ + for (i = FirstLowInvalidHeapAttributeNumber + 1; i <= child_rel->max_attr; i++) + { + int cndx = i - FirstLowInvalidHeapAttributeNumber - 1; + + child_rel->attr_needed[cndx] = + adjust_relid_set(child_rel->attr_needed[cndx], + appinfo->parent_relid, appinfo->child_relid); + } + } + + /* * Substitute newrelid for oldrelid in a Relid set */ static Relids *** a/src/include/optimizer/prep.h --- b/src/include/optimizer/prep.h *************** *** 58,61 **** extern void expand_inherited_tables(PlannerInfo *root); --- 58,66 ---- extern Node *adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo); + extern void adjust_appendrel_attr_needed(RelOptInfo *parent_rel, + RelOptInfo *child_rel, + RangeTblEntry *child_rte, + AppendRelInfo *appinfo); + #endif /* PREP_H */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers