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-2019, 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 | Datum *values, bool *isnull, |
131 | EState *estate, bool newIndex, |
132 | CEOUC_WAIT_MODE waitMode, |
133 | bool errorOK, |
134 | ItemPointer conflictTid); |
135 | |
136 | static bool index_recheck_constraint(Relation index, Oid *constr_procs, |
137 | Datum *existing_values, bool *existing_isnull, |
138 | Datum *new_values); |
139 | |
140 | /* ---------------------------------------------------------------- |
141 | * ExecOpenIndices |
142 | * |
143 | * Find the indices associated with a result relation, open them, |
144 | * and save information about them in the result ResultRelInfo. |
145 | * |
146 | * At entry, caller has already opened and locked |
147 | * resultRelInfo->ri_RelationDesc. |
148 | * ---------------------------------------------------------------- |
149 | */ |
150 | void |
151 | ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative) |
152 | { |
153 | Relation resultRelation = resultRelInfo->ri_RelationDesc; |
154 | List *indexoidlist; |
155 | ListCell *l; |
156 | int len, |
157 | i; |
158 | RelationPtr relationDescs; |
159 | IndexInfo **indexInfoArray; |
160 | |
161 | resultRelInfo->ri_NumIndices = 0; |
162 | |
163 | /* fast path if no indexes */ |
164 | if (!RelationGetForm(resultRelation)->relhasindex) |
165 | return; |
166 | |
167 | /* |
168 | * Get cached list of index OIDs |
169 | */ |
170 | indexoidlist = RelationGetIndexList(resultRelation); |
171 | len = list_length(indexoidlist); |
172 | if (len == 0) |
173 | return; |
174 | |
175 | /* |
176 | * allocate space for result arrays |
177 | */ |
178 | relationDescs = (RelationPtr) palloc(len * sizeof(Relation)); |
179 | indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *)); |
180 | |
181 | resultRelInfo->ri_NumIndices = len; |
182 | resultRelInfo->ri_IndexRelationDescs = relationDescs; |
183 | resultRelInfo->ri_IndexRelationInfo = indexInfoArray; |
184 | |
185 | /* |
186 | * For each index, open the index relation and save pg_index info. We |
187 | * acquire RowExclusiveLock, signifying we will update the index. |
188 | * |
189 | * Note: we do this even if the index is not indisready; it's not worth |
190 | * the trouble to optimize for the case where it isn't. |
191 | */ |
192 | i = 0; |
193 | foreach(l, indexoidlist) |
194 | { |
195 | Oid indexOid = lfirst_oid(l); |
196 | Relation indexDesc; |
197 | IndexInfo *ii; |
198 | |
199 | indexDesc = index_open(indexOid, RowExclusiveLock); |
200 | |
201 | /* extract index key information from the index's pg_index info */ |
202 | ii = BuildIndexInfo(indexDesc); |
203 | |
204 | /* |
205 | * If the indexes are to be used for speculative insertion, add extra |
206 | * information required by unique index entries. |
207 | */ |
208 | if (speculative && ii->ii_Unique) |
209 | BuildSpeculativeIndexInfo(indexDesc, ii); |
210 | |
211 | relationDescs[i] = indexDesc; |
212 | indexInfoArray[i] = ii; |
213 | i++; |
214 | } |
215 | |
216 | list_free(indexoidlist); |
217 | } |
218 | |
219 | /* ---------------------------------------------------------------- |
220 | * ExecCloseIndices |
221 | * |
222 | * Close the index relations stored in resultRelInfo |
223 | * ---------------------------------------------------------------- |
224 | */ |
225 | void |
226 | ExecCloseIndices(ResultRelInfo *resultRelInfo) |
227 | { |
228 | int i; |
229 | int numIndices; |
230 | RelationPtr indexDescs; |
231 | |
232 | numIndices = resultRelInfo->ri_NumIndices; |
233 | indexDescs = resultRelInfo->ri_IndexRelationDescs; |
234 | |
235 | for (i = 0; i < numIndices; i++) |
236 | { |
237 | if (indexDescs[i] == NULL) |
238 | continue; /* shouldn't happen? */ |
239 | |
240 | /* Drop lock acquired by ExecOpenIndices */ |
241 | index_close(indexDescs[i], RowExclusiveLock); |
242 | } |
243 | |
244 | /* |
245 | * XXX should free indexInfo array here too? Currently we assume that |
246 | * such stuff will be cleaned up automatically in FreeExecutorState. |
247 | */ |
248 | } |
249 | |
250 | /* ---------------------------------------------------------------- |
251 | * ExecInsertIndexTuples |
252 | * |
253 | * This routine takes care of inserting index tuples |
254 | * into all the relations indexing the result relation |
255 | * when a heap tuple is inserted into the result relation. |
256 | * |
257 | * Unique and exclusion constraints are enforced at the same |
258 | * time. This returns a list of index OIDs for any unique or |
259 | * exclusion constraints that are deferred and that had |
260 | * potential (unconfirmed) conflicts. (if noDupErr == true, |
261 | * the same is done for non-deferred constraints, but report |
262 | * if conflict was speculative or deferred conflict to caller) |
263 | * |
264 | * If 'arbiterIndexes' is nonempty, noDupErr applies only to |
265 | * those indexes. NIL means noDupErr applies to all indexes. |
266 | * |
267 | * CAUTION: this must not be called for a HOT update. |
268 | * We can't defend against that here for lack of info. |
269 | * Should we change the API to make it safer? |
270 | * ---------------------------------------------------------------- |
271 | */ |
272 | List * |
273 | ExecInsertIndexTuples(TupleTableSlot *slot, |
274 | EState *estate, |
275 | bool noDupErr, |
276 | bool *specConflict, |
277 | List *arbiterIndexes) |
278 | { |
279 | ItemPointer tupleid = &slot->tts_tid; |
280 | List *result = NIL; |
281 | ResultRelInfo *resultRelInfo; |
282 | int i; |
283 | int numIndices; |
284 | RelationPtr relationDescs; |
285 | Relation heapRelation; |
286 | IndexInfo **indexInfoArray; |
287 | ExprContext *econtext; |
288 | Datum values[INDEX_MAX_KEYS]; |
289 | bool isnull[INDEX_MAX_KEYS]; |
290 | |
291 | Assert(ItemPointerIsValid(tupleid)); |
292 | |
293 | /* |
294 | * Get information from the result relation info structure. |
295 | */ |
296 | resultRelInfo = estate->es_result_relation_info; |
297 | numIndices = resultRelInfo->ri_NumIndices; |
298 | relationDescs = resultRelInfo->ri_IndexRelationDescs; |
299 | indexInfoArray = resultRelInfo->ri_IndexRelationInfo; |
300 | heapRelation = resultRelInfo->ri_RelationDesc; |
301 | |
302 | /* Sanity check: slot must belong to the same rel as the resultRelInfo. */ |
303 | Assert(slot->tts_tableOid == RelationGetRelid(heapRelation)); |
304 | |
305 | /* |
306 | * We will use the EState's per-tuple context for evaluating predicates |
307 | * and index expressions (creating it if it's not already there). |
308 | */ |
309 | econtext = GetPerTupleExprContext(estate); |
310 | |
311 | /* Arrange for econtext's scan tuple to be the tuple under test */ |
312 | econtext->ecxt_scantuple = slot; |
313 | |
314 | /* |
315 | * for each index, form and insert the index tuple |
316 | */ |
317 | for (i = 0; i < numIndices; i++) |
318 | { |
319 | Relation indexRelation = relationDescs[i]; |
320 | IndexInfo *indexInfo; |
321 | bool applyNoDupErr; |
322 | IndexUniqueCheck checkUnique; |
323 | bool satisfiesConstraint; |
324 | |
325 | if (indexRelation == NULL) |
326 | continue; |
327 | |
328 | indexInfo = indexInfoArray[i]; |
329 | |
330 | /* If the index is marked as read-only, ignore it */ |
331 | if (!indexInfo->ii_ReadyForInserts) |
332 | continue; |
333 | |
334 | /* Check for partial index */ |
335 | if (indexInfo->ii_Predicate != NIL) |
336 | { |
337 | ExprState *predicate; |
338 | |
339 | /* |
340 | * If predicate state not set up yet, create it (in the estate's |
341 | * per-query context) |
342 | */ |
343 | predicate = indexInfo->ii_PredicateState; |
344 | if (predicate == NULL) |
345 | { |
346 | predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate); |
347 | indexInfo->ii_PredicateState = predicate; |
348 | } |
349 | |
350 | /* Skip this index-update if the predicate isn't satisfied */ |
351 | if (!ExecQual(predicate, econtext)) |
352 | continue; |
353 | } |
354 | |
355 | /* |
356 | * FormIndexDatum fills in its values and isnull parameters with the |
357 | * appropriate values for the column(s) of the index. |
358 | */ |
359 | FormIndexDatum(indexInfo, |
360 | slot, |
361 | estate, |
362 | values, |
363 | isnull); |
364 | |
365 | /* Check whether to apply noDupErr to this index */ |
366 | applyNoDupErr = noDupErr && |
367 | (arbiterIndexes == NIL || |
368 | list_member_oid(arbiterIndexes, |
369 | indexRelation->rd_index->indexrelid)); |
370 | |
371 | /* |
372 | * The index AM does the actual insertion, plus uniqueness checking. |
373 | * |
374 | * For an immediate-mode unique index, we just tell the index AM to |
375 | * throw error if not unique. |
376 | * |
377 | * For a deferrable unique index, we tell the index AM to just detect |
378 | * possible non-uniqueness, and we add the index OID to the result |
379 | * list if further checking is needed. |
380 | * |
381 | * For a speculative insertion (used by INSERT ... ON CONFLICT), do |
382 | * the same as for a deferrable unique index. |
383 | */ |
384 | if (!indexRelation->rd_index->indisunique) |
385 | checkUnique = UNIQUE_CHECK_NO; |
386 | else if (applyNoDupErr) |
387 | checkUnique = UNIQUE_CHECK_PARTIAL; |
388 | else if (indexRelation->rd_index->indimmediate) |
389 | checkUnique = UNIQUE_CHECK_YES; |
390 | else |
391 | checkUnique = UNIQUE_CHECK_PARTIAL; |
392 | |
393 | satisfiesConstraint = |
394 | index_insert(indexRelation, /* index relation */ |
395 | values, /* array of index Datums */ |
396 | isnull, /* null flags */ |
397 | tupleid, /* tid of heap tuple */ |
398 | heapRelation, /* heap relation */ |
399 | checkUnique, /* type of uniqueness check to do */ |
400 | indexInfo); /* index AM may need this */ |
401 | |
402 | /* |
403 | * If the index has an associated exclusion constraint, check that. |
404 | * This is simpler than the process for uniqueness checks since we |
405 | * always insert first and then check. If the constraint is deferred, |
406 | * we check now anyway, but don't throw error on violation or wait for |
407 | * a conclusive outcome from a concurrent insertion; instead we'll |
408 | * queue a recheck event. Similarly, noDupErr callers (speculative |
409 | * inserters) will recheck later, and wait for a conclusive outcome |
410 | * then. |
411 | * |
412 | * An index for an exclusion constraint can't also be UNIQUE (not an |
413 | * essential property, we just don't allow it in the grammar), so no |
414 | * need to preserve the prior state of satisfiesConstraint. |
415 | */ |
416 | if (indexInfo->ii_ExclusionOps != NULL) |
417 | { |
418 | bool violationOK; |
419 | CEOUC_WAIT_MODE waitMode; |
420 | |
421 | if (applyNoDupErr) |
422 | { |
423 | violationOK = true; |
424 | waitMode = CEOUC_LIVELOCK_PREVENTING_WAIT; |
425 | } |
426 | else if (!indexRelation->rd_index->indimmediate) |
427 | { |
428 | violationOK = true; |
429 | waitMode = CEOUC_NOWAIT; |
430 | } |
431 | else |
432 | { |
433 | violationOK = false; |
434 | waitMode = CEOUC_WAIT; |
435 | } |
436 | |
437 | satisfiesConstraint = |
438 | check_exclusion_or_unique_constraint(heapRelation, |
439 | indexRelation, indexInfo, |
440 | tupleid, values, isnull, |
441 | estate, false, |
442 | waitMode, violationOK, NULL); |
443 | } |
444 | |
445 | if ((checkUnique == UNIQUE_CHECK_PARTIAL || |
446 | indexInfo->ii_ExclusionOps != NULL) && |
447 | !satisfiesConstraint) |
448 | { |
449 | /* |
450 | * The tuple potentially violates the uniqueness or exclusion |
451 | * constraint, so make a note of the index so that we can re-check |
452 | * it later. Speculative inserters are told if there was a |
453 | * speculative conflict, since that always requires a restart. |
454 | */ |
455 | result = lappend_oid(result, RelationGetRelid(indexRelation)); |
456 | if (indexRelation->rd_index->indimmediate && specConflict) |
457 | *specConflict = true; |
458 | } |
459 | } |
460 | |
461 | return result; |
462 | } |
463 | |
464 | /* ---------------------------------------------------------------- |
465 | * ExecCheckIndexConstraints |
466 | * |
467 | * This routine checks if a tuple violates any unique or |
468 | * exclusion constraints. Returns true if there is no conflict. |
469 | * Otherwise returns false, and the TID of the conflicting |
470 | * tuple is returned in *conflictTid. |
471 | * |
472 | * If 'arbiterIndexes' is given, only those indexes are checked. |
473 | * NIL means all indexes. |
474 | * |
475 | * Note that this doesn't lock the values in any way, so it's |
476 | * possible that a conflicting tuple is inserted immediately |
477 | * after this returns. But this can be used for a pre-check |
478 | * before insertion. |
479 | * ---------------------------------------------------------------- |
480 | */ |
481 | bool |
482 | ExecCheckIndexConstraints(TupleTableSlot *slot, |
483 | EState *estate, ItemPointer conflictTid, |
484 | List *arbiterIndexes) |
485 | { |
486 | ResultRelInfo *resultRelInfo; |
487 | int i; |
488 | int numIndices; |
489 | RelationPtr relationDescs; |
490 | Relation heapRelation; |
491 | IndexInfo **indexInfoArray; |
492 | ExprContext *econtext; |
493 | Datum values[INDEX_MAX_KEYS]; |
494 | bool isnull[INDEX_MAX_KEYS]; |
495 | ItemPointerData invalidItemPtr; |
496 | bool checkedIndex = false; |
497 | |
498 | ItemPointerSetInvalid(conflictTid); |
499 | ItemPointerSetInvalid(&invalidItemPtr); |
500 | |
501 | /* |
502 | * Get information from the result relation info structure. |
503 | */ |
504 | resultRelInfo = estate->es_result_relation_info; |
505 | numIndices = resultRelInfo->ri_NumIndices; |
506 | relationDescs = resultRelInfo->ri_IndexRelationDescs; |
507 | indexInfoArray = resultRelInfo->ri_IndexRelationInfo; |
508 | heapRelation = resultRelInfo->ri_RelationDesc; |
509 | |
510 | /* |
511 | * We will use the EState's per-tuple context for evaluating predicates |
512 | * and index expressions (creating it if it's not already there). |
513 | */ |
514 | econtext = GetPerTupleExprContext(estate); |
515 | |
516 | /* Arrange for econtext's scan tuple to be the tuple under test */ |
517 | econtext->ecxt_scantuple = slot; |
518 | |
519 | /* |
520 | * For each index, form index tuple and check if it satisfies the |
521 | * constraint. |
522 | */ |
523 | for (i = 0; i < numIndices; i++) |
524 | { |
525 | Relation indexRelation = relationDescs[i]; |
526 | IndexInfo *indexInfo; |
527 | bool satisfiesConstraint; |
528 | |
529 | if (indexRelation == NULL) |
530 | continue; |
531 | |
532 | indexInfo = indexInfoArray[i]; |
533 | |
534 | if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps) |
535 | continue; |
536 | |
537 | /* If the index is marked as read-only, ignore it */ |
538 | if (!indexInfo->ii_ReadyForInserts) |
539 | continue; |
540 | |
541 | /* When specific arbiter indexes requested, only examine them */ |
542 | if (arbiterIndexes != NIL && |
543 | !list_member_oid(arbiterIndexes, |
544 | indexRelation->rd_index->indexrelid)) |
545 | continue; |
546 | |
547 | if (!indexRelation->rd_index->indimmediate) |
548 | ereport(ERROR, |
549 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
550 | errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters" ), |
551 | errtableconstraint(heapRelation, |
552 | RelationGetRelationName(indexRelation)))); |
553 | |
554 | checkedIndex = true; |
555 | |
556 | /* Check for partial index */ |
557 | if (indexInfo->ii_Predicate != NIL) |
558 | { |
559 | ExprState *predicate; |
560 | |
561 | /* |
562 | * If predicate state not set up yet, create it (in the estate's |
563 | * per-query context) |
564 | */ |
565 | predicate = indexInfo->ii_PredicateState; |
566 | if (predicate == NULL) |
567 | { |
568 | predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate); |
569 | indexInfo->ii_PredicateState = predicate; |
570 | } |
571 | |
572 | /* Skip this index-update if the predicate isn't satisfied */ |
573 | if (!ExecQual(predicate, econtext)) |
574 | continue; |
575 | } |
576 | |
577 | /* |
578 | * FormIndexDatum fills in its values and isnull parameters with the |
579 | * appropriate values for the column(s) of the index. |
580 | */ |
581 | FormIndexDatum(indexInfo, |
582 | slot, |
583 | estate, |
584 | values, |
585 | isnull); |
586 | |
587 | satisfiesConstraint = |
588 | check_exclusion_or_unique_constraint(heapRelation, indexRelation, |
589 | indexInfo, &invalidItemPtr, |
590 | values, isnull, estate, false, |
591 | CEOUC_WAIT, true, |
592 | conflictTid); |
593 | if (!satisfiesConstraint) |
594 | return false; |
595 | } |
596 | |
597 | if (arbiterIndexes != NIL && !checkedIndex) |
598 | elog(ERROR, "unexpected failure to find arbiter index" ); |
599 | |
600 | return true; |
601 | } |
602 | |
603 | /* |
604 | * Check for violation of an exclusion or unique constraint |
605 | * |
606 | * heap: the table containing the new tuple |
607 | * index: the index supporting the constraint |
608 | * indexInfo: info about the index, including the exclusion properties |
609 | * tupleid: heap TID of the new tuple we have just inserted (invalid if we |
610 | * haven't inserted a new tuple yet) |
611 | * values, isnull: the *index* column values computed for the new tuple |
612 | * estate: an EState we can do evaluation in |
613 | * newIndex: if true, we are trying to build a new index (this affects |
614 | * only the wording of error messages) |
615 | * waitMode: whether to wait for concurrent inserters/deleters |
616 | * violationOK: if true, don't throw error for violation |
617 | * conflictTid: if not-NULL, the TID of the conflicting tuple is returned here |
618 | * |
619 | * Returns true if OK, false if actual or potential violation |
620 | * |
621 | * 'waitMode' determines what happens if a conflict is detected with a tuple |
622 | * that was inserted or deleted by a transaction that's still running. |
623 | * CEOUC_WAIT means that we wait for the transaction to commit, before |
624 | * throwing an error or returning. CEOUC_NOWAIT means that we report the |
625 | * violation immediately; so the violation is only potential, and the caller |
626 | * must recheck sometime later. This behavior is convenient for deferred |
627 | * exclusion checks; we need not bother queuing a deferred event if there is |
628 | * definitely no conflict at insertion time. |
629 | * |
630 | * CEOUC_LIVELOCK_PREVENTING_WAIT is like CEOUC_NOWAIT, but we will sometimes |
631 | * wait anyway, to prevent livelocking if two transactions try inserting at |
632 | * the same time. This is used with speculative insertions, for INSERT ON |
633 | * CONFLICT statements. (See notes in file header) |
634 | * |
635 | * If violationOK is true, we just report the potential or actual violation to |
636 | * the caller by returning 'false'. Otherwise we throw a descriptive error |
637 | * message here. When violationOK is false, a false result is impossible. |
638 | * |
639 | * Note: The indexam is normally responsible for checking unique constraints, |
640 | * so this normally only needs to be used for exclusion constraints. But this |
641 | * function is also called when doing a "pre-check" for conflicts on a unique |
642 | * constraint, when doing speculative insertion. Caller may use the returned |
643 | * conflict TID to take further steps. |
644 | */ |
645 | static bool |
646 | check_exclusion_or_unique_constraint(Relation heap, Relation index, |
647 | IndexInfo *indexInfo, |
648 | ItemPointer tupleid, |
649 | Datum *values, bool *isnull, |
650 | EState *estate, bool newIndex, |
651 | CEOUC_WAIT_MODE waitMode, |
652 | bool violationOK, |
653 | ItemPointer conflictTid) |
654 | { |
655 | Oid *constr_procs; |
656 | uint16 *constr_strats; |
657 | Oid *index_collations = index->rd_indcollation; |
658 | int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index); |
659 | IndexScanDesc index_scan; |
660 | ScanKeyData scankeys[INDEX_MAX_KEYS]; |
661 | SnapshotData DirtySnapshot; |
662 | int i; |
663 | bool conflict; |
664 | bool found_self; |
665 | ExprContext *econtext; |
666 | TupleTableSlot *existing_slot; |
667 | TupleTableSlot *save_scantuple; |
668 | |
669 | if (indexInfo->ii_ExclusionOps) |
670 | { |
671 | constr_procs = indexInfo->ii_ExclusionProcs; |
672 | constr_strats = indexInfo->ii_ExclusionStrats; |
673 | } |
674 | else |
675 | { |
676 | constr_procs = indexInfo->ii_UniqueProcs; |
677 | constr_strats = indexInfo->ii_UniqueStrats; |
678 | } |
679 | |
680 | /* |
681 | * If any of the input values are NULL, the constraint check is assumed to |
682 | * pass (i.e., we assume the operators are strict). |
683 | */ |
684 | for (i = 0; i < indnkeyatts; i++) |
685 | { |
686 | if (isnull[i]) |
687 | return true; |
688 | } |
689 | |
690 | /* |
691 | * Search the tuples that are in the index for any violations, including |
692 | * tuples that aren't visible yet. |
693 | */ |
694 | InitDirtySnapshot(DirtySnapshot); |
695 | |
696 | for (i = 0; i < indnkeyatts; i++) |
697 | { |
698 | ScanKeyEntryInitialize(&scankeys[i], |
699 | 0, |
700 | i + 1, |
701 | constr_strats[i], |
702 | InvalidOid, |
703 | index_collations[i], |
704 | constr_procs[i], |
705 | values[i]); |
706 | } |
707 | |
708 | /* |
709 | * Need a TupleTableSlot to put existing tuples in. |
710 | * |
711 | * To use FormIndexDatum, we have to make the econtext's scantuple point |
712 | * to this slot. Be sure to save and restore caller's value for |
713 | * scantuple. |
714 | */ |
715 | existing_slot = table_slot_create(heap, NULL); |
716 | |
717 | econtext = GetPerTupleExprContext(estate); |
718 | save_scantuple = econtext->ecxt_scantuple; |
719 | econtext->ecxt_scantuple = existing_slot; |
720 | |
721 | /* |
722 | * May have to restart scan from this point if a potential conflict is |
723 | * found. |
724 | */ |
725 | retry: |
726 | conflict = false; |
727 | found_self = false; |
728 | index_scan = index_beginscan(heap, index, &DirtySnapshot, indnkeyatts, 0); |
729 | index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0); |
730 | |
731 | while (index_getnext_slot(index_scan, ForwardScanDirection, existing_slot)) |
732 | { |
733 | TransactionId xwait; |
734 | XLTW_Oper reason_wait; |
735 | Datum existing_values[INDEX_MAX_KEYS]; |
736 | bool existing_isnull[INDEX_MAX_KEYS]; |
737 | char *error_new; |
738 | char *error_existing; |
739 | |
740 | /* |
741 | * Ignore the entry for the tuple we're trying to check. |
742 | */ |
743 | if (ItemPointerIsValid(tupleid) && |
744 | ItemPointerEquals(tupleid, &existing_slot->tts_tid)) |
745 | { |
746 | if (found_self) /* should not happen */ |
747 | elog(ERROR, "found self tuple multiple times in index \"%s\"" , |
748 | RelationGetRelationName(index)); |
749 | found_self = true; |
750 | continue; |
751 | } |
752 | |
753 | /* |
754 | * Extract the index column values and isnull flags from the existing |
755 | * tuple. |
756 | */ |
757 | FormIndexDatum(indexInfo, existing_slot, estate, |
758 | existing_values, existing_isnull); |
759 | |
760 | /* If lossy indexscan, must recheck the condition */ |
761 | if (index_scan->xs_recheck) |
762 | { |
763 | if (!index_recheck_constraint(index, |
764 | constr_procs, |
765 | existing_values, |
766 | existing_isnull, |
767 | values)) |
768 | continue; /* tuple doesn't actually match, so no |
769 | * conflict */ |
770 | } |
771 | |
772 | /* |
773 | * At this point we have either a conflict or a potential conflict. |
774 | * |
775 | * If an in-progress transaction is affecting the visibility of this |
776 | * tuple, we need to wait for it to complete and then recheck (unless |
777 | * the caller requested not to). For simplicity we do rechecking by |
778 | * just restarting the whole scan --- this case probably doesn't |
779 | * happen often enough to be worth trying harder, and anyway we don't |
780 | * want to hold any index internal locks while waiting. |
781 | */ |
782 | xwait = TransactionIdIsValid(DirtySnapshot.xmin) ? |
783 | DirtySnapshot.xmin : DirtySnapshot.xmax; |
784 | |
785 | if (TransactionIdIsValid(xwait) && |
786 | (waitMode == CEOUC_WAIT || |
787 | (waitMode == CEOUC_LIVELOCK_PREVENTING_WAIT && |
788 | DirtySnapshot.speculativeToken && |
789 | TransactionIdPrecedes(GetCurrentTransactionId(), xwait)))) |
790 | { |
791 | reason_wait = indexInfo->ii_ExclusionOps ? |
792 | XLTW_RecheckExclusionConstr : XLTW_InsertIndex; |
793 | index_endscan(index_scan); |
794 | if (DirtySnapshot.speculativeToken) |
795 | SpeculativeInsertionWait(DirtySnapshot.xmin, |
796 | DirtySnapshot.speculativeToken); |
797 | else |
798 | XactLockTableWait(xwait, heap, |
799 | &existing_slot->tts_tid, reason_wait); |
800 | goto retry; |
801 | } |
802 | |
803 | /* |
804 | * We have a definite conflict (or a potential one, but the caller |
805 | * didn't want to wait). Return it to caller, or report it. |
806 | */ |
807 | if (violationOK) |
808 | { |
809 | conflict = true; |
810 | if (conflictTid) |
811 | *conflictTid = existing_slot->tts_tid; |
812 | break; |
813 | } |
814 | |
815 | error_new = BuildIndexValueDescription(index, values, isnull); |
816 | error_existing = BuildIndexValueDescription(index, existing_values, |
817 | existing_isnull); |
818 | if (newIndex) |
819 | ereport(ERROR, |
820 | (errcode(ERRCODE_EXCLUSION_VIOLATION), |
821 | errmsg("could not create exclusion constraint \"%s\"" , |
822 | RelationGetRelationName(index)), |
823 | error_new && error_existing ? |
824 | errdetail("Key %s conflicts with key %s." , |
825 | error_new, error_existing) : |
826 | errdetail("Key conflicts exist." ), |
827 | errtableconstraint(heap, |
828 | RelationGetRelationName(index)))); |
829 | else |
830 | ereport(ERROR, |
831 | (errcode(ERRCODE_EXCLUSION_VIOLATION), |
832 | errmsg("conflicting key value violates exclusion constraint \"%s\"" , |
833 | RelationGetRelationName(index)), |
834 | error_new && error_existing ? |
835 | errdetail("Key %s conflicts with existing key %s." , |
836 | error_new, error_existing) : |
837 | errdetail("Key conflicts with existing key." ), |
838 | errtableconstraint(heap, |
839 | RelationGetRelationName(index)))); |
840 | } |
841 | |
842 | index_endscan(index_scan); |
843 | |
844 | /* |
845 | * Ordinarily, at this point the search should have found the originally |
846 | * inserted tuple (if any), unless we exited the loop early because of |
847 | * conflict. However, it is possible to define exclusion constraints for |
848 | * which that wouldn't be true --- for instance, if the operator is <>. So |
849 | * we no longer complain if found_self is still false. |
850 | */ |
851 | |
852 | econtext->ecxt_scantuple = save_scantuple; |
853 | |
854 | ExecDropSingleTupleTableSlot(existing_slot); |
855 | |
856 | return !conflict; |
857 | } |
858 | |
859 | /* |
860 | * Check for violation of an exclusion constraint |
861 | * |
862 | * This is a dumbed down version of check_exclusion_or_unique_constraint |
863 | * for external callers. They don't need all the special modes. |
864 | */ |
865 | void |
866 | check_exclusion_constraint(Relation heap, Relation index, |
867 | IndexInfo *indexInfo, |
868 | ItemPointer tupleid, |
869 | Datum *values, bool *isnull, |
870 | EState *estate, bool newIndex) |
871 | { |
872 | (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid, |
873 | values, isnull, |
874 | estate, newIndex, |
875 | CEOUC_WAIT, false, NULL); |
876 | } |
877 | |
878 | /* |
879 | * Check existing tuple's index values to see if it really matches the |
880 | * exclusion condition against the new_values. Returns true if conflict. |
881 | */ |
882 | static bool |
883 | index_recheck_constraint(Relation index, Oid *constr_procs, |
884 | Datum *existing_values, bool *existing_isnull, |
885 | Datum *new_values) |
886 | { |
887 | int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index); |
888 | int i; |
889 | |
890 | for (i = 0; i < indnkeyatts; i++) |
891 | { |
892 | /* Assume the exclusion operators are strict */ |
893 | if (existing_isnull[i]) |
894 | return false; |
895 | |
896 | if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i], |
897 | index->rd_indcollation[i], |
898 | existing_values[i], |
899 | new_values[i]))) |
900 | return false; |
901 | } |
902 | |
903 | return true; |
904 | } |
905 | |