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