44 #include "catalog/pg_database_d.h"
61 bool all_visible_cleared,
bool new_all_visible_cleared);
62 #ifdef USE_ASSERT_CHECKING
63 static void check_lock_if_inplace_updateable_rel(
Relation relation,
66 static 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)
422 Assert(startBlk == 0 || startBlk < scan->rs_nblocks);
438 bool all_visible,
bool check_serializable)
462 if (check_serializable)
464 &loctup, buffer, snapshot);
494 bool check_serializable;
549 if (
likely(!check_serializable))
551 block, lines,
true,
false);
554 block, lines,
true,
true);
558 if (
likely(!check_serializable))
560 block, lines,
false,
false);
563 block, lines,
false,
true);
723 *linesleft = *lineoff;
872 for (; linesleft > 0; linesleft--, lineoff += dir)
981 linesleft = scan->rs_ntuples;
987 for (; linesleft > 0; linesleft--, lineindex += dir)
992 lineoff = scan->rs_vistuples[lineindex];
1006 scan->rs_cindex = lineindex;
1096 if (parallel_scan != NULL)
1144 bool allow_strat,
bool allow_sync,
bool allow_pagemode)
1256 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1267 elog(
ERROR,
"unexpected heap_getnext call during logical decoding");
1624 bool *all_dead,
bool first_call)
1630 bool at_chain_start;
1637 *all_dead = first_call;
1641 at_chain_start = first_call;
1667 at_chain_start =
false;
1734 if (all_dead && *all_dead)
1752 at_chain_start =
false;
1992 bool all_visible_cleared =
false;
2040 all_visible_cleared =
true;
2091 if (all_visible_cleared)
2185 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2186 errmsg(
"cannot insert tuples in a parallel worker")));
2203 if (relation->
rd_rel->relkind != RELKIND_RELATION &&
2204 relation->
rd_rel->relkind != RELKIND_MATVIEW)
2227 for (
int i = done;
i < ntuples;
i++)
2231 if (page_avail < tup_sz)
2236 page_avail -= tup_sz;
2268 bool starting_with_empty_page =
false;
2270 int npages_used = 0;
2281 for (
i = 0;
i < ntuples;
i++)
2318 while (ndone < ntuples)
2321 bool all_visible_cleared =
false;
2322 bool all_frozen_set =
false;
2337 if (ndone == 0 || !starting_with_empty_page)
2356 npages - npages_used);
2362 all_frozen_set =
true;
2377 if (needwal && need_cids)
2380 for (nthispage = 1; ndone + nthispage < ntuples; nthispage++)
2382 HeapTuple heaptup = heaptuples[ndone + nthispage];
2393 if (needwal && need_cids)
2406 all_visible_cleared =
true;
2412 else if (all_frozen_set)
2429 char *scratchptr = scratch.
data;
2437 init = starting_with_empty_page;
2453 tupledata = scratchptr;
2456 Assert(!(all_visible_cleared && all_frozen_set));
2459 if (all_visible_cleared)
2470 for (
i = 0;
i < nthispage;
i++)
2492 scratchptr += datalen;
2494 totaldatalen = scratchptr - tupledata;
2495 Assert((scratchptr - scratch.
data) < BLCKSZ);
2497 if (need_tuple_data)
2505 if (ndone + nthispage == ntuples)
2518 if (need_tuple_data)
2595 for (
i = 0;
i < ntuples;
i++)
2600 for (
i = 0;
i < ntuples;
i++)
2601 slots[
i]->tts_tid = heaptuples[
i]->t_self;
2653 const uint16 interesting =
2656 if ((new_infomask & interesting) != (old_infomask & interesting))
2689 bool have_tuple_lock =
false;
2691 bool all_visible_cleared =
false;
2693 bool old_key_copied =
false;
2704 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
2705 errmsg(
"cannot delete tuples during a parallel operation")));
2751 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2752 errmsg(
"attempted to delete invisible tuple")));
2778 bool current_is_member =
false;
2789 if (!current_is_member)
2869 if (result !=
TM_Ok)
2887 if (result !=
TM_Ok)
2896 if (have_tuple_lock)
2936 &new_xmax, &new_infomask, &new_infomask2);
2951 all_visible_cleared =
true;
2994 if (all_visible_cleared)
3001 xlrec.
xmax = new_xmax;
3003 if (old_key_tuple != NULL)
3005 if (relation->
rd_rel->relreplident == REPLICA_IDENTITY_FULL)
3019 if (old_key_tuple != NULL)
3028 old_key_tuple->
t_len
3053 if (relation->
rd_rel->relkind != RELKIND_RELATION &&
3054 relation->
rd_rel->relkind != RELKIND_MATVIEW)
3075 if (have_tuple_lock)
3080 if (old_key_tuple != NULL && old_key_copied)
3108 elog(
ERROR,
"tuple already updated by self");
3116 elog(
ERROR,
"tuple concurrently updated");
3120 elog(
ERROR,
"tuple concurrently deleted");
3124 elog(
ERROR,
"unrecognized heap_delete status: %u", result);
3158 bool old_key_copied =
false;
3169 bool have_tuple_lock =
false;
3171 bool use_hot_update =
false;
3172 bool summarized_update =
false;
3174 bool all_visible_cleared =
false;
3175 bool all_visible_cleared_new =
false;
3176 bool checked_lockers;
3177 bool locker_remains;
3178 bool id_has_external =
false;
3181 uint16 infomask_old_tuple,
3182 infomask2_old_tuple,
3184 infomask2_new_tuple;
3199 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
3200 errmsg(
"cannot update tuples during a parallel operation")));
3202 #ifdef USE_ASSERT_CHECKING
3203 check_lock_if_inplace_updateable_rel(relation, otid, newtup);
3229 interesting_attrs = NULL;
3275 newtup, &id_has_external);
3320 checked_lockers =
false;
3321 locker_remains =
false;
3331 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3332 errmsg(
"attempted to update invisible tuple")));
3338 bool can_continue =
false;
3383 bool current_is_member =
false;
3386 *lockmode, ¤t_is_member))
3394 if (!current_is_member)
3402 checked_lockers =
true;
3403 locker_remains = remain != 0;
3450 can_continue =
true;
3458 checked_lockers =
true;
3459 locker_remains =
true;
3460 can_continue =
true;
3469 checked_lockers =
true;
3470 locker_remains =
true;
3471 can_continue =
true;
3484 checked_lockers =
true;
3500 can_continue =
true;
3512 if (result !=
TM_Ok)
3530 if (result !=
TM_Ok)
3539 if (have_tuple_lock)
3580 xid, *lockmode,
true,
3581 &xmax_old_tuple, &infomask_old_tuple,
3582 &infomask2_old_tuple);
3593 (checked_lockers && !locker_remains))
3601 infomask2_new_tuple = 0;
3614 &infomask2_new_tuple);
3619 infomask2_new_tuple = 0;
3652 if (relation->
rd_rel->relkind != RELKIND_RELATION &&
3653 relation->
rd_rel->relkind != RELKIND_MATVIEW)
3669 if (need_toast || newtupsize > pagefree)
3672 uint16 infomask_lock_old_tuple,
3673 infomask2_lock_old_tuple;
3674 bool cleared_all_frozen =
false;
3697 xid, *lockmode,
false,
3698 &xmax_lock_old_tuple, &infomask_lock_old_tuple,
3699 &infomask2_lock_old_tuple);
3728 cleared_all_frozen =
true;
3741 xlrec.
xmax = xmax_lock_old_tuple;
3796 if (newtupsize > pagefree)
3801 &vmbuffer_new, &vmbuffer,
3813 if (newtupsize > pagefree ||
3861 if (newbuf == buffer)
3870 use_hot_update =
true;
3880 summarized_update =
true;
3954 all_visible_cleared =
true;
3961 all_visible_cleared_new =
true;
3967 if (newbuf != buffer)
3987 newbuf, &oldtup, heaptup,
3989 all_visible_cleared,
3990 all_visible_cleared_new);
3991 if (newbuf != buffer)
4000 if (newbuf != buffer)
4015 if (newbuf != buffer)
4026 if (have_tuple_lock)
4035 if (heaptup != newtup)
4049 if (summarized_update)
4055 *update_indexes =
TU_All;
4057 if (old_key_tuple != NULL && old_key_copied)
4070 #ifdef USE_ASSERT_CHECKING
4076 check_lock_if_inplace_updateable_rel(
Relation relation,
4083 case RelationRelationId:
4084 case DatabaseRelationId:
4104 case RelationRelationId:
4108 Oid relid = classForm->oid;
4117 if (classForm->relkind == RELKIND_INDEX)
4130 "missing lock for relation \"%s\" (OID %u, relkind %c) @ TID (%u,%u)",
4138 case DatabaseRelationId:
4144 "missing lock on database \"%s\" (OID %u) @ TID (%u,%u)",
4159 check_inplace_rel_lock(
HeapTuple oldtup)
4162 Oid relid = classForm->oid;
4171 if (classForm->relkind == RELKIND_INDEX)
4183 "missing lock for relation \"%s\" (OID %u, relkind %c) @ TID (%u,%u)",
4198 bool isnull1,
bool isnull2)
4206 if (isnull1 != isnull2)
4231 Assert(attrnum <= tupdesc->natts);
4233 return datumIsEqual(value1, value2, att->attbyval, att->attlen);
4299 value1 =
heap_getattr(oldtup, attrnum, tupdesc, &isnull1);
4300 value2 =
heap_getattr(newtup, attrnum, tupdesc, &isnull2);
4303 value2, isnull1, isnull2))
4313 if (attrnum < 0 || isnull1 ||
4323 *has_external =
true;
4348 &tmfd, &lockmode, update_indexes);
4353 elog(
ERROR,
"tuple already updated by self");
4361 elog(
ERROR,
"tuple concurrently updated");
4365 elog(
ERROR,
"tuple concurrently deleted");
4369 elog(
ERROR,
"unrecognized heap_update status: %u", result);
4390 is_update ?
"true" :
"false");
4429 bool follow_updates,
4443 bool first_time =
true;
4444 bool skip_tuple_lock =
false;
4445 bool have_tuple_lock =
false;
4446 bool cleared_all_frozen =
false;
4533 for (
i = 0;
i < nmembers;
i++)
4558 skip_tuple_lock =
true;
4607 require_sleep =
true;
4641 if (follow_updates && updated)
4672 require_sleep =
false;
4701 require_sleep =
false;
4727 require_sleep =
false;
4740 require_sleep =
false;
4766 require_sleep =
false;
4785 else if (require_sleep)
4797 if (!skip_tuple_lock &&
4817 elog(
ERROR,
"invalid lock mode in heap_lock_tuple");
4820 switch (wait_policy)
4828 status, infomask, relation,
4839 status, infomask, relation,
4842 (
errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4843 errmsg(
"could not obtain lock on row in relation \"%s\"",
4862 switch (wait_policy)
4880 (
errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4881 errmsg(
"could not obtain lock on row in relation \"%s\"",
4937 if (!require_sleep ||
4949 if (result !=
TM_Ok)
5011 &xid, &new_infomask, &new_infomask2);
5047 cleared_all_frozen =
true;
5106 if (have_tuple_lock)
5128 if (*have_tuple_lock)
5131 switch (wait_policy)
5145 (
errcode(ERRCODE_LOCK_NOT_AVAILABLE),
5146 errmsg(
"could not obtain lock on row in relation \"%s\"",
5150 *have_tuple_lock =
true;
5178 uint16 *result_infomask2)
5201 new_xmax = add_to_xmax;
5211 new_xmax = add_to_xmax;
5215 new_xmax = add_to_xmax;
5219 new_xmax = add_to_xmax;
5223 new_xmax = add_to_xmax;
5347 elog(
WARNING,
"LOCK_ONLY found for Xid in progress %u", xmax);
5369 if (xmax == add_to_xmax)
5383 if (
mode < old_mode)
5394 add_to_xmax, new_status);
5434 *result_infomask = new_infomask;
5435 *result_infomask2 = new_infomask2;
5436 *result_xmax = new_xmax;
5560 bool cleared_all_frozen =
false;
5561 bool pinned_desired_page;
5599 pinned_desired_page =
true;
5602 pinned_desired_page =
false;
5682 for (
i = 0;
i < nmembers;
i++)
5715 if (result !=
TM_Ok)