| 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 | |