44#include "catalog/pg_database_d.h"
61 bool all_visible_cleared,
bool new_all_visible_cleared);
62#ifdef USE_ASSERT_CHECKING
63static void check_lock_if_inplace_updateable_rel(
Relation relation,
66static void check_inplace_rel_lock(
HeapTuple oldtup);
75 bool *have_tuple_lock);
151#define LOCKMODE_from_mxstatus(status) \
152 (tupleLockExtraInfo[TUPLOCK_from_mxstatus((status))].hwlock)
159#define LockTupleTuplock(rel, tup, mode) \
160 LockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock)
161#define UnlockTupleTuplock(rel, tup, mode) \
162 UnlockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock)
163#define ConditionalLockTupleTuplock(rel, tup, mode) \
164 ConditionalLockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock)
177} IndexDeletePrefetchState;
181#define BOTTOMUP_MAX_NBLOCKS 6
182#define BOTTOMUP_TOLERANCE_NBLOCKS 3
210#define TUPLOCK_from_mxstatus(status) \
211 (MultiXactStatusLock[(status)])
224 void *callback_private_data,
225 void *per_buffer_data)
262 void *callback_private_data,
263 void *per_buffer_data)
329 allow_strat = allow_sync =
false;
352 else if (keep_startblock)
424 Assert(startBlk == 0 || startBlk < scan->rs_nblocks);
440 bool all_visible,
bool check_serializable)
464 if (check_serializable)
466 &loctup, buffer, snapshot);
496 bool check_serializable;
551 if (
likely(!check_serializable))
553 block, lines,
true,
false);
556 block, lines,
true,
true);
560 if (
likely(!check_serializable))
562 block, lines,
false,
false);
565 block, lines,
false,
true);
725 *linesleft = *lineoff;
874 for (; linesleft > 0; linesleft--, lineoff += dir)
983 linesleft = scan->rs_ntuples;
989 for (; linesleft > 0; linesleft--, lineindex += dir)
994 Assert(lineindex <= scan->rs_ntuples);
995 lineoff = scan->rs_vistuples[lineindex];
1009 scan->rs_cindex = lineindex;
1099 if (parallel_scan != NULL)
1147 bool allow_strat,
bool allow_sync,
bool allow_pagemode)
1259 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1270 elog(
ERROR,
"unexpected heap_getnext call during logical decoding");
1627 bool *all_dead,
bool first_call)
1633 bool at_chain_start;
1640 *all_dead = first_call;
1644 at_chain_start = first_call;
1670 at_chain_start =
false;
1737 if (all_dead && *all_dead)
1755 at_chain_start =
false;
1995 bool all_visible_cleared =
false;
2043 all_visible_cleared =
true;
2094 if (all_visible_cleared)
2188 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2189 errmsg(
"cannot insert tuples in a parallel worker")));
2206 if (relation->
rd_rel->relkind != RELKIND_RELATION &&
2207 relation->
rd_rel->relkind != RELKIND_MATVIEW)
2230 for (
int i = done;
i < ntuples;
i++)
2234 if (page_avail < tup_sz)
2239 page_avail -= tup_sz;
2271 bool starting_with_empty_page =
false;
2273 int npages_used = 0;
2284 for (
i = 0;
i < ntuples;
i++)
2321 while (ndone < ntuples)
2324 bool all_visible_cleared =
false;
2325 bool all_frozen_set =
false;
2340 if (ndone == 0 || !starting_with_empty_page)
2359 npages - npages_used);
2365 all_frozen_set =
true;
2380 if (needwal && need_cids)
2383 for (nthispage = 1; ndone + nthispage < ntuples; nthispage++)
2385 HeapTuple heaptup = heaptuples[ndone + nthispage];
2396 if (needwal && need_cids)
2409 all_visible_cleared =
true;
2415 else if (all_frozen_set)
2432 char *scratchptr = scratch.
data;
2440 init = starting_with_empty_page;
2456 tupledata = scratchptr;
2459 Assert(!(all_visible_cleared && all_frozen_set));
2462 if (all_visible_cleared)
2473 for (
i = 0;
i < nthispage;
i++)
2495 scratchptr += datalen;
2497 totaldatalen = scratchptr - tupledata;
2498 Assert((scratchptr - scratch.
data) < BLCKSZ);
2500 if (need_tuple_data)
2508 if (ndone + nthispage == ntuples)
2521 if (need_tuple_data)
2598 for (
i = 0;
i < ntuples;
i++)
2603 for (
i = 0;
i < ntuples;
i++)
2604 slots[
i]->tts_tid = heaptuples[
i]->t_self;
2656 const uint16 interesting =
2659 if ((new_infomask & interesting) != (old_infomask & interesting))
2692 bool have_tuple_lock =
false;
2694 bool all_visible_cleared =
false;
2696 bool old_key_copied =
false;
2707 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2708 errmsg(
"cannot delete tuples during a parallel operation")));
2754 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2755 errmsg(
"attempted to delete invisible tuple")));
2781 bool current_is_member =
false;
2792 if (!current_is_member)
2872 if (result !=
TM_Ok)
2890 if (result !=
TM_Ok)
2899 if (have_tuple_lock)
2939 &new_xmax, &new_infomask, &new_infomask2);
2954 all_visible_cleared =
true;
2997 if (all_visible_cleared)
3004 xlrec.
xmax = new_xmax;
3006 if (old_key_tuple != NULL)
3008 if (relation->
rd_rel->relreplident == REPLICA_IDENTITY_FULL)
3022 if (old_key_tuple != NULL)
3031 old_key_tuple->
t_len
3056 if (relation->
rd_rel->relkind != RELKIND_RELATION &&
3057 relation->
rd_rel->relkind != RELKIND_MATVIEW)
3078 if (have_tuple_lock)
3083 if (old_key_tuple != NULL && old_key_copied)
3111 elog(
ERROR,
"tuple already updated by self");
3119 elog(
ERROR,
"tuple concurrently updated");
3123 elog(
ERROR,
"tuple concurrently deleted");
3127 elog(
ERROR,
"unrecognized heap_delete status: %u", result);
3161 bool old_key_copied =
false;
3172 bool have_tuple_lock =
false;
3174 bool use_hot_update =
false;
3175 bool summarized_update =
false;
3177 bool all_visible_cleared =
false;
3178 bool all_visible_cleared_new =
false;
3179 bool checked_lockers;
3180 bool locker_remains;
3181 bool id_has_external =
false;
3184 uint16 infomask_old_tuple,
3185 infomask2_old_tuple,
3187 infomask2_new_tuple;
3202 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
3203 errmsg(
"cannot update tuples during a parallel operation")));
3205#ifdef USE_ASSERT_CHECKING
3206 check_lock_if_inplace_updateable_rel(relation, otid, newtup);
3232 interesting_attrs = NULL;
3278 newtup, &id_has_external);
3323 checked_lockers =
false;
3324 locker_remains =
false;
3334 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3335 errmsg(
"attempted to update invisible tuple")));
3341 bool can_continue =
false;
3386 bool current_is_member =
false;
3389 *lockmode, ¤t_is_member))
3397 if (!current_is_member)
3405 checked_lockers =
true;
3406 locker_remains = remain != 0;
3453 can_continue =
true;
3461 checked_lockers =
true;
3462 locker_remains =
true;
3463 can_continue =
true;
3472 checked_lockers =
true;
3473 locker_remains =
true;
3474 can_continue =
true;
3487 checked_lockers =
true;
3503 can_continue =
true;
3515 if (result !=
TM_Ok)
3533 if (result !=
TM_Ok)
3542 if (have_tuple_lock)
3583 xid, *lockmode,
true,
3584 &xmax_old_tuple, &infomask_old_tuple,
3585 &infomask2_old_tuple);
3596 (checked_lockers && !locker_remains))
3604 infomask2_new_tuple = 0;
3617 &infomask2_new_tuple);
3622 infomask2_new_tuple = 0;
3655 if (relation->
rd_rel->relkind != RELKIND_RELATION &&
3656 relation->
rd_rel->relkind != RELKIND_MATVIEW)
3672 if (need_toast || newtupsize > pagefree)
3675 uint16 infomask_lock_old_tuple,
3676 infomask2_lock_old_tuple;
3677 bool cleared_all_frozen =
false;
3700 xid, *lockmode,
false,
3701 &xmax_lock_old_tuple, &infomask_lock_old_tuple,
3702 &infomask2_lock_old_tuple);
3731 cleared_all_frozen =
true;
3744 xlrec.
xmax = xmax_lock_old_tuple;
3799 if (newtupsize > pagefree)
3804 &vmbuffer_new, &vmbuffer,
3816 if (newtupsize > pagefree ||
3864 if (newbuf == buffer)
3873 use_hot_update =
true;
3883 summarized_update =
true;
3957 all_visible_cleared =
true;
3964 all_visible_cleared_new =
true;
3970 if (newbuf != buffer)
3990 newbuf, &oldtup, heaptup,
3992 all_visible_cleared,
3993 all_visible_cleared_new);
3994 if (newbuf != buffer)
4003 if (newbuf != buffer)
4018 if (newbuf != buffer)
4029 if (have_tuple_lock)
4038 if (heaptup != newtup)
4052 if (summarized_update)
4058 *update_indexes =
TU_All;
4060 if (old_key_tuple != NULL && old_key_copied)
4073#ifdef USE_ASSERT_CHECKING
4079check_lock_if_inplace_updateable_rel(
Relation relation,
4086 case RelationRelationId:
4087 case DatabaseRelationId:
4107 case RelationRelationId:
4111 Oid relid = classForm->oid;
4120 if (classForm->relkind == RELKIND_INDEX)
4133 "missing lock for relation \"%s\" (OID %u, relkind %c) @ TID (%u,%u)",
4141 case DatabaseRelationId:
4147 "missing lock on database \"%s\" (OID %u) @ TID (%u,%u)",
4165 Oid relid = classForm->oid;
4174 if (classForm->relkind == RELKIND_INDEX)
4186 "missing lock for relation \"%s\" (OID %u, relkind %c) @ TID (%u,%u)",
4201 bool isnull1,
bool isnull2)
4207 if (isnull1 != isnull2)
4234 Assert(attrnum <= tupdesc->natts);
4302 value1 =
heap_getattr(oldtup, attrnum, tupdesc, &isnull1);
4303 value2 =
heap_getattr(newtup, attrnum, tupdesc, &isnull2);
4306 value2, isnull1, isnull2))
4316 if (attrnum < 0 || isnull1 ||
4326 *has_external =
true;
4351 &tmfd, &lockmode, update_indexes);
4356 elog(
ERROR,
"tuple already updated by self");
4364 elog(
ERROR,
"tuple concurrently updated");
4368 elog(
ERROR,
"tuple concurrently deleted");
4372 elog(
ERROR,
"unrecognized heap_update status: %u", result);
4393 is_update ?
"true" :
"false");
4432 bool follow_updates,
4446 bool first_time =
true;
4447 bool skip_tuple_lock =
false;
4448 bool have_tuple_lock =
false;
4449 bool cleared_all_frozen =
false;
4536 for (
i = 0;
i < nmembers;
i++)
4561 skip_tuple_lock =
true;
4610 require_sleep =
true;
4644 if (follow_updates && updated)
4675 require_sleep =
false;
4704 require_sleep =
false;
4730 require_sleep =
false;
4743 require_sleep =
false;
4769 require_sleep =
false;
4788 else if (require_sleep)
4800 if (!skip_tuple_lock &&
4820 elog(
ERROR,
"invalid lock mode in heap_lock_tuple");
4823 switch (wait_policy)
4831 status, infomask, relation,
4842 status, infomask, relation,
4845 (
errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4846 errmsg(
"could not obtain lock on row in relation \"%s\"",
4865 switch (wait_policy)
4883 (
errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4884 errmsg(
"could not obtain lock on row in relation \"%s\"",
4940 if (!require_sleep ||
4952 if (result !=
TM_Ok)
5014 &xid, &new_infomask, &new_infomask2);
5050 cleared_all_frozen =
true;
5109 if (have_tuple_lock)
5131 if (*have_tuple_lock)
5134 switch (wait_policy)
5148 (
errcode(ERRCODE_LOCK_NOT_AVAILABLE),
5149 errmsg(
"could not obtain lock on row in relation \"%s\"",
5153 *have_tuple_lock =
true;
5181 uint16 *result_infomask2)
5204 new_xmax = add_to_xmax;
5214 new_xmax = add_to_xmax;
5218 new_xmax = add_to_xmax;
5222 new_xmax = add_to_xmax;
5226 new_xmax = add_to_xmax;
5255 old_infomask &= ~HEAP_XMAX_IS_MULTI;
5282 old_infomask &= ~HEAP_XMAX_IS_MULTI;
5350 elog(
WARNING,
"LOCK_ONLY found for Xid in progress %u", xmax);
5352 old_infomask &= ~HEAP_XMAX_LOCK_ONLY;