8000 Don't trust deferred-unique indexes for join removal. · fschopp/postgres@0f39d50 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 0f39d50

Browse files
committed
Don't trust deferred-unique indexes for join removal.
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.
1 parent bb446b6 commit 0f39d50

File tree

5 files changed

+15
-4
lines changed

5 files changed

+15
-4
lines changed

src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,7 @@ _outIndexOptInfo(StringInfo str, IndexOptInfo *node)
17701770
WRITE_NODE_FIELD(indextlist);
17711771
WRITE_BOOL_FIELD(predOK);
17721772
WRITE_BOOL_FIELD(unique);
1773+
WRITE_BOOL_FIELD(immediate);
17731774
WRITE_BOOL_FIELD(hypothetical);
17741775
}
17751776

src/backend/optimizer/path/indxpath.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,10 +2277,11 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
22772277
int c;
22782278

22792279
/*
2280-
* If the index is not unique or if it's a partial index that doesn't
2281-
* match the query, it's useless here.
2280+
* If the index is not unique, or not immediately enforced, or if it's
2281+
* a partial index that doesn't match the query, it's useless here.
22822282
*/
2283-
if (!ind->unique || (ind->indpred != NIL && !ind->predOK))
2283+
if (!ind->unique || !ind->immediate ||
2284+
(ind->indpred != NIL && !ind->predOK))
22842285
continue;
22852286

22862287
/*

src/backend/optimizer/util/plancat.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
324324

325325
info->predOK = false; /* set later in indxpath.c */
326326
info->unique = index->indisunique;
327+
info->immediate = index->indimmediate;
327328
info->hypothetical = false;
328329

329330
/*
@@ -1076,6 +1077,11 @@ join_selectivity(PlannerInfo *root,
10761077
* Detect whether there is a unique index on the specified attribute
10771078
* of the specified relation, thus allowing us to conclude that all
10781079
* the (non-null) values of the attribute are distinct.
1080+
*
1081+
* This function does not check the index's indimmediate property, which
1082+
* means that uniqueness may transiently fail to hold intra-transaction.
1083+
* That's appropriate when we are making statistical estimates, but beware
1084+
* of using this for any correctness proofs.
10791085
*/
10801086
bool
10811087
has_unique_index(RelOptInfo *rel, AttrNumber attno)

src/backend/utils/adt/selfuncs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4129,7 +4129,9 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
41294129
* commonly the same as the exposed type of the variable argument,
41304130
* but can be different in binary-compatible-type cases.
41314131
* isunique: TRUE if we were able to match the var to a unique index,
4132-
* implying its values are unique for this query.
4132+
* implying its values are unique for this query. (Caution: this
4133+
* should be trusted for statistical purposes only, since we do not
4134+
* check indimmediate.)
41334135
*
41344136
* Caller is responsible for doing ReleaseVariableStats() before exiting.
41354137
*/

src/include/nodes/relation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ typedef struct IndexOptInfo
488488

489489
bool predOK; /* true if predicate matches query */
490490
bool unique; /* true if a unique index */
491+
bool immediate; /* is uniqueness enforced immediately? */
491492
bool hypothetical; /* true if index doesn't really exist */
492493
bool amcanorderbyop; /* does AM support order by operator result? */
493494
bool amcanreturn; /* can AM return IndexTuples? */

0 commit comments

Comments
 (0)
0