(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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers