(2014/07/01 11:10), Etsuro Fujita wrote: > (2014/06/30 22:48), Tom Lane wrote: >> Etsuro Fujita <fujita.ets...@lab.ntt.co.jp> writes: >>> Done. I think this is because create_foreignscan_plan() makes reference >>> to attr_needed, which isn't computed for inheritance children. >> >> 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. > > +1 for calculating attr_needed for child rels. (I was wondering too.) > > I'll create a separate patch for it.
Attached is a WIP patch for that. The following functions have been changed to refer to attr_needed: * check_index_only() * remove_unused_subquery_outputs() * check_selective_binary_conversion() I'll add this to the upcoming commitfest. If anyone has any time to glance at it before then, that would be a great help. 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. */ ! /* Collect 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 *oldrel, + RelOptInfo *newrel, + RangeTblEntry *newrte, + AppendRelInfo *appinfo); + static void adjust_appendrel_attr_needed_setop(RelOptInfo *oldrel, + RelOptInfo *newrel, + RangeTblEntry *newrte, + 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,2002 ---- } /* + * 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 *oldrel, + RelOptInfo *newrel, + RangeTblEntry *newrte, + AppendRelInfo *appinfo) + { + if (OidIsValid(appinfo->parent_reloid)) + adjust_appendrel_attr_needed_inh(oldrel, newrel, newrte, appinfo); + else + adjust_appendrel_attr_needed_setop(oldrel, newrel, newrte, appinfo); + } + + static void + adjust_appendrel_attr_needed_inh(RelOptInfo *oldrel, + RelOptInfo *newrel, + RangeTblEntry *newrte, + AppendRelInfo *appinfo) + { + int i; + ListCell *lc; + + Assert(newrte->rtekind == RTE_RELATION); + + /* + * System attributes and whole-row Vars have the same numbers in all tables. + */ + for (i = newrel->min_attr; i <= InvalidAttrNumber; i++) + newrel->attr_needed[i - newrel->min_attr] = + adjust_relid_set(oldrel->attr_needed[i - newrel->min_attr], + 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 oldattoff; + + i++; + if (var == NULL) /* ignore dropped columns */ + continue; + Assert(IsA(var, Var)); + + if (!bms_is_empty(oldrel->attr_needed[i - newrel->min_attr])) + newrel->attr_needed[var->varattno - oldrel->min_attr] = + adjust_relid_set(oldrel->attr_needed[i - newrel->min_attr], + appinfo->parent_relid, appinfo->child_relid); + } + } + + static void + adjust_appendrel_attr_needed_setop(RelOptInfo *oldrel, + RelOptInfo *newrel, + RangeTblEntry *newrte, + AppendRelInfo *appinfo) + { + int i; + ListCell *lc; + bool whole_row; + + if (newrte->rtekind != RTE_RELATION) + { + for (i = oldrel->min_attr; i <= oldrel->max_attr; i++) + newrel->attr_needed[i] = adjust_relid_set(oldrel->attr_needed[i], + appinfo->parent_relid, + appinfo->child_relid); + return; + } + + /* + * Compute the child's attr_needed by transforming the parent's attr_needed + * through the translated_vars mapping of the specified AppendRelInfo. + */ + + /* Check if parent has whole-row reference */ + whole_row = !bms_is_empty(oldrel->attr_needed[InvalidAttrNumber]); + + i = InvalidAttrNumber; + foreach(lc, appinfo->translated_vars) + { + Node *node = (Node *) lfirst(lc); + bool result; + + i++; + if (whole_row || !bms_is_empty(oldrel->attr_needed[i])) + { + Bitmapset *attrs_used = NULL; + Bitmapset *tmpset = NULL; + int j; + + pull_varattnos(node, newrel->relid, &attrs_used); + tmpset = bms_copy(attrs_used); + while ((j = bms_first_member(tmpset)) >= 0) + { + if (whole_row) + newrel->attr_needed[j - 1] = + bms_add_members(newrel->attr_needed[j - 1], + oldrel->attr_needed[InvalidAttrNumber]); + if (!bms_is_empty(oldrel->attr_needed[i])) + newrel->attr_needed[j - 1] = + bms_add_members(newrel->attr_needed[j - 1], + oldrel->attr_needed[i]); + } + bms_free(tmpset); + bms_free(attrs_used); + } + } + + /* Adjust attr_needed's relid sets */ + for (i = newrel->min_attr; i <= newrel->max_attr; i++) + newrel->attr_needed[i - newrel->min_attr] = + adjust_relid_set(newrel->attr_needed[i - newrel->min_attr], + 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 *oldrel, + RelOptInfo *newrel, + RangeTblEntry *newrte, + 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