break;
}
}
+
+ /*
+ * We insist that all non-dummy rels have a nonzero rowcount estimate.
+ */
+ Assert(rel->rows > 0 || IS_DUMMY_REL(rel));
}
/*
/* Let FDW adjust the size estimates, if it can */
rel->fdwroutine->GetForeignRelSize(root, rel, rte->relid);
+
+ /* ... but do not let it set the rows estimate to zero */
+ rel->rows = clamp_row_est(rel->rows);
}
/*
Index rti, RangeTblEntry *rte)
{
int parentRTindex = rti;
+ bool has_live_children;
double parent_rows;
double parent_size;
double *parent_attrsizes;
* Note: if you consider changing this logic, beware that child rels could
* have zero rows and/or width, if they were excluded by constraints.
*/
+ has_live_children = false;
parent_rows = 0;
parent_size = 0;
nattrs = rel->max_attr - rel->min_attr + 1;
if (IS_DUMMY_REL(childrel))
continue;
+ /* We have at least one live child. */
+ has_live_children = true;
+
/*
* Accumulate size information from each live child.
*/
- if (childrel->rows > 0)
+ Assert(childrel->rows > 0);
+
+ parent_rows += childrel->rows;
+ parent_size += childrel->width * childrel->rows;
+
+ /*
+ * Accumulate per-column estimates too. We need not do anything for
+ * PlaceHolderVars in the parent list. If child expression isn't a
+ * Var, or we didn't record a width estimate for it, we have to fall
+ * back on a datatype-based estimate.
+ *
+ * By construction, child's reltargetlist is 1-to-1 with parent's.
+ */
+ forboth(parentvars, rel->reltargetlist,
+ childvars, childrel->reltargetlist)
{
- parent_rows += childrel->rows;
- parent_size += childrel->width * childrel->rows;
+ Var *parentvar = (Var *) lfirst(parentvars);
+ Node *childvar = (Node *) lfirst(childvars);
- /*
- * Accumulate per-column estimates too. We need not do anything
- * for PlaceHolderVars in the parent list. If child expression
- * isn't a Var, or we didn't record a width estimate for it, we
- * have to fall back on a datatype-based estimate.
- *
- * By construction, child's reltargetlist is 1-to-1 with parent's.
- */
- forboth(parentvars, rel->reltargetlist,
- childvars, childrel->reltargetlist)
+ if (IsA(parentvar, Var))
{
- Var *parentvar = (Var *) lfirst(parentvars);
- Node *childvar = (Node *) lfirst(childvars);
+ int pndx = parentvar->varattno - rel->min_attr;
+ int32 child_width = 0;
- if (IsA(parentvar, Var))
+ if (IsA(childvar, Var) &&
+ ((Var *) childvar)->varno == childrel->relid)
{
- int pndx = parentvar->varattno - rel->min_attr;
- int32 child_width = 0;
+ int cndx = ((Var *) childvar)->varattno - childrel->min_attr;
- if (IsA(childvar, Var) &&
- ((Var *) childvar)->varno == childrel->relid)
- {
- int cndx = ((Var *) childvar)->varattno - childrel->min_attr;
-
- child_width = childrel->attr_widths[cndx];
- }
- if (child_width <= 0)
- child_width = get_typavgwidth(exprType(childvar),
- exprTypmod(childvar));
- Assert(child_width > 0);
- parent_attrsizes[pndx] += child_width * childrel->rows;
+ child_width = childrel->attr_widths[cndx];
}
+ if (child_width <= 0)
+ child_width = get_typavgwidth(exprType(childvar),
+ exprTypmod(childvar));
+ Assert(child_width > 0);
+ parent_attrsizes[pndx] += child_width * childrel->rows;
}
}
}
- /*
- * Save the finished size estimates.
- */
- rel->rows = parent_rows;
- if (parent_rows > 0)
+ if (has_live_children)
{
+ /*
+ * Save the finished size estimates.
+ */
int i;
+ Assert(parent_rows > 0);
+ rel->rows = parent_rows;
rel->width = rint(parent_size / parent_rows);
for (i = 0; i < nattrs; i++)
rel->attr_widths[i] = rint(parent_attrsizes[i] / parent_rows);
+
+ /*
+ * Set "raw tuples" count equal to "rows" for the appendrel; needed
+ * because some places assume rel->tuples is valid for any baserel.
+ */
+ rel->tuples = parent_rows;
}
else
- rel->width = 0; /* attr_widths should be zero already */
-
- /*
- * Set "raw tuples" count equal to "rows" for the appendrel; needed
- * because some places assume rel->tuples is valid for any baserel.
- */
- rel->tuples = parent_rows;
+ {
+ /*
+ * All children were excluded by constraints, so mark the whole
+ * appendrel dummy. We must do this in this phase so that the rel's
+ * dummy-ness is visible when we generate paths for other rels.
+ */
+ set_dummy_rel_pathlist(rel);
+ }
pfree(parent_attrsizes);
}