| Line | Hits | Source | Commit |
| 4657 |
- |
remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel, |
- |
| 4658 |
- |
Bitmapset *extra_used_attrs) |
- |
| 4659 |
- |
{ |
- |
| 4660 |
- |
Bitmapset *attrs_used; |
- |
| 4661 |
- |
ListCell *lc; |
- |
| 4662 |
- |
|
- |
| 4663 |
- |
/* |
- |
| 4664 |
- |
* Just point directly to extra_used_attrs. No need to bms_copy as none of |
- |
| 4665 |
- |
* the current callers use the Bitmapset after calling this function. |
- |
| 4666 |
- |
*/ |
- |
| 4667 |
- |
attrs_used = extra_used_attrs; |
- |
| 4668 |
- |
|
- |
| 4669 |
- |
/* |
- |
| 4670 |
- |
* Do nothing if subquery has UNION/INTERSECT/EXCEPT: in principle we |
- |
| 4671 |
- |
* could update all the child SELECTs' tlists, but it seems not worth the |
- |
| 4672 |
- |
* trouble presently. |
- |
| 4673 |
- |
*/ |
- |
| 4674 |
- |
if (subquery->setOperations) |
- |
| 4675 |
- |
return; |
- |
| 4676 |
- |
|
- |
| 4677 |
- |
/* |
- |
| 4678 |
- |
* If subquery has regular DISTINCT (not DISTINCT ON), we're wasting our |
- |
| 4679 |
- |
* time: all its output columns must be used in the distinctClause. |
- |
| 4680 |
- |
*/ |
- |
| 4681 |
- |
if (subquery->distinctClause && !subquery->hasDistinctOn) |
- |
| 4682 |
- |
return; |
- |
| 4683 |
- |
|
- |
| 4684 |
- |
/* |
- |
| 4685 |
- |
* Collect a bitmap of all the output column numbers used by the upper |
- |
| 4686 |
- |
* query. |
- |
| 4687 |
- |
* |
- |
| 4688 |
- |
* Add all the attributes needed for joins or final output. Note: we must |
- |
| 4689 |
- |
* look at rel's targetlist, not the attr_needed data, because attr_needed |
- |
| 4690 |
- |
* isn't computed for inheritance child rels, cf set_append_rel_size(). |
- |
| 4691 |
- |
* (XXX might be worth changing that sometime.) |
- |
| 4692 |
- |
*/ |
- |
| 4693 |
- |
pull_varattnos((Node *) rel->reltarget->exprs, rel->relid, &attrs_used); |
- |
| 4694 |
- |
|
- |
| 4695 |
- |
/* Add all the attributes used by un-pushed-down restriction clauses. */ |
- |
| 4696 |
- |
foreach(lc, rel->baserestrictinfo) |
- |
| 4697 |
- |
{ |
- |
| 4698 |
- |
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); |
- |
| 4699 |
- |
|
- |
| 4700 |
- |
pull_varattnos((Node *) rinfo->clause, rel->relid, &attrs_used); |
- |
| 4701 |
- |
} |
- |
| 4702 |
- |
|
- |
| 4703 |
- |
/* |
- |
| 4704 |
- |
* If there's a whole-row reference to the subquery, we can't remove |
- |
| 4705 |
- |
* anything. |
- |
| 4706 |
- |
*/ |
- |
| 4707 |
- |
if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, attrs_used)) |
- |
| 4708 |
- |
return; |
- |
| 4709 |
- |
|
- |
| 4710 |
- |
/* |
- |
| 4711 |
- |
* Run through the tlist and zap entries we don't need. It's okay to |
- |
| 4712 |
- |
* modify the tlist items in-place because set_subquery_pathlist made a |
- |
| 4713 |
- |
* copy of the subquery. |
- |
| 4714 |
- |
*/ |
- |
| 4715 |
- |
foreach(lc, subquery->targetList) |
- |
| 4716 |
- |
{ |
- |
| 4717 |
- |
TargetEntry *tle = (TargetEntry *) lfirst(lc); |
- |
| 4718 |
- |
Node *texpr = (Node *) tle->expr; |
- |
| 4719 |
- |
|
- |
| 4720 |
- |
/* |
- |
| 4721 |
- |
* If it has a sortgroupref number, it's used in some sort/group |
- |
| 4722 |
- |
* clause so we'd better not remove it. Also, don't remove any |
- |
| 4723 |
- |
* resjunk columns, since their reason for being has nothing to do |
- |
| 4724 |
- |
* with anybody reading the subquery's output. (It's likely that |
- |
| 4725 |
- |
* resjunk columns in a sub-SELECT would always have ressortgroupref |
- |
| 4726 |
- |
* set, but even if they don't, it seems imprudent to remove them.) |
- |
| 4727 |
- |
*/ |
- |
| 4728 |
- |
if (tle->ressortgroupref || tle->resjunk) |
- |
| 4729 |
- |
continue; |
- |
| 4730 |
- |
|
- |
| 4731 |
- |
/* |
- |
| 4732 |
- |
* If it's used by the upper query, we can't remove it. |
- |
| 4733 |
- |
*/ |
- |
| 4734 |
- |
if (bms_is_member(tle->resno - FirstLowInvalidHeapAttributeNumber, |
- |
| 4735 |
- |
attrs_used)) |
- |
| 4736 |
- |
continue; |
- |
| 4737 |
- |
|
- |
| 4738 |
- |
/* |
- |
| 4739 |
- |
* If it contains a set-returning function, we can't remove it since |
- |
| 4740 |
- |
* that could change the number of rows returned by the subquery. |
- |
| 4741 |
- |
*/ |
- |
| 4742 |
- |
if (subquery->hasTargetSRFs && |
- |
| 4743 |
- |
expression_returns_set(texpr)) |
- |
| 4744 |
- |
continue; |
- |
| 4745 |
- |
|
- |
| 4746 |
- |
/* |
- |
| 4747 |
- |
* If it contains volatile functions, we daren't remove it for fear |
- |
| 4748 |
- |
* that the user is expecting their side-effects to happen. |
- |
| 4749 |
- |
*/ |
- |
| 4750 |
- |
if (contain_volatile_functions(texpr)) |
- |
| 4751 |
- |
continue; |
- |
| 4752 |
- |
|
- |
| 4753 |
- |
/* |
7521a30Row pattern recognition patch (planner). |
| 4754 |
- |
* If any RPR (Row Pattern Recognition) window clause references this |
7521a30Row pattern recognition patch (planner). |
| 4755 |
- |
* column in its DEFINE clause, don't remove it. The DEFINE |
7521a30Row pattern recognition patch (planner). |
| 4756 |
- |
* expression needs these columns in the tuplestore slot for pattern |
7521a30Row pattern recognition patch (planner). |
| 4757 |
- |
* matching evaluation, even if the outer query doesn't reference |
7521a30Row pattern recognition patch (planner). |
| 4758 |
- |
* them. |
7521a30Row pattern recognition patch (planner). |
| 4759 |
- |
*/ |
7521a30Row pattern recognition patch (planner). |
| 4760 |
27223 |
if (IsA(texpr, Var)) |
7521a30Row pattern recognition patch (planner). |
| 4761 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4762 |
- |
Var *var = (Var *) texpr; |
7521a30Row pattern recognition patch (planner). |
| 4763 |
- |
bool needed_by_define = false; |
7521a30Row pattern recognition patch (planner). |
| 4764 |
- |
|
7521a30Row pattern recognition patch (planner). |
| 4765 |
12762 |
foreach_node(WindowClause, wc, subquery->windowClause) |
7521a30Row pattern recognition patch (planner). |
| 4766 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4767 |
55 |
if (wc->defineClause != NIL) |
7521a30Row pattern recognition patch (planner). |
| 4768 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4769 |
50 |
List *vars = pull_var_clause((Node *) wc->defineClause, 0); |
7521a30Row pattern recognition patch (planner). |
| 4770 |
- |
|
7521a30Row pattern recognition patch (planner). |
| 4771 |
80 |
foreach_node(Var, dvar, vars) |
7521a30Row pattern recognition patch (planner). |
| 4772 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4773 |
- |
|
7521a30Row pattern recognition patch (planner). |
| 4774 |
- |
/* |
7521a30Row pattern recognition patch (planner). |
| 4775 |
- |
* Match varno as well as varattno: a Var pulled from |
7521a30Row pattern recognition patch (planner). |
| 4776 |
- |
* a DEFINE clause can share an attribute number with |
7521a30Row pattern recognition patch (planner). |
| 4777 |
- |
* an unrelated output column of a different relation, |
7521a30Row pattern recognition patch (planner). |
| 4778 |
- |
* which would otherwise be over-retained. Checking |
7521a30Row pattern recognition patch (planner). |
| 4779 |
- |
* varlevelsup is just paranoia, since outer |
7521a30Row pattern recognition patch (planner). |
| 4780 |
- |
* references in DEFINE are rejected during parse |
7521a30Row pattern recognition patch (planner). |
| 4781 |
- |
* analysis. |
7521a30Row pattern recognition patch (planner). |
| 4782 |
- |
*/ |
7521a30Row pattern recognition patch (planner). |
| 4783 |
60 |
if (dvar->varno == var->varno && |
7521a30Row pattern recognition patch (planner). |
| 4784 |
55 |
dvar->varattno == var->varattno && |
7521a30Row pattern recognition patch (planner). |
| 4785 |
30 |
dvar->varlevelsup == var->varlevelsup) |
7521a30Row pattern recognition patch (planner). |
| 4786 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4787 |
- |
needed_by_define = true; |
7521a30Row pattern recognition patch (planner). |
| 4788 |
- |
break; |
7521a30Row pattern recognition patch (planner). |
| 4789 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4790 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4791 |
50 |
list_free(vars); |
7521a30Row pattern recognition patch (planner). |
| 4792 |
50 |
if (needed_by_define) |
7521a30Row pattern recognition patch (planner). |
| 4793 |
- |
break; |
7521a30Row pattern recognition patch (planner). |
| 4794 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4795 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4796 |
12737 |
if (needed_by_define) |
7521a30Row pattern recognition patch (planner). |
| 4797 |
30 |
continue; |
7521a30Row pattern recognition patch (planner). |
| 4798 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4799 |
- |
|
7521a30Row pattern recognition patch (planner). |
| 4800 |
- |
/* |
7521a30Row pattern recognition patch (planner). |
| 4801 |
- |
* If it's a window function referencing a window clause with RPR, |
7521a30Row pattern recognition patch (planner). |
| 4802 |
- |
* don't remove it. Even when the window function result is unused by |
7521a30Row pattern recognition patch (planner). |
| 4803 |
- |
* the outer query, the RPR pattern matching (frame reduction via |
7521a30Row pattern recognition patch (planner). |
| 4804 |
- |
* DEFINE/PATTERN) must still execute. Replacing this with NULL would |
7521a30Row pattern recognition patch (planner). |
| 4805 |
- |
* leave no active window functions for the WindowClause, causing the |
7521a30Row pattern recognition patch (planner). |
| 4806 |
- |
* planner to omit the WindowAgg node entirely. |
7521a30Row pattern recognition patch (planner). |
| 4807 |
- |
*/ |
7521a30Row pattern recognition patch (planner). |
| 4808 |
27193 |
if (IsA(texpr, WindowFunc)) |
7521a30Row pattern recognition patch (planner). |
| 4809 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4810 |
- |
bool is_rpr = false; |
b848408Tidy up row pattern recognition plumbing |
| 4811 |
- |
WindowFunc *wfunc = (WindowFunc *) texpr; |
7521a30Row pattern recognition patch (planner). |
| 4812 |
- |
|
7521a30Row pattern recognition patch (planner). |
| 4813 |
35 |
foreach_node(WindowClause, wc, subquery->windowClause) |
b848408Tidy up row pattern recognition plumbing |
| 4814 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4815 |
30 |
if (wc->winref == wfunc->winref && wc->defineClause != NIL) |
b848408Tidy up row pattern recognition plumbing |
| 4816 |
- |
{ |
7521a30Row pattern recognition patch (planner). |
| 4817 |
- |
is_rpr = true; |
b848408Tidy up row pattern recognition plumbing |
| 4818 |
- |
break; |
7521a30Row pattern recognition patch (planner). |
| 4819 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4820 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4821 |
- |
|
b848408Tidy up row pattern recognition plumbing |
| 4822 |
30 |
if (is_rpr) |
b848408Tidy up row pattern recognition plumbing |
| 4823 |
25 |
continue; |
7521a30Row pattern recognition patch (planner). |
| 4824 |
- |
} |
7521a30Row pattern recognition patch (planner). |
| 4825 |
- |
|
7521a30Row pattern recognition patch (planner). |
| 4826 |
- |
/* |
- |
| 4827 |
- |
* OK, we don't need it. Replace the expression with a NULL constant. |
- |
| 4828 |
- |
* Preserve the exposed type of the expression, in case something |
- |
| 4829 |
- |
* looks at the rowtype of the subquery's result. |
- |
| 4830 |
- |
*/ |
- |
| 4831 |
- |
tle->expr = (Expr *) makeNullConst(exprType(texpr), |
- |
| 4832 |
- |
exprTypmod(texpr), |
- |
| 4833 |
- |
exprCollation(texpr)); |
- |
| 4834 |
- |
} |
- |
| 4835 |
- |
} |
- |