]> granicus.if.org Git - postgresql/commitdiff
Don't trust deferred-unique indexes for join removal.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Oct 2011 04:43:52 +0000 (00:43 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Oct 2011 04:43:52 +0000 (00:43 -0400)
The uniqueness condition might fail to hold intra-transaction, and assuming
it does can give incorrect query results.  Per report from Marti Raudsepp,
though this is not his proposed patch.

Back-patch to 9.0, where both these features were introduced.  In the
released branches, add the new IndexOptInfo field to the end of the struct,
to try to minimize ABI breakage for third-party code that may be examining
that struct.

src/backend/nodes/outfuncs.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/util/plancat.c
src/backend/utils/adt/selfuncs.c
src/include/nodes/relation.h

index 09dc9ccb5ece83b2870dcf45c555abb762881932..5c56658a271dfc9c1446cd6673a5cd401771d557 100644 (file)
@@ -1616,6 +1616,7 @@ _outIndexOptInfo(StringInfo str, IndexOptInfo *node)
        WRITE_NODE_FIELD(indpred);
        WRITE_BOOL_FIELD(predOK);
        WRITE_BOOL_FIELD(unique);
+       WRITE_BOOL_FIELD(immediate);
        WRITE_BOOL_FIELD(hypothetical);
 }
 
index 2c97bea3fa3a346f05a54904859b082e3872786c..e43e12d8832d92ca979ed8b1e0169a5baba90b2b 100644 (file)
@@ -1948,10 +1948,11 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
                int                     c;
 
                /*
-                * If the index is not unique or if it's a partial index that doesn't
-                * match the query, it's useless here.
+                * If the index is not unique, or not immediately enforced, or if it's
+                * a partial index that doesn't match the query, it's useless here.
                 */
-               if (!ind->unique || (ind->indpred != NIL && !ind->predOK))
+               if (!ind->unique || !ind->immediate ||
+                       (ind->indpred != NIL && !ind->predOK))
                        continue;
 
                /*
index e35c8c326d7ea37d3957c77c180cf2b3beaeebf1..f7fb38404f21ae4e8976a5a9171064624010b088 100644 (file)
@@ -275,6 +275,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
                                ChangeVarNodes((Node *) info->indpred, 1, varno, 0);
                        info->predOK = false;           /* set later in indxpath.c */
                        info->unique = index->indisunique;
+                       info->immediate = index->indimmediate;
                        info->hypothetical = false;
 
                        /*
@@ -876,6 +877,11 @@ join_selectivity(PlannerInfo *root,
  * Detect whether there is a unique index on the specified attribute
  * of the specified relation, thus allowing us to conclude that all
  * the (non-null) values of the attribute are distinct.
+ *
+ * This function does not check the index's indimmediate property, which
+ * means that uniqueness may transiently fail to hold intra-transaction.
+ * That's appropriate when we are making statistical estimates, but beware
+ * of using this for any correctness proofs.
  */
 bool
 has_unique_index(RelOptInfo *rel, AttrNumber attno)
index 7c1567a2cc3a733d9349fbc5a04ed6636740dfae..6989627adc3da9b4c7a6d10e8c469102c9103406 100644 (file)
@@ -4102,7 +4102,9 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
  *             commonly the same as the exposed type of the variable argument,
  *             but can be different in binary-compatible-type cases.
  *     isunique: TRUE if we were able to match the var to a unique index,
- *             implying its values are unique for this query.
+ *             implying its values are unique for this query.  (Caution: this
+ *             should be trusted for statistical purposes only, since we do not
+ *             check indimmediate.)
  *
  * Caller is responsible for doing ReleaseVariableStats() before exiting.
  */
index 7d39e10747ac7bd05ffce0190ea616a93645a857..dc3a37eae950dc72aff47b94f9f377e7845a33b6 100644 (file)
@@ -473,6 +473,8 @@ typedef struct IndexOptInfo
        bool            amhasgetbitmap; /* does AM have amgetbitmap interface? */
        /* added in 9.0.4: */
        bool            hypothetical;   /* true if index doesn't really exist */
+       /* added in 9.0.6: */
+       bool            immediate;              /* is uniqueness enforced immediately? */
 } IndexOptInfo;