Coverage Report

Created: 2025-06-13 06:06

/src/postgres/src/backend/executor/execIndexing.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * execIndexing.c
4
 *    routines for inserting index tuples and enforcing unique and
5
 *    exclusion constraints.
6
 *
7
 * ExecInsertIndexTuples() is the main entry point.  It's called after
8
 * inserting a tuple to the heap, and it inserts corresponding index tuples
9
 * into all indexes.  At the same time, it enforces any unique and
10
 * exclusion constraints:
11
 *
12
 * Unique Indexes
13
 * --------------
14
 *
15
 * Enforcing a unique constraint is straightforward.  When the index AM
16
 * inserts the tuple to the index, it also checks that there are no
17
 * conflicting tuples in the index already.  It does so atomically, so that
18
 * even if two backends try to insert the same key concurrently, only one
19
 * of them will succeed.  All the logic to ensure atomicity, and to wait
20
 * for in-progress transactions to finish, is handled by the index AM.
21
 *
22
 * If a unique constraint is deferred, we request the index AM to not
23
 * throw an error if a conflict is found.  Instead, we make note that there
24
 * was a conflict and return the list of indexes with conflicts to the
25
 * caller.  The caller must re-check them later, by calling index_insert()
26
 * with the UNIQUE_CHECK_EXISTING option.
27
 *
28
 * Exclusion Constraints
29
 * ---------------------
30
 *
31
 * Exclusion constraints are different from unique indexes in that when the
32
 * tuple is inserted to the index, the index AM does not check for
33
 * duplicate keys at the same time.  After the insertion, we perform a
34
 * separate scan on the index to check for conflicting tuples, and if one
35
 * is found, we throw an error and the transaction is aborted.  If the
36
 * conflicting tuple's inserter or deleter is in-progress, we wait for it
37
 * to finish first.
38
 *
39
 * There is a chance of deadlock, if two backends insert a tuple at the
40
 * same time, and then perform the scan to check for conflicts.  They will
41
 * find each other's tuple, and both try to wait for each other.  The
42
 * deadlock detector will detect that, and abort one of the transactions.
43
 * That's fairly harmless, as one of them was bound to abort with a
44
 * "duplicate key error" anyway, although you get a different error
45
 * message.
46
 *
47
 * If an exclusion constraint is deferred, we still perform the conflict
48
 * checking scan immediately after inserting the index tuple.  But instead
49
 * of throwing an error if a conflict is found, we return that information
50
 * to the caller.  The caller must re-check them later by calling
51
 * check_exclusion_constraint().
52
 *
53
 * Speculative insertion
54
 * ---------------------
55
 *
56
 * Speculative insertion is a two-phase mechanism used to implement
57
 * INSERT ... ON CONFLICT DO UPDATE/NOTHING.  The tuple is first inserted
58
 * to the heap and update the indexes as usual, but if a constraint is
59
 * violated, we can still back out the insertion without aborting the whole
60
 * transaction.  In an INSERT ... ON CONFLICT statement, if a conflict is
61
 * detected, the inserted tuple is backed out and the ON CONFLICT action is
62
 * executed instead.
63
 *
64
 * Insertion to a unique index works as usual: the index AM checks for
65
 * duplicate keys atomically with the insertion.  But instead of throwing
66
 * an error on a conflict, the speculatively inserted heap tuple is backed
67
 * out.
68
 *
69
 * Exclusion constraints are slightly more complicated.  As mentioned
70
 * earlier, there is a risk of deadlock when two backends insert the same
71
 * key concurrently.  That was not a problem for regular insertions, when
72
 * one of the transactions has to be aborted anyway, but with a speculative
73
 * insertion we cannot let a deadlock happen, because we only want to back
74
 * out the speculatively inserted tuple on conflict, not abort the whole
75
 * transaction.
76
 *
77
 * When a backend detects that the speculative insertion conflicts with
78
 * another in-progress tuple, it has two options:
79
 *
80
 * 1. back out the speculatively inserted tuple, then wait for the other
81
 *    transaction, and retry. Or,
82
 * 2. wait for the other transaction, with the speculatively inserted tuple
83
 *    still in place.
84
 *
85
 * If two backends insert at the same time, and both try to wait for each
86
 * other, they will deadlock.  So option 2 is not acceptable.  Option 1
87
 * avoids the deadlock, but it is prone to a livelock instead.  Both
88
 * transactions will wake up immediately as the other transaction backs
89
 * out.  Then they both retry, and conflict with each other again, lather,
90
 * rinse, repeat.
91
 *
92
 * To avoid the livelock, one of the backends must back out first, and then
93
 * wait, while the other one waits without backing out.  It doesn't matter
94
 * which one backs out, so we employ an arbitrary rule that the transaction
95
 * with the higher XID backs out.
96
 *
97
 *
98
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
99
 * Portions Copyright (c) 1994, Regents of the University of California
100
 *
101
 *
102
 * IDENTIFICATION
103
 *    src/backend/executor/execIndexing.c
104
 *
105
 *-------------------------------------------------------------------------
106
 */
107
#include "postgres.h"
108
109
#include "access/genam.h"
110
#include "access/relscan.h"
111
#include "access/tableam.h"
112
#include "access/xact.h"
113
#include "catalog/index.h"
114
#include "executor/executor.h"
115
#include "nodes/nodeFuncs.h"
116
#include "storage/lmgr.h"
117
#include "utils/multirangetypes.h"
118
#include "utils/rangetypes.h"
119
#include "utils/snapmgr.h"
120
121
/* waitMode argument to check_exclusion_or_unique_constraint() */
122
typedef enum
123
{
124
  CEOUC_WAIT,
125
  CEOUC_NOWAIT,
126
  CEOUC_LIVELOCK_PREVENTING_WAIT,
127
} CEOUC_WAIT_MODE;
128
129
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index,
130
                         IndexInfo *indexInfo,
131
                         ItemPointer tupleid,
132
                         const Datum *values, const bool *isnull,
133
                         EState *estate, bool newIndex,
134
                         CEOUC_WAIT_MODE waitMode,
135
                         bool violationOK,
136
                         ItemPointer conflictTid);
137
138
static bool index_recheck_constraint(Relation index, const Oid *constr_procs,
139
                   const Datum *existing_values, const bool *existing_isnull,
140
                   const Datum *new_values);
141
static bool index_unchanged_by_update(ResultRelInfo *resultRelInfo,
142
                    EState *estate, IndexInfo *indexInfo,
143
                    Relation indexRelation);
144
static bool index_expression_changed_walker(Node *node,
145
                      Bitmapset *allUpdatedCols);
146
static void ExecWithoutOverlapsNotEmpty(Relation rel, NameData attname, Datum attval,
147
                    char typtype, Oid atttypid);
148
149
/* ----------------------------------------------------------------
150
 *    ExecOpenIndices
151
 *
152
 *    Find the indices associated with a result relation, open them,
153
 *    and save information about them in the result ResultRelInfo.
154
 *
155
 *    At entry, caller has already opened and locked
156
 *    resultRelInfo->ri_RelationDesc.
157
 * ----------------------------------------------------------------
158
 */
159
void
160
ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
161
0
{
162
0
  Relation  resultRelation = resultRelInfo->ri_RelationDesc;
163
0
  List     *indexoidlist;
164
0
  ListCell   *l;
165
0
  int     len,
166
0
        i;
167
0
  RelationPtr relationDescs;
168
0
  IndexInfo **indexInfoArray;
169
170
0
  resultRelInfo->ri_NumIndices = 0;
171
172
  /* fast path if no indexes */
173
0
  if (!RelationGetForm(resultRelation)->relhasindex)
174
0
    return;
175
176
  /*
177
   * Get cached list of index OIDs
178
   */
179
0
  indexoidlist = RelationGetIndexList(resultRelation);
180
0
  len = list_length(indexoidlist);
181
0
  if (len == 0)
182
0
    return;
183
184
  /* This Assert will fail if ExecOpenIndices is called twice */
185
0
  Assert(resultRelInfo->ri_IndexRelationDescs == NULL);
186
187
  /*
188
   * allocate space for result arrays
189
   */
190
0
  relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
191
0
  indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
192
193
0
  resultRelInfo->ri_NumIndices = len;
194
0
  resultRelInfo->ri_IndexRelationDescs = relationDescs;
195
0
  resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
196
197
  /*
198
   * For each index, open the index relation and save pg_index info. We
199
   * acquire RowExclusiveLock, signifying we will update the index.
200
   *
201
   * Note: we do this even if the index is not indisready; it's not worth
202
   * the trouble to optimize for the case where it isn't.
203
   */
204
0
  i = 0;
205
0
  foreach(l, indexoidlist)
206
0
  {
207
0
    Oid     indexOid = lfirst_oid(l);
208
0
    Relation  indexDesc;
209
0
    IndexInfo  *ii;
210
211
0
    indexDesc = index_open(indexOid, RowExclusiveLock);
212
213
    /* extract index key information from the index's pg_index info */
214
0
    ii = BuildIndexInfo(indexDesc);
215
216
    /*
217
     * If the indexes are to be used for speculative insertion, add extra
218
     * information required by unique index entries.
219
     */
220
0
    if (speculative && ii->ii_Unique && !indexDesc->rd_index->indisexclusion)
221
0
      BuildSpeculativeIndexInfo(indexDesc, ii);
222
223
0
    relationDescs[i] = indexDesc;
224
0
    indexInfoArray[i] = ii;
225
0
    i++;
226
0
  }
227
228
0
  list_free(indexoidlist);
229
0
}
230
231
/* ----------------------------------------------------------------
232
 *    ExecCloseIndices
233
 *
234
 *    Close the index relations stored in resultRelInfo
235
 * ----------------------------------------------------------------
236
 */
237
void
238
ExecCloseIndices(ResultRelInfo *resultRelInfo)
239
0
{
240
0
  int     i;
241
0
  int     numIndices;
242
0
  RelationPtr indexDescs;
243
0
  IndexInfo **indexInfos;
244
245
0
  numIndices = resultRelInfo->ri_NumIndices;
246
0
  indexDescs = resultRelInfo->ri_IndexRelationDescs;
247
0
  indexInfos = resultRelInfo->ri_IndexRelationInfo;
248
249
0
  for (i = 0; i < numIndices; i++)
250
0
  {
251
    /* This Assert will fail if ExecCloseIndices is called twice */
252
0
    Assert(indexDescs[i] != NULL);
253
254
    /* Give the index a chance to do some post-insert cleanup */
255
0
    index_insert_cleanup(indexDescs[i], indexInfos[i]);
256
257
    /* Drop lock acquired by ExecOpenIndices */
258
0
    index_close(indexDescs[i], RowExclusiveLock);
259
260
    /* Mark the index as closed */
261
0
    indexDescs[i] = NULL;
262
0
  }
263
264
  /*
265
   * We don't attempt to free the IndexInfo data structures or the arrays,
266
   * instead assuming that such stuff will be cleaned up automatically in
267
   * FreeExecutorState.
268
   */
269
0
}
270
271
/* ----------------------------------------------------------------
272
 *    ExecInsertIndexTuples
273
 *
274
 *    This routine takes care of inserting index tuples
275
 *    into all the relations indexing the result relation
276
 *    when a heap tuple is inserted into the result relation.
277
 *
278
 *    When 'update' is true and 'onlySummarizing' is false,
279
 *    executor is performing an UPDATE that could not use an
280
 *    optimization like heapam's HOT (in more general terms a
281
 *    call to table_tuple_update() took place and set
282
 *    'update_indexes' to TUUI_All).  Receiving this hint makes
283
 *    us consider if we should pass down the 'indexUnchanged'
284
 *    hint in turn.  That's something that we figure out for
285
 *    each index_insert() call iff 'update' is true.
286
 *    (When 'update' is false we already know not to pass the
287
 *    hint to any index.)
288
 *
289
 *    If onlySummarizing is set, an equivalent optimization to
290
 *    HOT has been applied and any updated columns are indexed
291
 *    only by summarizing indexes (or in more general terms a
292
 *    call to table_tuple_update() took place and set
293
 *    'update_indexes' to TUUI_Summarizing). We can (and must)
294
 *    therefore only update the indexes that have
295
 *    'amsummarizing' = true.
296
 *
297
 *    Unique and exclusion constraints are enforced at the same
298
 *    time.  This returns a list of index OIDs for any unique or
299
 *    exclusion constraints that are deferred and that had
300
 *    potential (unconfirmed) conflicts.  (if noDupErr == true,
301
 *    the same is done for non-deferred constraints, but report
302
 *    if conflict was speculative or deferred conflict to caller)
303
 *
304
 *    If 'arbiterIndexes' is nonempty, noDupErr applies only to
305
 *    those indexes.  NIL means noDupErr applies to all indexes.
306
 * ----------------------------------------------------------------
307
 */
308
List *
309
ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
310
            TupleTableSlot *slot,
311
            EState *estate,
312
            bool update,
313
            bool noDupErr,
314
            bool *specConflict,
315
            List *arbiterIndexes,
316
            bool onlySummarizing)
317
0
{
318
0
  ItemPointer tupleid = &slot->tts_tid;
319
0
  List     *result = NIL;
320
0
  int     i;
321
0
  int     numIndices;
322
0
  RelationPtr relationDescs;
323
0
  Relation  heapRelation;
324
0
  IndexInfo **indexInfoArray;
325
0
  ExprContext *econtext;
326
0
  Datum   values[INDEX_MAX_KEYS];
327
0
  bool    isnull[INDEX_MAX_KEYS];
328
329
0
  Assert(ItemPointerIsValid(tupleid));
330
331
  /*
332
   * Get information from the result relation info structure.
333
   */
334
0
  numIndices = resultRelInfo->ri_NumIndices;
335
0
  relationDescs = resultRelInfo->ri_IndexRelationDescs;
336
0
  indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
337
0
  heapRelation = resultRelInfo->ri_RelationDesc;
338
339
  /* Sanity check: slot must belong to the same rel as the resultRelInfo. */
340
0
  Assert(slot->tts_tableOid == RelationGetRelid(heapRelation));
341
342
  /*
343
   * We will use the EState's per-tuple context for evaluating predicates
344
   * and index expressions (creating it if it's not already there).
345
   */
346
0
  econtext = GetPerTupleExprContext(estate);
347
348
  /* Arrange for econtext's scan tuple to be the tuple under test */
349
0
  econtext->ecxt_scantuple = slot;
350
351
  /*
352
   * for each index, form and insert the index tuple
353
   */
354
0
  for (i = 0; i < numIndices; i++)
355
0
  {
356
0
    Relation  indexRelation = relationDescs[i];
357
0
    IndexInfo  *indexInfo;
358
0
    bool    applyNoDupErr;
359
0
    IndexUniqueCheck checkUnique;
360
0
    bool    indexUnchanged;
361
0
    bool    satisfiesConstraint;
362
363
0
    if (indexRelation == NULL)
364
0
      continue;
365
366
0
    indexInfo = indexInfoArray[i];
367
368
    /* If the index is marked as read-only, ignore it */
369
0
    if (!indexInfo->ii_ReadyForInserts)
370
0
      continue;
371
372
    /*
373
     * Skip processing of non-summarizing indexes if we only update
374
     * summarizing indexes
375
     */
376
0
    if (onlySummarizing && !indexInfo->ii_Summarizing)
377
0
      continue;
378
379
    /* Check for partial index */
380
0
    if (indexInfo->ii_Predicate != NIL)
381
0
    {
382
0
      ExprState  *predicate;
383
384
      /*
385
       * If predicate state not set up yet, create it (in the estate's
386
       * per-query context)
387
       */
388
0
      predicate = indexInfo->ii_PredicateState;
389
0
      if (predicate == NULL)
390
0
      {
391
0
        predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
392
0
        indexInfo->ii_PredicateState = predicate;
393
0
      }
394
395
      /* Skip this index-update if the predicate isn't satisfied */
396
0
      if (!ExecQual(predicate, econtext))
397
0
        continue;
398
0
    }
399
400
    /*
401
     * FormIndexDatum fills in its values and isnull parameters with the
402
     * appropriate values for the column(s) of the index.
403
     */
404
0
    FormIndexDatum(indexInfo,
405
0
             slot,
406
0
             estate,
407
0
             values,
408
0
             isnull);
409
410
    /* Check whether to apply noDupErr to this index */
411
0
    applyNoDupErr = noDupErr &&
412
0
      (arbiterIndexes == NIL ||
413
0
       list_member_oid(arbiterIndexes,
414
0
               indexRelation->rd_index->indexrelid));
415
416
    /*
417
     * The index AM does the actual insertion, plus uniqueness checking.
418
     *
419
     * For an immediate-mode unique index, we just tell the index AM to
420
     * throw error if not unique.
421
     *
422
     * For a deferrable unique index, we tell the index AM to just detect
423
     * possible non-uniqueness, and we add the index OID to the result
424
     * list if further checking is needed.
425
     *
426
     * For a speculative insertion (used by INSERT ... ON CONFLICT), do
427
     * the same as for a deferrable unique index.
428
     */
429
0
    if (!indexRelation->rd_index->indisunique)
430
0
      checkUnique = UNIQUE_CHECK_NO;
431
0
    else if (applyNoDupErr)
432
0
      checkUnique = UNIQUE_CHECK_PARTIAL;
433
0
    else if (indexRelation->rd_index->indimmediate)
434
0
      checkUnique = UNIQUE_CHECK_YES;
435
0
    else
436
0
      checkUnique = UNIQUE_CHECK_PARTIAL;
437
438
    /*
439
     * There's definitely going to be an index_insert() call for this
440
     * index.  If we're being called as part of an UPDATE statement,
441
     * consider if the 'indexUnchanged' = true hint should be passed.
442
     */
443
0
    indexUnchanged = update && index_unchanged_by_update(resultRelInfo,
444
0
                               estate,
445
0
                               indexInfo,
446
0
                               indexRelation);
447
448
0
    satisfiesConstraint =
449
0
      index_insert(indexRelation, /* index relation */
450
0
             values,  /* array of index Datums */
451
0
             isnull,  /* null flags */
452
0
             tupleid, /* tid of heap tuple */
453
0
             heapRelation,  /* heap relation */
454
0
             checkUnique, /* type of uniqueness check to do */
455
0
             indexUnchanged,  /* UPDATE without logical change? */
456
0
             indexInfo);  /* index AM may need this */
457
458
    /*
459
     * If the index has an associated exclusion constraint, check that.
460
     * This is simpler than the process for uniqueness checks since we
461
     * always insert first and then check.  If the constraint is deferred,
462
     * we check now anyway, but don't throw error on violation or wait for
463
     * a conclusive outcome from a concurrent insertion; instead we'll
464
     * queue a recheck event.  Similarly, noDupErr callers (speculative
465
     * inserters) will recheck later, and wait for a conclusive outcome
466
     * then.
467
     *
468
     * An index for an exclusion constraint can't also be UNIQUE (not an
469
     * essential property, we just don't allow it in the grammar), so no
470
     * need to preserve the prior state of satisfiesConstraint.
471
     */
472
0
    if (indexInfo->ii_ExclusionOps != NULL)
473
0
    {
474
0
      bool    violationOK;
475
0
      CEOUC_WAIT_MODE waitMode;
476
477
0
      if (applyNoDupErr)
478
0
      {
479
0
        violationOK = true;
480
0
        waitMode = CEOUC_LIVELOCK_PREVENTING_WAIT;
481
0
      }
482
0
      else if (!indexRelation->rd_index->indimmediate)
483
0
      {
484
0
        violationOK = true;
485
0
        waitMode = CEOUC_NOWAIT;
486
0
      }
487
0
      else
488
0
      {
489
0
        violationOK = false;
490
0
        waitMode = CEOUC_WAIT;
491
0
      }
492
493
0
      satisfiesConstraint =
494
0
        check_exclusion_or_unique_constraint(heapRelation,
495
0
                           indexRelation, indexInfo,
496
0
                           tupleid, values, isnull,
497
0
                           estate, false,
498
0
                           waitMode, violationOK, NULL);
499
0
    }
500
501
0
    if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
502
0
       indexInfo->ii_ExclusionOps != NULL) &&
503
0
      !satisfiesConstraint)
504
0
    {
505
      /*
506
       * The tuple potentially violates the uniqueness or exclusion
507
       * constraint, so make a note of the index so that we can re-check
508
       * it later.  Speculative inserters are told if there was a
509
       * speculative conflict, since that always requires a restart.
510
       */
511
0
      result = lappend_oid(result, RelationGetRelid(indexRelation));
512
0
      if (indexRelation->rd_index->indimmediate && specConflict)
513
0
        *specConflict = true;
514
0
    }
515
0
  }
516
517
0
  return result;
518
0
}
519
520
/* ----------------------------------------------------------------
521
 *    ExecCheckIndexConstraints
522
 *
523
 *    This routine checks if a tuple violates any unique or
524
 *    exclusion constraints.  Returns true if there is no conflict.
525
 *    Otherwise returns false, and the TID of the conflicting
526
 *    tuple is returned in *conflictTid.
527
 *
528
 *    If 'arbiterIndexes' is given, only those indexes are checked.
529
 *    NIL means all indexes.
530
 *
531
 *    Note that this doesn't lock the values in any way, so it's
532
 *    possible that a conflicting tuple is inserted immediately
533
 *    after this returns.  This can be used for either a pre-check
534
 *    before insertion or a re-check after finding a conflict.
535
 *
536
 *    'tupleid' should be the TID of the tuple that has been recently
537
 *    inserted (or can be invalid if we haven't inserted a new tuple yet).
538
 *    This tuple will be excluded from conflict checking.
539
 * ----------------------------------------------------------------
540
 */
541
bool
542
ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
543
              EState *estate, ItemPointer conflictTid,
544
              ItemPointer tupleid, List *arbiterIndexes)
545
0
{
546
0
  int     i;
547
0
  int     numIndices;
548
0
  RelationPtr relationDescs;
549
0
  Relation  heapRelation;
550
0
  IndexInfo **indexInfoArray;
551
0
  ExprContext *econtext;
552
0
  Datum   values[INDEX_MAX_KEYS];
553
0
  bool    isnull[INDEX_MAX_KEYS];
554
0
  ItemPointerData invalidItemPtr;
555
0
  bool    checkedIndex = false;
556
557
0
  ItemPointerSetInvalid(conflictTid);
558
0
  ItemPointerSetInvalid(&invalidItemPtr);
559
560
  /*
561
   * Get information from the result relation info structure.
562
   */
563
0
  numIndices = resultRelInfo->ri_NumIndices;
564
0
  relationDescs = resultRelInfo->ri_IndexRelationDescs;
565
0
  indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
566
0
  heapRelation = resultRelInfo->ri_RelationDesc;
567
568
  /*
569
   * We will use the EState's per-tuple context for evaluating predicates
570
   * and index expressions (creating it if it's not already there).
571
   */
572
0
  econtext = GetPerTupleExprContext(estate);
573
574
  /* Arrange for econtext's scan tuple to be the tuple under test */
575
0
  econtext->ecxt_scantuple = slot;
576
577
  /*
578
   * For each index, form index tuple and check if it satisfies the
579
   * constraint.
580
   */
581
0
  for (i = 0; i < numIndices; i++)
582
0
  {
583
0
    Relation  indexRelation = relationDescs[i];
584
0
    IndexInfo  *indexInfo;
585
0
    bool    satisfiesConstraint;
586
587
0
    if (indexRelation == NULL)
588
0
      continue;
589
590
0
    indexInfo = indexInfoArray[i];
591
592
0
    if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps)
593
0
      continue;
594
595
    /* If the index is marked as read-only, ignore it */
596
0
    if (!indexInfo->ii_ReadyForInserts)
597
0
      continue;
598
599
    /* When specific arbiter indexes requested, only examine them */
600
0
    if (arbiterIndexes != NIL &&
601
0
      !list_member_oid(arbiterIndexes,
602
0
               indexRelation->rd_index->indexrelid))
603
0
      continue;
604
605
0
    if (!indexRelation->rd_index->indimmediate)
606
0
      ereport(ERROR,
607
0
          (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
608
0
           errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
609
0
           errtableconstraint(heapRelation,
610
0
                    RelationGetRelationName(indexRelation))));
611
612
0
    checkedIndex = true;
613
614
    /* Check for partial index */
615
0
    if (indexInfo->ii_Predicate != NIL)
616
0
    {
617
0
      ExprState  *predicate;
618
619
      /*
620
       * If predicate state not set up yet, create it (in the estate's
621
       * per-query context)
622
       */
623
0
      predicate = indexInfo->ii_PredicateState;
624
0
      if (predicate == NULL)
625
0
      {
626
0
        predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
627
0
        indexInfo->ii_PredicateState = predicate;
628
0
      }
629
630
      /* Skip this index-update if the predicate isn't satisfied */
631
0
      if (!ExecQual(predicate, econtext))
632
0
        continue;
633
0
    }
634
635
    /*
636
     * FormIndexDatum fills in its values and isnull parameters with the
637
     * appropriate values for the column(s) of the index.
638
     */
639
0
    FormIndexDatum(indexInfo,
640
0
             slot,
641
0
             estate,
642
0
             values,
643
0
             isnull);
644
645
0
    satisfiesConstraint =
646
0
      check_exclusion_or_unique_constraint(heapRelation, indexRelation,
647
0
                         indexInfo, tupleid,
648
0
                         values, isnull, estate, false,
649
0
                         CEOUC_WAIT, true,
650
0
                         conflictTid);
651
0
    if (!satisfiesConstraint)
652
0
      return false;
653
0
  }
654
655
0
  if (arbiterIndexes != NIL && !checkedIndex)
656
0
    elog(ERROR, "unexpected failure to find arbiter index");
657
658
0
  return true;
659
0
}
660
661
/*
662
 * Check for violation of an exclusion or unique constraint
663
 *
664
 * heap: the table containing the new tuple
665
 * index: the index supporting the constraint
666
 * indexInfo: info about the index, including the exclusion properties
667
 * tupleid: heap TID of the new tuple we have just inserted (invalid if we
668
 *    haven't inserted a new tuple yet)
669
 * values, isnull: the *index* column values computed for the new tuple
670
 * estate: an EState we can do evaluation in
671
 * newIndex: if true, we are trying to build a new index (this affects
672
 *    only the wording of error messages)
673
 * waitMode: whether to wait for concurrent inserters/deleters
674
 * violationOK: if true, don't throw error for violation
675
 * conflictTid: if not-NULL, the TID of the conflicting tuple is returned here
676
 *
677
 * Returns true if OK, false if actual or potential violation
678
 *
679
 * 'waitMode' determines what happens if a conflict is detected with a tuple
680
 * that was inserted or deleted by a transaction that's still running.
681
 * CEOUC_WAIT means that we wait for the transaction to commit, before
682
 * throwing an error or returning.  CEOUC_NOWAIT means that we report the
683
 * violation immediately; so the violation is only potential, and the caller
684
 * must recheck sometime later.  This behavior is convenient for deferred
685
 * exclusion checks; we need not bother queuing a deferred event if there is
686
 * definitely no conflict at insertion time.
687
 *
688
 * CEOUC_LIVELOCK_PREVENTING_WAIT is like CEOUC_NOWAIT, but we will sometimes
689
 * wait anyway, to prevent livelocking if two transactions try inserting at
690
 * the same time.  This is used with speculative insertions, for INSERT ON
691
 * CONFLICT statements. (See notes in file header)
692
 *
693
 * If violationOK is true, we just report the potential or actual violation to
694
 * the caller by returning 'false'.  Otherwise we throw a descriptive error
695
 * message here.  When violationOK is false, a false result is impossible.
696
 *
697
 * Note: The indexam is normally responsible for checking unique constraints,
698
 * so this normally only needs to be used for exclusion constraints.  But this
699
 * function is also called when doing a "pre-check" for conflicts on a unique
700
 * constraint, when doing speculative insertion.  Caller may use the returned
701
 * conflict TID to take further steps.
702
 */
703
static bool
704
check_exclusion_or_unique_constraint(Relation heap, Relation index,
705
                   IndexInfo *indexInfo,
706
                   ItemPointer tupleid,
707
                   const Datum *values, const bool *isnull,
708
                   EState *estate, bool newIndex,
709
                   CEOUC_WAIT_MODE waitMode,
710
                   bool violationOK,
711
                   ItemPointer conflictTid)
712
0
{
713
0
  Oid      *constr_procs;
714
0
  uint16     *constr_strats;
715
0
  Oid      *index_collations = index->rd_indcollation;
716
0
  int     indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
717
0
  IndexScanDesc index_scan;
718
0
  ScanKeyData scankeys[INDEX_MAX_KEYS];
719
0
  SnapshotData DirtySnapshot;
720
0
  int     i;
721
0
  bool    conflict;
722
0
  bool    found_self;
723
0
  ExprContext *econtext;
724
0
  TupleTableSlot *existing_slot;
725
0
  TupleTableSlot *save_scantuple;
726
727
0
  if (indexInfo->ii_ExclusionOps)
728
0
  {
729
0
    constr_procs = indexInfo->ii_ExclusionProcs;
730
0
    constr_strats = indexInfo->ii_ExclusionStrats;
731
0
  }
732
0
  else
733
0
  {
734
0
    constr_procs = indexInfo->ii_UniqueProcs;
735
0
    constr_strats = indexInfo->ii_UniqueStrats;
736
0
  }
737
738
  /*
739
   * If this is a WITHOUT OVERLAPS constraint, we must also forbid empty
740
   * ranges/multiranges. This must happen before we look for NULLs below, or
741
   * a UNIQUE constraint could insert an empty range along with a NULL
742
   * scalar part.
743
   */
744
0
  if (indexInfo->ii_WithoutOverlaps)
745
0
  {
746
    /*
747
     * Look up the type from the heap tuple, but check the Datum from the
748
     * index tuple.
749
     */
750
0
    AttrNumber  attno = indexInfo->ii_IndexAttrNumbers[indnkeyatts - 1];
751
752
0
    if (!isnull[indnkeyatts - 1])
753
0
    {
754
0
      TupleDesc tupdesc = RelationGetDescr(heap);
755
0
      Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
756
0
      TypeCacheEntry *typcache = lookup_type_cache(att->atttypid, 0);
757
758
0
      ExecWithoutOverlapsNotEmpty(heap, att->attname,
759
0
                    values[indnkeyatts - 1],
760
0
                    typcache->typtype, att->atttypid);
761
0
    }
762
0
  }
763
764
  /*
765
   * If any of the input values are NULL, and the index uses the default
766
   * nulls-are-distinct mode, the constraint check is assumed to pass (i.e.,
767
   * we assume the operators are strict).  Otherwise, we interpret the
768
   * constraint as specifying IS NULL for each column whose input value is
769
   * NULL.
770
   */
771
0
  if (!indexInfo->ii_NullsNotDistinct)
772
0
  {
773
0
    for (i = 0; i < indnkeyatts; i++)
774
0
    {
775
0
      if (isnull[i])
776
0
        return true;
777
0
    }
778
0
  }
779
780
  /*
781
   * Search the tuples that are in the index for any violations, including
782
   * tuples that aren't visible yet.
783
   */
784
0
  InitDirtySnapshot(DirtySnapshot);
785
786
0
  for (i = 0; i < indnkeyatts; i++)
787
0
  {
788
0
    ScanKeyEntryInitialize(&scankeys[i],
789
0
                 isnull[i] ? SK_ISNULL | SK_SEARCHNULL : 0,
790
0
                 i + 1,
791
0
                 constr_strats[i],
792
0
                 InvalidOid,
793
0
                 index_collations[i],
794
0
                 constr_procs[i],
795
0
                 values[i]);
796
0
  }
797
798
  /*
799
   * Need a TupleTableSlot to put existing tuples in.
800
   *
801
   * To use FormIndexDatum, we have to make the econtext's scantuple point
802
   * to this slot.  Be sure to save and restore caller's value for
803
   * scantuple.
804
   */
805
0
  existing_slot = table_slot_create(heap, NULL);
806
807
0
  econtext = GetPerTupleExprContext(estate);
808
0
  save_scantuple = econtext->ecxt_scantuple;
809
0
  econtext->ecxt_scantuple = existing_slot;
810
811
  /*
812
   * May have to restart scan from this point if a potential conflict is
813
   * found.
814
   */
815
0
retry:
816
0
  conflict = false;
817
0
  found_self = false;
818
0
  index_scan = index_beginscan(heap, index, &DirtySnapshot, NULL, indnkeyatts, 0);
819
0
  index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0);
820
821
0
  while (index_getnext_slot(index_scan, ForwardScanDirection, existing_slot))
822
0
  {
823
0
    TransactionId xwait;
824
0
    XLTW_Oper reason_wait;
825
0
    Datum   existing_values[INDEX_MAX_KEYS];
826
0
    bool    existing_isnull[INDEX_MAX_KEYS];
827
0
    char     *error_new;
828
0
    char     *error_existing;
829
830
    /*
831
     * Ignore the entry for the tuple we're trying to check.
832
     */
833
0
    if (ItemPointerIsValid(tupleid) &&
834
0
      ItemPointerEquals(tupleid, &existing_slot->tts_tid))
835
0
    {
836
0
      if (found_self)   /* should not happen */
837
0
        elog(ERROR, "found self tuple multiple times in index \"%s\"",
838
0
           RelationGetRelationName(index));
839
0
      found_self = true;
840
0
      continue;
841
0
    }
842
843
    /*
844
     * Extract the index column values and isnull flags from the existing
845
     * tuple.
846
     */
847
0
    FormIndexDatum(indexInfo, existing_slot, estate,
848
0
             existing_values, existing_isnull);
849
850
    /* If lossy indexscan, must recheck the condition */
851
0
    if (index_scan->xs_recheck)
852
0
    {
853
0
      if (!index_recheck_constraint(index,
854
0
                      constr_procs,
855
0
                      existing_values,
856
0
                      existing_isnull,
857
0
                      values))
858
0
        continue;   /* tuple doesn't actually match, so no
859
                 * conflict */
860
0
    }
861
862
    /*
863
     * At this point we have either a conflict or a potential conflict.
864
     *
865
     * If an in-progress transaction is affecting the visibility of this
866
     * tuple, we need to wait for it to complete and then recheck (unless
867
     * the caller requested not to).  For simplicity we do rechecking by
868
     * just restarting the whole scan --- this case probably doesn't
869
     * happen often enough to be worth trying harder, and anyway we don't
870
     * want to hold any index internal locks while waiting.
871
     */
872
0
    xwait = TransactionIdIsValid(DirtySnapshot.xmin) ?
873
0
      DirtySnapshot.xmin : DirtySnapshot.xmax;
874
875
0
    if (TransactionIdIsValid(xwait) &&
876
0
      (waitMode == CEOUC_WAIT ||
877
0
       (waitMode == CEOUC_LIVELOCK_PREVENTING_WAIT &&
878
0
        DirtySnapshot.speculativeToken &&
879
0
        TransactionIdPrecedes(GetCurrentTransactionId(), xwait))))
880
0
    {
881
0
      reason_wait = indexInfo->ii_ExclusionOps ?
882
0
        XLTW_RecheckExclusionConstr : XLTW_InsertIndex;
883
0
      index_endscan(index_scan);
884
0
      if (DirtySnapshot.speculativeToken)
885
0
        SpeculativeInsertionWait(DirtySnapshot.xmin,
886
0
                     DirtySnapshot.speculativeToken);
887
0
      else
888
0
        XactLockTableWait(xwait, heap,
889
0
                  &existing_slot->tts_tid, reason_wait);
890
0
      goto retry;
891
0
    }
892
893
    /*
894
     * We have a definite conflict (or a potential one, but the caller
895
     * didn't want to wait).  Return it to caller, or report it.
896
     */
897
0
    if (violationOK)
898
0
    {
899
0
      conflict = true;
900
0
      if (conflictTid)
901
0
        *conflictTid = existing_slot->tts_tid;
902
0
      break;
903
0
    }
904
905
0
    error_new = BuildIndexValueDescription(index, values, isnull);
906
0
    error_existing = BuildIndexValueDescription(index, existing_values,
907
0
                          existing_isnull);
908
0
    if (newIndex)
909
0
      ereport(ERROR,
910
0
          (errcode(ERRCODE_EXCLUSION_VIOLATION),
911
0
           errmsg("could not create exclusion constraint \"%s\"",
912
0
              RelationGetRelationName(index)),
913
0
           error_new && error_existing ?
914
0
           errdetail("Key %s conflicts with key %s.",
915
0
                 error_new, error_existing) :
916
0
           errdetail("Key conflicts exist."),
917
0
           errtableconstraint(heap,
918
0
                    RelationGetRelationName(index))));
919
0
    else
920
0
      ereport(ERROR,
921
0
          (errcode(ERRCODE_EXCLUSION_VIOLATION),
922
0
           errmsg("conflicting key value violates exclusion constraint \"%s\"",
923
0
              RelationGetRelationName(index)),
924
0
           error_new && error_existing ?
925
0
           errdetail("Key %s conflicts with existing key %s.",
926
0
                 error_new, error_existing) :
927
0
           errdetail("Key conflicts with existing key."),
928
0
           errtableconstraint(heap,
929
0
                    RelationGetRelationName(index))));
930
0
  }
931
932
0
  index_endscan(index_scan);
933
934
  /*
935
   * Ordinarily, at this point the search should have found the originally
936
   * inserted tuple (if any), unless we exited the loop early because of
937
   * conflict.  However, it is possible to define exclusion constraints for
938
   * which that wouldn't be true --- for instance, if the operator is <>. So
939
   * we no longer complain if found_self is still false.
940
   */
941
942
0
  econtext->ecxt_scantuple = save_scantuple;
943
944
0
  ExecDropSingleTupleTableSlot(existing_slot);
945
946
0
  return !conflict;
947
0
}
948
949
/*
950
 * Check for violation of an exclusion constraint
951
 *
952
 * This is a dumbed down version of check_exclusion_or_unique_constraint
953
 * for external callers. They don't need all the special modes.
954
 */
955
void
956
check_exclusion_constraint(Relation heap, Relation index,
957
               IndexInfo *indexInfo,
958
               ItemPointer tupleid,
959
               const Datum *values, const bool *isnull,
960
               EState *estate, bool newIndex)
961
0
{
962
0
  (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
963
0
                        values, isnull,
964
0
                        estate, newIndex,
965
0
                        CEOUC_WAIT, false, NULL);
966
0
}
967
968
/*
969
 * Check existing tuple's index values to see if it really matches the
970
 * exclusion condition against the new_values.  Returns true if conflict.
971
 */
972
static bool
973
index_recheck_constraint(Relation index, const Oid *constr_procs,
974
             const Datum *existing_values, const bool *existing_isnull,
975
             const Datum *new_values)
976
0
{
977
0
  int     indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
978
0
  int     i;
979
980
0
  for (i = 0; i < indnkeyatts; i++)
981
0
  {
982
    /* Assume the exclusion operators are strict */
983
0
    if (existing_isnull[i])
984
0
      return false;
985
986
0
    if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i],
987
0
                         index->rd_indcollation[i],
988
0
                         existing_values[i],
989
0
                         new_values[i])))
990
0
      return false;
991
0
  }
992
993
0
  return true;
994
0
}
995
996
/*
997
 * Check if ExecInsertIndexTuples() should pass indexUnchanged hint.
998
 *
999
 * When the executor performs an UPDATE that requires a new round of index
1000
 * tuples, determine if we should pass 'indexUnchanged' = true hint for one
1001
 * single index.
1002
 */
1003
static bool
1004
index_unchanged_by_update(ResultRelInfo *resultRelInfo, EState *estate,
1005
              IndexInfo *indexInfo, Relation indexRelation)
1006
0
{
1007
0
  Bitmapset  *updatedCols;
1008
0
  Bitmapset  *extraUpdatedCols;
1009
0
  Bitmapset  *allUpdatedCols;
1010
0
  bool    hasexpression = false;
1011
0
  List     *idxExprs;
1012
1013
  /*
1014
   * Check cache first
1015
   */
1016
0
  if (indexInfo->ii_CheckedUnchanged)
1017
0
    return indexInfo->ii_IndexUnchanged;
1018
0
  indexInfo->ii_CheckedUnchanged = true;
1019
1020
  /*
1021
   * Check for indexed attribute overlap with updated columns.
1022
   *
1023
   * Only do this for key columns.  A change to a non-key column within an
1024
   * INCLUDE index should not be counted here.  Non-key column values are
1025
   * opaque payload state to the index AM, a little like an extra table TID.
1026
   *
1027
   * Note that row-level BEFORE triggers won't affect our behavior, since
1028
   * they don't affect the updatedCols bitmaps generally.  It doesn't seem
1029
   * worth the trouble of checking which attributes were changed directly.
1030
   */
1031
0
  updatedCols = ExecGetUpdatedCols(resultRelInfo, estate);
1032
0
  extraUpdatedCols = ExecGetExtraUpdatedCols(resultRelInfo, estate);
1033
0
  for (int attr = 0; attr < indexInfo->ii_NumIndexKeyAttrs; attr++)
1034
0
  {
1035
0
    int     keycol = indexInfo->ii_IndexAttrNumbers[attr];
1036
1037
0
    if (keycol <= 0)
1038
0
    {
1039
      /*
1040
       * Skip expressions for now, but remember to deal with them later
1041
       * on
1042
       */
1043
0
      hasexpression = true;
1044
0
      continue;
1045
0
    }
1046
1047
0
    if (bms_is_member(keycol - FirstLowInvalidHeapAttributeNumber,
1048
0
              updatedCols) ||
1049
0
      bms_is_member(keycol - FirstLowInvalidHeapAttributeNumber,
1050
0
              extraUpdatedCols))
1051
0
    {
1052
      /* Changed key column -- don't hint for this index */
1053
0
      indexInfo->ii_IndexUnchanged = false;
1054
0
      return false;
1055
0
    }
1056
0
  }
1057
1058
  /*
1059
   * When we get this far and index has no expressions, return true so that
1060
   * index_insert() call will go on to pass 'indexUnchanged' = true hint.
1061
   *
1062
   * The _absence_ of an indexed key attribute that overlaps with updated
1063
   * attributes (in addition to the total absence of indexed expressions)
1064
   * shows that the index as a whole is logically unchanged by UPDATE.
1065
   */
1066
0
  if (!hasexpression)
1067
0
  {
1068
0
    indexInfo->ii_IndexUnchanged = true;
1069
0
    return true;
1070
0
  }
1071
1072
  /*
1073
   * Need to pass only one bms to expression_tree_walker helper function.
1074
   * Avoid allocating memory in common case where there are no extra cols.
1075
   */
1076
0
  if (!extraUpdatedCols)
1077
0
    allUpdatedCols = updatedCols;
1078
0
  else
1079
0
    allUpdatedCols = bms_union(updatedCols, extraUpdatedCols);
1080
1081
  /*
1082
   * We have to work slightly harder in the event of indexed expressions,
1083
   * but the principle is the same as before: try to find columns (Vars,
1084
   * actually) that overlap with known-updated columns.
1085
   *
1086
   * If we find any matching Vars, don't pass hint for index.  Otherwise
1087
   * pass hint.
1088
   */
1089
0
  idxExprs = RelationGetIndexExpressions(indexRelation);
1090
0
  hasexpression = index_expression_changed_walker((Node *) idxExprs,
1091
0
                          allUpdatedCols);
1092
0
  list_free(idxExprs);
1093
0
  if (extraUpdatedCols)
1094
0
    bms_free(allUpdatedCols);
1095
1096
0
  if (hasexpression)
1097
0
  {
1098
0
    indexInfo->ii_IndexUnchanged = false;
1099
0
    return false;
1100
0
  }
1101
1102
  /*
1103
   * Deliberately don't consider index predicates.  We should even give the
1104
   * hint when result rel's "updated tuple" has no corresponding index
1105
   * tuple, which is possible with a partial index (provided the usual
1106
   * conditions are met).
1107
   */
1108
0
  indexInfo->ii_IndexUnchanged = true;
1109
0
  return true;
1110
0
}
1111
1112
/*
1113
 * Indexed expression helper for index_unchanged_by_update().
1114
 *
1115
 * Returns true when Var that appears within allUpdatedCols located.
1116
 */
1117
static bool
1118
index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols)
1119
0
{
1120
0
  if (node == NULL)
1121
0
    return false;
1122
1123
0
  if (IsA(node, Var))
1124
0
  {
1125
0
    Var      *var = (Var *) node;
1126
1127
0
    if (bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber,
1128
0
              allUpdatedCols))
1129
0
    {
1130
      /* Var was updated -- indicates that we should not hint */
1131
0
      return true;
1132
0
    }
1133
1134
    /* Still haven't found a reason to not pass the hint */
1135
0
    return false;
1136
0
  }
1137
1138
0
  return expression_tree_walker(node, index_expression_changed_walker,
1139
0
                  allUpdatedCols);
1140
0
}
1141
1142
/*
1143
 * ExecWithoutOverlapsNotEmpty - raise an error if the tuple has an empty
1144
 * range or multirange in the given attribute.
1145
 */
1146
static void
1147
ExecWithoutOverlapsNotEmpty(Relation rel, NameData attname, Datum attval, char typtype, Oid atttypid)
1148
0
{
1149
0
  bool    isempty;
1150
0
  RangeType  *r;
1151
0
  MultirangeType *mr;
1152
1153
0
  switch (typtype)
1154
0
  {
1155
0
    case TYPTYPE_RANGE:
1156
0
      r = DatumGetRangeTypeP(attval);
1157
0
      isempty = RangeIsEmpty(r);
1158
0
      break;
1159
0
    case TYPTYPE_MULTIRANGE:
1160
0
      mr = DatumGetMultirangeTypeP(attval);
1161
0
      isempty = MultirangeIsEmpty(mr);
1162
0
      break;
1163
0
    default:
1164
0
      elog(ERROR, "WITHOUT OVERLAPS column \"%s\" is not a range or multirange",
1165
0
         NameStr(attname));
1166
0
  }
1167
1168
  /* Report a CHECK_VIOLATION */
1169
0
  if (isempty)
1170
0
    ereport(ERROR,
1171
0
        (errcode(ERRCODE_CHECK_VIOLATION),
1172
0
         errmsg("empty WITHOUT OVERLAPS value found in column \"%s\" in relation \"%s\"",
1173
0
            NameStr(attname), RelationGetRelationName(rel))));
1174
0
}