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