@@ -1247,8 +1247,10 @@ innerrel_is_unique(PlannerInfo *root,
1247
1247
1248
1248
/*
1249
1249
* innerrel_is_unique_ext
1250
- * Do the same as innerrel_is_unique(), but also return additional clauses
1251
- * from a baserestrictinfo list that were used to prove uniqueness.
1250
+ * Do the same as innerrel_is_unique(), but also set to '*extra_clauses'
1251
+ * additional clauses from a baserestrictinfo list that were used to prove
1252
+ * uniqueness. A non NULL 'extra_clauses' indicates that we're checking
1253
+ * for self-join and correspondingly dealing with filtered clauses.
1252
1254
*/
1253
1255
bool
1254
1256
innerrel_is_unique_ext (PlannerInfo * root ,
@@ -1264,6 +1266,7 @@ innerrel_is_unique_ext(PlannerInfo *root,
1264
1266
ListCell * lc ;
1265
1267
UniqueRelInfo * uniqueRelInfo ;
1266
1268
List * outer_exprs = NIL ;
1269
+ bool self_join = (extra_clauses != NULL );
1267
1270
1268
1271
/* Certainly can't prove uniqueness when there are no joinclauses */
1269
1272
if (restrictlist == NIL )
@@ -1278,16 +1281,23 @@ innerrel_is_unique_ext(PlannerInfo *root,
1278
1281
1279
1282
/*
1280
1283
* Query the cache to see if we've managed to prove that innerrel is
1281
- * unique for any subset of this outerrel. We don't need an exact match,
1282
- * as extra outerrels can't make the innerrel any less unique (or more
1283
- * formally, the restrictlist for a join to a superset outerrel must be a
1284
- * superset of the conditions we successfully used before).
1284
+ * unique for any subset of this outerrel. For non self-join search, we
1285
+ * don't need an exact match, as extra outerrels can't make the innerrel
1286
+ * any less unique (or more formally, the restrictlist for a join to a
1287
+ * superset outerrel must be a superset of the conditions we successfully
1288
+ * used before). For self-join search, we require an exact match of
1289
+ * outerrels, because we need extra clauses to be valid for our case.
1290
+ * Also, for self-join checking we've filtered the clauses list. Thus,
1291
+ * for a self-join search, we can match only the result cached for another
1292
+ * self-join check.
1285
1293
*/
1286
1294
foreach (lc , innerrel -> unique_for_rels )
1287
1295
{
1288
1296
uniqueRelInfo = (UniqueRelInfo * ) lfirst (lc );
1289
1297
1290
- if (bms_is_subset (uniqueRelInfo -> outerrelids , outerrelids ))
1298
+ if ((!self_join && bms_is_subset (uniqueRelInfo -> outerrelids , outerrelids )) ||
1299
+ (self_join && bms_equal (uniqueRelInfo -> outerrelids , outerrelids ) &&
1300
+ uniqueRelInfo -> self_join ))
1291
1301
{
1292
1302
if (extra_clauses )
1293
1303
* extra_clauses = uniqueRelInfo -> extra_clauses ;
@@ -1309,7 +1319,8 @@ innerrel_is_unique_ext(PlannerInfo *root,
1309
1319
1310
1320
/* No cached information, so try to make the proof. */
1311
1321
if (is_innerrel_unique_for (root , joinrelids , outerrelids , innerrel ,
1312
- jointype , restrictlist , & outer_exprs ))
1322
+ jointype , restrictlist ,
1323
+ self_join ? & outer_exprs : NULL ))
1313
1324
{
1314
1325
/*
1315
1326
* Cache the positive result for future probes, being sure to keep it
@@ -1323,8 +1334,9 @@ innerrel_is_unique_ext(PlannerInfo *root,
1323
1334
*/
1324
1335
old_context = MemoryContextSwitchTo (root -> planner_cxt );
1325
1336
uniqueRelInfo = makeNode (UniqueRelInfo );
1326
- uniqueRelInfo -> extra_clauses = outer_exprs ;
1327
1337
uniqueRelInfo -> outerrelids = bms_copy (outerrelids );
1338
+ uniqueRelInfo -> self_join = self_join ;
1339
+ uniqueRelInfo -> extra_clauses = outer_exprs ;
1328
1340
innerrel -> unique_for_rels = lappend (innerrel -> unique_for_rels ,
1329
1341
uniqueRelInfo );
1330
1342
MemoryContextSwitchTo (old_context );
0 commit comments