* ExecCheckTupleVisible -- verify tuple is visible * * It would not be consistent with guarantees of the higher isolation levels to * proceed with avoiding insertion (taking speculative insertion's alternative * path) on the basis of another tuple that is not visible to MVCC snapshot. * Check for the need to raise a serialization failure, and do so as necessary. */
| 267 | * Check for the need to raise a serialization failure, and do so as necessary. |
| 268 | */ |
| 269 | static void |
| 270 | ExecCheckTupleVisible(EState *estate, |
| 271 | Relation rel, |
| 272 | TupleTableSlot *slot) |
| 273 | { |
| 274 | if (!IsolationUsesXactSnapshot()) |
| 275 | return; |
| 276 | |
| 277 | if (!table_tuple_satisfies_snapshot(rel, slot, estate->es_snapshot)) |
| 278 | { |
| 279 | Datum xminDatum; |
| 280 | TransactionId xmin; |
| 281 | bool isnull; |
| 282 | |
| 283 | xminDatum = slot_getsysattr(slot, MinTransactionIdAttributeNumber, &isnull); |
| 284 | Assert(!isnull); |
| 285 | xmin = DatumGetTransactionId(xminDatum); |
| 286 | |
| 287 | /* |
| 288 | * We should not raise a serialization failure if the conflict is |
| 289 | * against a tuple inserted by our own transaction, even if it's not |
| 290 | * visible to our snapshot. (This would happen, for example, if |
| 291 | * conflicting keys are proposed for insertion in a single command.) |
| 292 | */ |
| 293 | if (!TransactionIdIsCurrentTransactionId(xmin)) |
| 294 | ereport(ERROR, |
| 295 | (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), |
| 296 | errmsg("could not serialize access due to concurrent update"))); |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | /* |
| 301 | * ExecCheckTIDVisible -- convenience variant of ExecCheckTupleVisible() |
no test coverage detected