|
30 | 30 | #include "optimizer/pathnode.h"
|
31 | 31 | #include "optimizer/paths.h"
|
32 | 32 | #include "optimizer/predtest.h"
|
| 33 | +#include "optimizer/prep.h" |
33 | 34 | #include "optimizer/restrictinfo.h"
|
34 | 35 | #include "optimizer/var.h"
|
35 | 36 | #include "utils/builtins.h"
|
@@ -216,7 +217,7 @@ static Const *string_to_const(const char *str, Oid datatype);
|
216 | 217 | *
|
217 | 218 | * 'rel' is the relation for which we want to generate index paths
|
218 | 219 | *
|
219 |
| - * Note: check_partial_indexes() must have been run previously for this rel. |
| 220 | + * Note: check_index_predicates() must have been run previously for this rel. |
220 | 221 | *
|
221 | 222 | * Note: in cases involving LATERAL references in the relation's tlist, it's
|
222 | 223 | * possible that rel->lateral_relids is nonempty. Currently, we include
|
@@ -1800,25 +1801,27 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
|
1800 | 1801 | /*
|
1801 | 1802 | * Check that all needed attributes of the relation are available from the
|
1802 | 1803 | * index.
|
1803 |
| - * |
1804 |
| - * XXX this is overly conservative for partial indexes, since we will |
1805 |
| - * consider attributes involved in the index predicate as required even |
1806 |
| - * though the predicate won't need to be checked at runtime. (The same is |
1807 |
| - * true for attributes used only in index quals, if we are certain that |
1808 |
| - * the index is not lossy.) However, it would be quite expensive to |
1809 |
| - * determine that accurately at this point, so for now we take the easy |
1810 |
| - * way out. |
1811 | 1804 | */
|
1812 | 1805 |
|
1813 | 1806 | /*
|
1814 |
| - * Add all the attributes needed for joins or final output. Note: we must |
1815 |
| - * look at rel's targetlist, not the attr_needed data, because attr_needed |
1816 |
| - * isn't computed for inheritance child rels. |
| 1807 | + * First, identify all the attributes needed for joins or final output. |
| 1808 | + * Note: we must look at rel's targetlist, not the attr_needed data, |
| 1809 | + * because attr_needed isn't computed for inheritance child rels. |
1817 | 1810 | */
|
1818 | 1811 | pull_varattnos((Node *) rel->reltarget->exprs, rel->relid, &attrs_used);
|
1819 | 1812 |
|
1820 |
| - /* Add all the attributes used by restriction clauses. */ |
1821 |
| - foreach(lc, rel->baserestrictinfo) |
| 1813 | + /* |
| 1814 | + * Add all the attributes used by restriction clauses; but consider only |
| 1815 | + * those clauses not implied by the index predicate, since ones that are |
| 1816 | + * so implied don't need to be checked explicitly in the plan. |
| 1817 | + * |
| 1818 | + * Note: attributes used only in index quals would not be needed at |
| 1819 | + * runtime either, if we are certain that the index is not lossy. However |
| 1820 | + * it'd be complicated to account for that accurately, and it doesn't |
| 1821 | + * matter in most cases, since we'd conclude that such attributes are |
| 1822 | + * available from the index anyway. |
| 1823 | + */ |
| 1824 | + foreach(lc, index->indrestrictinfo) |
1822 | 1825 | {
|
1823 | 1826 | RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
|
1824 | 1827 |
|
@@ -2023,7 +2026,8 @@ static void
|
2023 | 2026 | match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index,
|
2024 | 2027 | IndexClauseSet *clauseset)
|
2025 | 2028 | {
|
2026 |
| - match_clauses_to_index(index, rel->baserestrictinfo, clauseset); |
| 2029 | + /* We can ignore clauses that are implied by the index predicate */ |
| 2030 | + match_clauses_to_index(index, index->indrestrictinfo, clauseset); |
2027 | 2031 | }
|
2028 | 2032 |
|
2029 | 2033 | /*
|
@@ -2664,39 +2668,48 @@ match_clause_to_ordering_op(IndexOptInfo *index,
|
2664 | 2668 | ****************************************************************************/
|
2665 | 2669 |
|
2666 | 2670 | /*
|
2667 |
| - * check_partial_indexes |
2668 |
| - * Check each partial index of the relation, and mark it predOK if |
2669 |
| - * the index's predicate is satisfied for this query. |
| 2671 | + * check_index_predicates |
| 2672 | + * Set the predicate-derived IndexOptInfo fields for each index |
| 2673 | + * of the specified relation. |
| 2674 | + * |
| 2675 | + * predOK is set true if the index is partial and its predicate is satisfied |
| 2676 | + * for this query, ie the query's WHERE clauses imply the predicate. |
2670 | 2677 | *
|
2671 |
| - * Note: it is possible for this to get re-run after adding more restrictions |
2672 |
| - * to the rel; so we might be able to prove more indexes OK. We assume that |
2673 |
| - * adding more restrictions can't make an index not OK. |
| 2678 | + * indrestrictinfo is set to the relation's baserestrictinfo list less any |
| 2679 | + * conditions that are implied by the index's predicate. (Obviously, for a |
| 2680 | + * non-partial index, this is the same as baserestrictinfo.) Such conditions |
| 2681 | + * can be dropped from the plan when using the index, in certain cases. |
| 2682 | + * |
| 2683 | + * At one time it was possible for this to get re-run after adding more |
| 2684 | + * restrictions to the rel, thus possibly letting us prove more indexes OK. |
| 2685 | + * That doesn't happen any more (at least not in the core code's usage), |
| 2686 | + * but this code still supports it in case extensions want to mess with the |
| 2687 | + * baserestrictinfo list. We assume that adding more restrictions can't make |
| 2688 | + * an index not predOK. We must recompute indrestrictinfo each time, though, |
| 2689 | + * to make sure any newly-added restrictions get into it if needed. |
2674 | 2690 | */
|
2675 | 2691 | void
|
2676 |
| -check_partial_indexes(PlannerInfo *root, RelOptInfo *rel) |
| 2692 | +check_index_predicates(PlannerInfo *root, RelOptInfo *rel) |
2677 | 2693 | {
|
2678 | 2694 | List *clauselist;
|
2679 | 2695 | bool have_partial;
|
| 2696 | + bool is_target_rel; |
2680 | 2697 | Relids otherrels;
|
2681 | 2698 | ListCell *lc;
|
2682 | 2699 |
|
2683 | 2700 | /*
|
2684 |
| - * Frequently, there will be no partial indexes, so first check to make |
2685 |
| - * sure there's something useful to do here. |
| 2701 | + * Initialize the indrestrictinfo lists to be identical to |
| 2702 | + * baserestrictinfo, and check whether there are any partial indexes. If |
| 2703 | + * not, this is all we need to do. |
2686 | 2704 | */
|
2687 | 2705 | have_partial = false;
|
2688 | 2706 | foreach(lc, rel->indexlist)
|
2689 | 2707 | {
|
2690 | 2708 | IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
|
2691 | 2709 |
|
2692 |
| - if (index->indpred == NIL) |
2693 |
| - continue; /* ignore non-partial indexes */ |
2694 |
| - |
2695 |
| - if (index->predOK) |
2696 |
| - continue; /* don't repeat work if already proven OK */ |
2697 |
| - |
2698 |
| - have_partial = true; |
2699 |
| - break; |
| 2710 | + index->indrestrictinfo = rel->baserestrictinfo; |
| 2711 | + if (index->indpred) |
| 2712 | + have_partial = true; |
2700 | 2713 | }
|
2701 | 2714 | if (!have_partial)
|
2702 | 2715 | return;
|
@@ -2743,18 +2756,54 @@ check_partial_indexes(PlannerInfo *root, RelOptInfo *rel)
|
2743 | 2756 | otherrels,
|
2744 | 2757 | rel));
|
2745 | 2758 |
|
2746 |
| - /* Now try to prove each index predicate true */ |
| 2759 | + /* |
| 2760 | + * Normally we remove quals that are implied by a partial index's |
| 2761 | + * predicate from indrestrictinfo, indicating that they need not be |
| 2762 | + * checked explicitly by an indexscan plan using this index. However, if |
| 2763 | + * the rel is a target relation of UPDATE/DELETE/SELECT FOR UPDATE, we |
| 2764 | + * cannot remove such quals from the plan, because they need to be in the |
| 2765 | + * plan so that they will be properly rechecked by EvalPlanQual testing. |
| 2766 | + * Some day we might want to remove such quals from the main plan anyway |
| 2767 | + * and pass them through to EvalPlanQual via a side channel; but for now, |
| 2768 | + * we just don't remove implied quals at all for target relations. |
| 2769 | + */ |
| 2770 | + is_target_rel = (rel->relid == root->parse->resultRelation || |
| 2771 | + get_plan_rowmark(root->rowMarks, rel->relid) != NULL); |
| 2772 | + |
| 2773 | + /* |
| 2774 | + * Now try to prove each index predicate true, and compute the |
| 2775 | + * indrestrictinfo lists for partial indexes. Note that we compute the |
| 2776 | + * indrestrictinfo list even for non-predOK indexes; this might seem |
| 2777 | + * wasteful, but we may be able to use such indexes in OR clauses, cf |
| 2778 | + * generate_bitmap_or_paths(). |
| 2779 | + */ |
2747 | 2780 | foreach(lc, rel->indexlist)
|
2748 | 2781 | {
|
2749 | 2782 | IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
|
| 2783 | + ListCell *lcr; |
2750 | 2784 |
|
2751 | 2785 | if (index->indpred == NIL)
|
2752 |
| - continue; /* ignore non-partial indexes */ |
| 2786 | + continue; /* ignore non-partial indexes here */ |
2753 | 2787 |
|
2754 |
| - if (index->predOK) |
2755 |
| - continue; /* don't repeat work if already proven OK */ |
| 2788 | + if (!index->predOK) /* don't repeat work if already proven OK */ |
| 2789 | + index->predOK = predicate_implied_by(index->indpred, clauselist); |
2756 | 2790 |
|
2757 |
| - index->predOK = predicate_implied_by(index->indpred, clauselist); |
| 2791 | + /* If rel is an update target, leave indrestrictinfo as set above */ |
| 2792 | + if (is_target_rel) |
| 2793 | + continue; |
| 2794 | + |
| 2795 | + /* Else compute indrestrictinfo as the non-implied quals */ |
| 2796 | + index->indrestrictinfo = NIL; |
| 2797 | + foreach(lcr, rel->baserestrictinfo) |
| 2798 | + { |
| 2799 | + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcr); |
| 2800 | + |
| 2801 | + /* predicate_implied_by() assumes first arg is immutable */ |
| 2802 | + if (contain_mutable_functions((Node *) rinfo->clause) || |
| 2803 | + !predicate_implied_by(list_make1(rinfo->clause), |
| 2804 | + index->indpred)) |
| 2805 | + index->indrestrictinfo = lappend(index->indrestrictinfo, rinfo); |
| 2806 | + } |
2758 | 2807 | }
|
2759 | 2808 | }
|
2760 | 2809 |
|
|
0 commit comments