PostgreSQL Source Code  git master
heapam.h File Reference
#include "access/sdir.h"
#include "access/skey.h"
#include "nodes/lockoptions.h"
#include "nodes/primnodes.h"
#include "storage/bufpage.h"
#include "storage/lockdefs.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for heapam.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  HeapUpdateFailureData
 

Macros

#define HEAP_INSERT_SKIP_WAL   0x0001
 
#define HEAP_INSERT_SKIP_FSM   0x0002
 
#define HEAP_INSERT_FROZEN   0x0004
 
#define HEAP_INSERT_SPECULATIVE   0x0008
 
#define MaxLockTupleMode   LockTupleExclusive
 
#define heap_close(r, l)   relation_close(r,l)
 
#define HeapScanIsValid(scan)   PointerIsValid(scan)
 

Typedefs

typedef struct BulkInsertStateDataBulkInsertState
 
typedef enum LockTupleMode LockTupleMode
 
typedef struct HeapUpdateFailureData HeapUpdateFailureData
 
typedef struct HeapScanDescDataHeapScanDesc
 
typedef struct ParallelHeapScanDescDataParallelHeapScanDesc
 

Enumerations

enum  LockTupleMode { LockTupleKeyShare, LockTupleShare, LockTupleNoKeyExclusive, LockTupleExclusive }
 

Functions

Relation relation_open (Oid relationId, LOCKMODE lockmode)
 
Relation try_relation_open (Oid relationId, LOCKMODE lockmode)
 
Relation relation_openrv (const RangeVar *relation, LOCKMODE lockmode)
 
Relation relation_openrv_extended (const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
 
void relation_close (Relation relation, LOCKMODE lockmode)
 
Relation heap_open (Oid relationId, LOCKMODE lockmode)
 
Relation heap_openrv (const RangeVar *relation, LOCKMODE lockmode)
 
Relation heap_openrv_extended (const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
 
HeapScanDesc heap_beginscan (Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
 
HeapScanDesc heap_beginscan_catalog (Relation relation, int nkeys, ScanKey key)
 
HeapScanDesc heap_beginscan_strat (Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync)
 
HeapScanDesc heap_beginscan_bm (Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
 
HeapScanDesc heap_beginscan_sampling (Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync, bool allow_pagemode)
 
void heap_setscanlimits (HeapScanDesc scan, BlockNumber startBlk, BlockNumber endBlk)
 
void heapgetpage (HeapScanDesc scan, BlockNumber page)
 
void heap_rescan (HeapScanDesc scan, ScanKey key)
 
void heap_rescan_set_params (HeapScanDesc scan, ScanKey key, bool allow_strat, bool allow_sync, bool allow_pagemode)
 
void heap_endscan (HeapScanDesc scan)
 
HeapTuple heap_getnext (HeapScanDesc scan, ScanDirection direction)
 
Size heap_parallelscan_estimate (Snapshot snapshot)
 
void heap_parallelscan_initialize (ParallelHeapScanDesc target, Relation relation, Snapshot snapshot)
 
void heap_parallelscan_reinitialize (ParallelHeapScanDesc parallel_scan)
 
HeapScanDesc heap_beginscan_parallel (Relation, ParallelHeapScanDesc)
 
bool heap_fetch (Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
 
bool heap_hot_search_buffer (ItemPointer tid, Relation relation, Buffer buffer, Snapshot snapshot, HeapTuple heapTuple, bool *all_dead, bool first_call)
 
bool heap_hot_search (ItemPointer tid, Relation relation, Snapshot snapshot, bool *all_dead)
 
void heap_get_latest_tid (Relation relation, Snapshot snapshot, ItemPointer tid)
 
void setLastTid (const ItemPointer tid)
 
BulkInsertState GetBulkInsertState (void)
 
void FreeBulkInsertState (BulkInsertState)
 
void ReleaseBulkInsertStatePin (BulkInsertState bistate)
 
Oid heap_insert (Relation relation, HeapTuple tup, CommandId cid, int options, BulkInsertState bistate)
 
void heap_multi_insert (Relation relation, HeapTuple *tuples, int ntuples, CommandId cid, int options, BulkInsertState bistate)
 
HTSU_Result heap_delete (Relation relation, ItemPointer tid, CommandId cid, Snapshot crosscheck, bool wait, HeapUpdateFailureData *hufd, bool changingPart)
 
void heap_finish_speculative (Relation relation, HeapTuple tuple)
 
void heap_abort_speculative (Relation relation, HeapTuple tuple)
 
HTSU_Result heap_update (Relation relation, ItemPointer otid, HeapTuple newtup, CommandId cid, Snapshot crosscheck, bool wait, HeapUpdateFailureData *hufd, LockTupleMode *lockmode)
 
HTSU_Result heap_lock_tuple (Relation relation, HeapTuple tuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_update, Buffer *buffer, HeapUpdateFailureData *hufd)
 
void heap_inplace_update (Relation relation, HeapTuple tuple)
 
bool heap_freeze_tuple (HeapTupleHeader tuple, TransactionId relfrozenxid, TransactionId relminmxid, TransactionId cutoff_xid, TransactionId cutoff_multi)
 
bool heap_tuple_needs_freeze (HeapTupleHeader tuple, TransactionId cutoff_xid, MultiXactId cutoff_multi, Buffer buf)
 
bool heap_tuple_needs_eventual_freeze (HeapTupleHeader tuple)
 
Oid simple_heap_insert (Relation relation, HeapTuple tup)
 
void simple_heap_delete (Relation relation, ItemPointer tid)
 
void simple_heap_update (Relation relation, ItemPointer otid, HeapTuple tup)
 
void heap_sync (Relation relation)
 
void heap_update_snapshot (HeapScanDesc scan, Snapshot snapshot)
 
void heap_page_prune_opt (Relation relation, Buffer buffer)
 
int heap_page_prune (Relation relation, Buffer buffer, TransactionId OldestXmin, bool report_stats, TransactionId *latestRemovedXid)
 
void heap_page_prune_execute (Buffer buffer, OffsetNumber *redirected, int nredirected, OffsetNumber *nowdead, int ndead, OffsetNumber *nowunused, int nunused)
 
void heap_get_root_tuples (Page page, OffsetNumber *root_offsets)
 
void ss_report_location (Relation rel, BlockNumber location)
 
BlockNumber ss_get_location (Relation rel, BlockNumber relnblocks)
 
void SyncScanShmemInit (void)
 
Size SyncScanShmemSize (void)
 

Macro Definition Documentation

◆ heap_close

#define heap_close (   r,
 
)    relation_close(r,l)

Definition at line 97 of file heapam.h.

Referenced by _bt_parallel_build_main(), acquire_inherited_sample_rows(), AcquireRewriteLocks(), AddEnumLabel(), AddNewAttributeTuples(), addRangeTableEntry(), AddRoleMems(), AddSubscriptionRelState(), AfterTriggerSetState(), AggregateCreate(), AlterCollation(), AlterConstraintNamespaces(), AlterDatabase(), AlterDatabaseOwner(), AlterDomainAddConstraint(), AlterDomainDefault(), AlterDomainDropConstraint(), AlterDomainNotNull(), AlterDomainValidateConstraint(), AlterEventTrigger(), AlterEventTriggerOwner(), AlterEventTriggerOwner_oid(), AlterExtensionNamespace(), AlterForeignDataWrapper(), AlterForeignDataWrapperOwner(), AlterForeignDataWrapperOwner_oid(), AlterForeignServer(), AlterForeignServerOwner(), AlterForeignServerOwner_oid(), AlterFunction(), AlterObjectNamespace_oid(), AlterOperator(), AlterPolicy(), AlterPublication(), AlterPublicationOwner(), AlterPublicationOwner_oid(), AlterRole(), AlterSchemaOwner(), AlterSchemaOwner_oid(), AlterSequence(), AlterSetting(), AlterSubscription(), AlterSubscriptionOwner(), AlterSubscriptionOwner_oid(), AlterTableMoveAll(), AlterTableNamespaceInternal(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeNamespaceInternal(), AlterTypeOwner(), AlterTypeOwner_oid(), AlterTypeOwnerInternal(), AlterUserMapping(), AppendAttributeTuples(), ApplyExtensionUpdates(), AssignTypeArrayOid(), ATAddCheckConstraint(), ATAddForeignKeyConstraint(), ATExecAddColumn(), ATExecAddIdentity(), ATExecAddInherit(), ATExecAddOf(), ATExecAlterColumnGenericOptions(), ATExecAlterColumnType(), ATExecAlterConstraint(), ATExecAttachPartition(), ATExecChangeOwner(), ATExecDetachPartition(), ATExecDisableRowSecurity(), ATExecDropColumn(), ATExecDropConstraint(), ATExecDropIdentity(), ATExecDropInherit(), ATExecDropNotNull(), ATExecDropOf(), ATExecEnableRowSecurity(), ATExecForceNoForceRowSecurity(), ATExecGenericOptions(), ATExecSetIdentity(), ATExecSetNotNull(), ATExecSetOptions(), ATExecSetRelOptions(), ATExecSetStatistics(), ATExecSetStorage(), ATExecSetTableSpace(), ATExecValidateConstraint(), ATPrepChangePersistence(), ATRewriteTable(), ATRewriteTables(), AttrDefaultFetch(), boot_openrel(), BootstrapToastTable(), bringetbitmap(), brinvacuumcleanup(), bt_index_check_internal(), build_indices(), build_physical_tlist(), BuildRelationExtStatistics(), CatalogCacheInitializeCache(), change_owner_fix_column_acls(), changeDependencyFor(), changeDependencyOnOwner(), check_db_file_conflict(), check_default_allows_bound(), check_selective_binary_conversion(), CheckAndCreateToastTable(), CheckConstraintFetch(), checkSharedDependencies(), ChooseConstraintName(), CloneForeignKeyConstraints(), CloneRowTriggersToPartition(), close_lo_relation(), closerel(), CloseTableList(), cluster(), CollationCreate(), ConstraintNameIsUsed(), ConstraintSetParentConstraint(), ConversionCreate(), copy_heap_data(), copyTemplateDependencies(), CountDBSubscriptions(), create_proc_lang(), create_toast_table(), CreateAccessMethod(), CreateCast(), CreateComments(), CreateConstraintEntry(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateInheritance(), CreateOpFamily(), CreatePolicy(), CreatePublication(), CreateRole(), CreateSharedComments(), CreateSubscription(), CreateTableSpace(), CreateTransform(), CreateTrigger(), CreateUserMapping(), currtid_byrelname(), currtid_byreloid(), currtid_for_view(), database_to_xmlschema_internal(), DefineIndex(), DefineOpClass(), DefineQueryRewrite(), DefineRelation(), DefineSequence(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), DeleteAttributeTuples(), DeleteComments(), deleteDependencyRecordsFor(), deleteDependencyRecordsForClass(), DeleteInheritsTuple(), DeleteInitPrivs(), deleteOneObject(), DeleteRelationTuple(), DeleteSecurityLabel(), DeleteSequenceTuple(), DeleteSharedComments(), deleteSharedDependencyRecordsFor(), DeleteSharedSecurityLabel(), DeleteSystemAttributeTuples(), DelRoleMems(), deparseColumnRef(), deparseFromExprForRel(), deparseSelectSql(), do_autovacuum(), DoCopy(), drop_parent_dependency(), DropCastById(), dropDatabaseDependencies(), dropdb(), DropProceduralLanguageById(), DropRole(), DropSetting(), DropSubscription(), DropTableSpace(), DropTransformById(), EnableDisableRule(), EnableDisableTrigger(), ENRMetadataGetTupDesc(), enum_endpoint(), enum_range_internal(), EnumValuesCreate(), EnumValuesDelete(), EventTriggerSQLDropAddObject(), exec_object_restorecon(), ExecAlterExtensionStmt(), ExecAlterObjectDependsStmt(), ExecAlterObjectSchemaStmt(), ExecAlterOwnerStmt(), ExecCleanUpTriggerState(), ExecCleanupTupleRouting(), ExecCloseScanRelation(), ExecEndPlan(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), ExecRefreshMatView(), ExecRenameStmt(), ExecuteTruncate(), ExecuteTruncateGuts(), expand_inherited_rtentry(), expand_partitioned_rtentry(), extension_config_remove(), find_inheritance_children(), find_language_template(), find_typed_table_dependencies(), finish_heap_swap(), fireRIRrules(), free_parsestate(), generate_partition_qual(), get_actual_variable_range(), get_all_vacuum_rels(), get_constraint_index(), get_database_list(), get_database_oid(), get_db_info(), get_domain_constraint_oid(), get_extension_name(), get_extension_oid(), get_extension_schema(), get_file_fdw_attribute_options(), get_index_constraint(), get_object_address_relobject(), get_partition_ancestors(), get_partition_parent(), get_partition_qual_relid(), get_pkey_attnames(), get_primary_key_attnos(), get_relation_constraint_attnos(), get_relation_constraint_oid(), get_relation_constraints(), get_relation_data_width(), get_relation_idx_constraint_oid(), get_relation_info(), get_relation_policy_oid(), get_row_security_policies(), get_subscription_list(), get_tablespace_name(), get_tablespace_oid(), get_trigger_oid(), GetAllTablesPublicationRelations(), GetAllTablesPublications(), GetComment(), getConstraintTypeDescription(), GetDatabaseTuple(), GetDatabaseTupleByOid(), GetDefaultOpClass(), getExtensionOfObject(), getObjectDescription(), getObjectIdentityParts(), getOwnedSequences(), GetPublicationRelations(), getRelationsInNamespace(), GetSecurityLabel(), GetSharedSecurityLabel(), GetSubscriptionNotReadyRelations(), GetSubscriptionRelations(), GetSubscriptionRelState(), gettype(), GrantRole(), has_row_triggers(), has_superclass(), heap_create_with_catalog(), heap_drop_with_catalog(), heap_sync(), heap_truncate(), heap_truncate_find_FKs(), heap_truncate_one_rel(), index_build(), index_constraint_create(), index_create(), index_drop(), index_set_state_flags(), index_update_stats(), infer_arbiter_indexes(), insert_event_trigger_tuple(), InsertExtensionTuple(), InsertRule(), intorel_shutdown(), isQueryUsingTempRelation_walker(), LargeObjectCreate(), LargeObjectDrop(), LargeObjectExists(), load_domaintype_info(), load_enum_cache_data(), LockViewRecurse(), logicalrep_rel_close(), LogicalRepSyncTableStart(), lookup_ts_config_cache(), LookupOpclassInfo(), make_new_heap(), make_ruledef(), make_viewdef(), makeArrayTypeName(), mark_index_clustered(), MergeAttributes(), MergeAttributesIntoExisting(), MergeConstraintsIntoExisting(), MergeWithExistingConstraint(), movedb(), myLargeObjectExists(), NamespaceCreate(), objectsInSchemaToOids(), OpenTableList(), OperatorCreate(), OperatorShellMake(), OperatorUpd(), performDeletion(), performMultipleDeletions(), pg_event_trigger_ddl_commands(), pg_extension_config_dump(), pg_extension_ownercheck(), pg_get_constraintdef_worker(), pg_get_replica_identity_index(), pg_get_serial_sequence(), pg_get_triggerdef_worker(), pg_identify_object(), pg_largeobject_aclmask_snapshot(), pg_largeobject_ownercheck(), pgrowlocks(), pgstat_collect_oids(), plan_create_index_workers(), postgresPlanDirectModify(), postgresPlanForeignModify(), preprocess_targetlist(), ProcedureCreate(), process_settings(), publication_add_relation(), QueuePartitionConstraintValidation(), RangeCreate(), RangeDelete(), rebuild_relation(), recordExtensionInitPrivWorker(), recordMultipleDependencies(), recordSharedDependencyOn(), refresh_by_match_merge(), refuseDupeIndexAttach(), reindex_index(), reindex_relation(), ReindexMultipleTables(), relation_has_policies(), relation_mark_replica_identity(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationClearMissing(), RelationGetExclusionInfo(), RelationGetFKeyList(), RelationGetIndexList(), RelationGetStatExtList(), RelationRemoveInheritance(), RelationSetNewRelfilenode(), RelidByRelfilenode(), remove_dbtablespaces(), RemoveAccessMethodById(), RemoveAmOpEntryById(), RemoveAmProcEntryById(), RemoveAttrDefault(), RemoveAttrDefaultById(), RemoveAttributeById(), RemoveCollationById(), RemoveConstraintById(), RemoveConversionById(), RemoveDefaultACLById(), RemoveEventTriggerById(), RemoveExtensionById(), RemoveForeignDataWrapperById(), RemoveForeignServerById(), RemoveFunctionById(), RemoveInheritance(), RemoveObjects(), RemoveOpClassById(), RemoveOperatorById(), RemoveOpFamilyById(), RemovePartitionKeyByRelId(), RemovePolicyById(), RemovePublicationById(), RemovePublicationRelById(), RemoveRewriteRuleById(), RemoveRoleFromObjectACL(), RemoveRoleFromObjectPolicy(), RemoveSchemaById(), RemoveStatistics(), RemoveStatisticsById(), RemoveSubscriptionRel(), RemoveTriggerById(), RemoveTSConfigurationById(), RemoveTSDictionaryById(), RemoveTSParserById(), RemoveTSTemplateById(), RemoveTypeById(), RemoveUserMappingById(), rename_policy(), renameatt_internal(), RenameConstraint(), RenameConstraintById(), RenameDatabase(), RenameEnumLabel(), RenameRelationInternal(), RenameRewriteRule(), RenameRole(), RenameSchema(), RenameTableSpace(), renametrig(), RenameType(), RenameTypeInternal(), replorigin_create(), replorigin_drop(), RewriteQuery(), rewriteTargetView(), RI_FKey_cascade_del(), RI_FKey_cascade_upd(), RI_FKey_check(), ri_restrict(), ri_setdefault(), ri_setnull(), ScanPgRelation(), schema_to_xmlschema_internal(), SearchCatCacheList(), SearchCatCacheMiss(), sepgsql_attribute_post_create(), sepgsql_database_post_create(), sepgsql_index_modify(), sepgsql_proc_post_create(), sepgsql_proc_setattr(), sepgsql_relation_post_create(), sepgsql_relation_setattr(), sepgsql_schema_post_create(), sequenceIsOwned(), SetDefaultACL(), SetFunctionArgType(), SetFunctionReturnType(), SetMatViewPopulatedState(), SetRelationHasSubclass(), SetRelationNumChecks(), SetRelationRuleStatus(), SetSecurityLabel(), SetSharedSecurityLabel(), setTargetTable(), shdepDropOwned(), shdepReassignOwned(), StoreAttrDefault(), StoreCatalogInheritance(), storeOperators(), StorePartitionBound(), StorePartitionKey(), storeProcedures(), StoreSingleInheritance(), swap_relation_files(), table_to_xml_and_xmlschema(), table_to_xmlschema(), ThereIsAtLeastOneRole(), toast_delete_datum(), toast_fetch_datum(), toast_fetch_datum_slice(), toast_get_valid_index(), toast_save_datum(), toastid_valueid_exists(), transformIndexConstraint(), transformIndexStmt(), transformRuleStmt(), transformTableLikeClause(), transientrel_shutdown(), TypeCreate(), typeInheritsFrom(), TypeShellMake(), update_attstats(), update_default_partition_oid(), update_relispartition(), updateAclDependencies(), UpdateIndexRelation(), UpdateSubscriptionRelState(), vac_truncate_clog(), vac_update_datfrozenxid(), vac_update_relstats(), validate_index(), validateDomainConstraint(), and validatePartitionedIndex().

◆ HEAP_INSERT_FROZEN

#define HEAP_INSERT_FROZEN   0x0004

Definition at line 30 of file heapam.h.

Referenced by CopyFrom(), heap_prepare_insert(), and transientrel_startup().

◆ HEAP_INSERT_SKIP_FSM

#define HEAP_INSERT_SKIP_FSM   0x0002

◆ HEAP_INSERT_SKIP_WAL

◆ HEAP_INSERT_SPECULATIVE

#define HEAP_INSERT_SPECULATIVE   0x0008

Definition at line 31 of file heapam.h.

Referenced by ExecInsert(), heap_insert(), and toast_insert_or_update().

◆ HeapScanIsValid

#define HeapScanIsValid (   scan)    PointerIsValid(scan)

Definition at line 107 of file heapam.h.

◆ MaxLockTupleMode

#define MaxLockTupleMode   LockTupleExclusive

Definition at line 50 of file heapam.h.

Typedef Documentation

◆ BulkInsertState

Definition at line 33 of file heapam.h.

◆ HeapScanDesc

Definition at line 100 of file heapam.h.

◆ HeapUpdateFailureData

◆ LockTupleMode

◆ ParallelHeapScanDesc

Definition at line 101 of file heapam.h.

Enumeration Type Documentation

◆ LockTupleMode

Enumerator
LockTupleKeyShare 
LockTupleShare 
LockTupleNoKeyExclusive 
LockTupleExclusive 

Definition at line 38 of file heapam.h.

39 {
40  /* SELECT FOR KEY SHARE */
42  /* SELECT FOR SHARE */
44  /* SELECT FOR NO KEY UPDATE, and UPDATEs that don't modify key columns */
46  /* SELECT FOR UPDATE, UPDATEs that modify key columns, and DELETE */
LockTupleMode
Definition: heapam.h:38

Function Documentation

◆ FreeBulkInsertState()

void FreeBulkInsertState ( BulkInsertState  )

Definition at line 2378 of file heapam.c.

References BulkInsertStateData::current_buf, FreeAccessStrategy(), InvalidBuffer, pfree(), ReleaseBuffer(), and BulkInsertStateData::strategy.

Referenced by ATRewriteTable(), CopyFrom(), intorel_shutdown(), and transientrel_shutdown().

2379 {
2380  if (bistate->current_buf != InvalidBuffer)
2381  ReleaseBuffer(bistate->current_buf);
2382  FreeAccessStrategy(bistate->strategy);
2383  pfree(bistate);
2384 }
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
void pfree(void *pointer)
Definition: mcxt.c:1031
void FreeAccessStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:597

◆ GetBulkInsertState()

BulkInsertState GetBulkInsertState ( void  )

Definition at line 2364 of file heapam.c.

References BAS_BULKWRITE, BulkInsertStateData::current_buf, GetAccessStrategy(), InvalidBuffer, palloc(), and BulkInsertStateData::strategy.

Referenced by ATRewriteTable(), CopyFrom(), intorel_startup(), and transientrel_startup().

2365 {
2366  BulkInsertState bistate;
2367 
2368  bistate = (BulkInsertState) palloc(sizeof(BulkInsertStateData));
2370  bistate->current_buf = InvalidBuffer;
2371  return bistate;
2372 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:542
#define InvalidBuffer
Definition: buf.h:25
struct BulkInsertStateData * BulkInsertState
Definition: heapam.h:33
BufferAccessStrategy strategy
Definition: hio.h:33
void * palloc(Size size)
Definition: mcxt.c:924
Buffer current_buf
Definition: hio.h:34

◆ heap_abort_speculative()

void heap_abort_speculative ( Relation  relation,
HeapTuple  tuple 
)

Definition at line 6249 of file heapam.c.

References Assert, buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetPage, compute_infobits(), elog, END_CRIT_SECTION, ERROR, xl_heap_delete::flags, GetCurrentTransactionId(), HEAP_KEYS_UPDATED, HEAP_MOVED, HEAP_XMAX_BITS, HeapTupleHasExternal, HeapTupleHeaderIsHeapOnly, HeapTupleHeaderIsSpeculative, HeapTupleHeaderSetXmin, xl_heap_delete::infobits_set, InvalidTransactionId, IsToastRelation(), ItemIdGetLength, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerIsValid, LockBuffer(), MarkBufferDirty(), xl_heap_delete::offnum, PageGetItem, PageGetItemId, PageIsAllVisible, PageSetLSN, PageSetPrunable, pgstat_count_heap_delete(), ReadBuffer(), RecentGlobalXmin, REGBUF_STANDARD, RelationGetRelid, RelationNeedsWAL, ReleaseBuffer(), SizeOfHeapDelete, START_CRIT_SECTION, HeapTupleHeaderData::t_choice, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_heap, HeapTupleHeaderData::t_infomask, HeapTupleHeaderData::t_infomask2, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, HeapTupleFields::t_xmin, toast_delete(), TransactionIdIsValid, XLH_DELETE_IS_SUPER, XLOG_HEAP_DELETE, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), XLogRegisterData(), and xl_heap_delete::xmax.

Referenced by ExecInsert(), and toast_delete_datum().

6250 {
6252  ItemPointer tid = &(tuple->t_self);
6253  ItemId lp;
6254  HeapTupleData tp;
6255  Page page;
6256  BlockNumber block;
6257  Buffer buffer;
6258 
6259  Assert(ItemPointerIsValid(tid));
6260 
6261  block = ItemPointerGetBlockNumber(tid);
6262  buffer = ReadBuffer(relation, block);
6263  page = BufferGetPage(buffer);
6264 
6266 
6267  /*
6268  * Page can't be all visible, we just inserted into it, and are still
6269  * running.
6270  */
6271  Assert(!PageIsAllVisible(page));
6272 
6273  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
6274  Assert(ItemIdIsNormal(lp));
6275 
6276  tp.t_tableOid = RelationGetRelid(relation);
6277  tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
6278  tp.t_len = ItemIdGetLength(lp);
6279  tp.t_self = *tid;
6280 
6281  /*
6282  * Sanity check that the tuple really is a speculatively inserted tuple,
6283  * inserted by us.
6284  */
6285  if (tp.t_data->t_choice.t_heap.t_xmin != xid)
6286  elog(ERROR, "attempted to kill a tuple inserted by another transaction");
6287  if (!(IsToastRelation(relation) || HeapTupleHeaderIsSpeculative(tp.t_data)))
6288  elog(ERROR, "attempted to kill a non-speculative tuple");
6290 
6291  /*
6292  * No need to check for serializable conflicts here. There is never a
6293  * need for a combocid, either. No need to extract replica identity, or
6294  * do anything special with infomask bits.
6295  */
6296 
6298 
6299  /*
6300  * The tuple will become DEAD immediately. Flag that this page
6301  * immediately is a candidate for pruning by setting xmin to
6302  * RecentGlobalXmin. That's not pretty, but it doesn't seem worth
6303  * inventing a nicer API for this.
6304  */
6307 
6308  /* store transaction information of xact deleting the tuple */
6311 
6312  /*
6313  * Set the tuple header xmin to InvalidTransactionId. This makes the
6314  * tuple immediately invisible everyone. (In particular, to any
6315  * transactions waiting on the speculative token, woken up later.)
6316  */
6318 
6319  /* Clear the speculative insertion token too */
6320  tp.t_data->t_ctid = tp.t_self;
6321 
6322  MarkBufferDirty(buffer);
6323 
6324  /*
6325  * XLOG stuff
6326  *
6327  * The WAL records generated here match heap_delete(). The same recovery
6328  * routines are used.
6329  */
6330  if (RelationNeedsWAL(relation))
6331  {
6332  xl_heap_delete xlrec;
6333  XLogRecPtr recptr;
6334 
6335  xlrec.flags = XLH_DELETE_IS_SUPER;
6337  tp.t_data->t_infomask2);
6339  xlrec.xmax = xid;
6340 
6341  XLogBeginInsert();
6342  XLogRegisterData((char *) &xlrec, SizeOfHeapDelete);
6343  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
6344 
6345  /* No replica identity & replication origin logged */
6346 
6347  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
6348 
6349  PageSetLSN(page, recptr);
6350  }
6351 
6352  END_CRIT_SECTION();
6353 
6354  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6355 
6356  if (HeapTupleHasExternal(&tp))
6357  {
6358  Assert(!IsToastRelation(relation));
6359  toast_delete(relation, &tp, true);
6360  }
6361 
6362  /*
6363  * Never need to mark tuple for invalidation, since catalogs don't support
6364  * speculative insertion
6365  */
6366 
6367  /* Now we can release the buffer */
6368  ReleaseBuffer(buffer);
6369 
6370  /* count deletion, as we counted the insertion too */
6371  pgstat_count_heap_delete(relation);
6372 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
bool IsToastRelation(Relation relation)
Definition: catalog.c:136
#define HEAP_XMAX_BITS
Definition: htup_details.h:269
union HeapTupleHeaderData::@45 t_choice
#define XLH_DELETE_IS_SUPER
Definition: heapam_xlog.h:95
static uint8 compute_infobits(uint16 infomask, uint16 infomask2)
Definition: heapam.c:2999
HeapTupleFields t_heap
Definition: htup_details.h:155
#define PageIsAllVisible(page)
Definition: bufpage.h:381
uint32 TransactionId
Definition: c.h:474
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:428
#define PageSetPrunable(page, xid)
Definition: bufpage.h:394
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
OffsetNumber offnum
Definition: heapam_xlog.h:106
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderIsHeapOnly(tup)
Definition: htup_details.h:514
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
TransactionId xmax
Definition: heapam_xlog.h:105
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define SizeOfHeapDelete
Definition: heapam_xlog.h:111
TransactionId RecentGlobalXmin
Definition: snapmgr.c:166
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define InvalidTransactionId
Definition: transam.h:31
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
TransactionId t_xmin
Definition: htup_details.h:122
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define HEAP_KEYS_UPDATED
Definition: htup_details.h:277
#define HEAP_MOVED
Definition: htup_details.h:215
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
uint8 infobits_set
Definition: heapam_xlog.h:107
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define RelationNeedsWAL(relation)
Definition: rel.h:510
void pgstat_count_heap_delete(Relation rel)
Definition: pgstat.c:1953
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:686
void toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)
Definition: tuptoaster.c:464
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define XLOG_HEAP_DELETE
Definition: heapam_xlog.h:33
#define RelationGetRelid(relation)
Definition: rel.h:407
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:318

◆ heap_beginscan()

HeapScanDesc heap_beginscan ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key 
)

Definition at line 1404 of file heapam.c.

References heap_beginscan_internal().

Referenced by AlterDomainNotNull(), ATRewriteTable(), check_default_allows_bound(), copy_heap_data(), CopyTo(), DefineQueryRewrite(), pgrowlocks(), pgstat_collect_oids(), RelationFindReplTupleSeq(), SeqNext(), validateCheckConstraint(), validateDomainConstraint(), and validateForeignKeyConstraint().

1406 {
1407  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1408  true, true, true, false, false, false);
1409 }
static HeapScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, ParallelHeapScanDesc parallel_scan, bool allow_strat, bool allow_sync, bool allow_pagemode, bool is_bitmapscan, bool is_samplescan, bool temp_snap)
Definition: heapam.c:1450

◆ heap_beginscan_bm()

HeapScanDesc heap_beginscan_bm ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key 
)

Definition at line 1432 of file heapam.c.

References heap_beginscan_internal().

Referenced by ExecInitBitmapHeapScan().

1434 {
1435  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1436  false, false, true, true, false, false);
1437 }
static HeapScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, ParallelHeapScanDesc parallel_scan, bool allow_strat, bool allow_sync, bool allow_pagemode, bool is_bitmapscan, bool is_samplescan, bool temp_snap)
Definition: heapam.c:1450

◆ heap_beginscan_catalog()

HeapScanDesc heap_beginscan_catalog ( Relation  relation,
int  nkeys,
ScanKey  key 
)

Definition at line 1412 of file heapam.c.

References GetCatalogSnapshot(), heap_beginscan_internal(), RegisterSnapshot(), and RelationGetRelid.

Referenced by AlterTableMoveAll(), AlterTableSpaceOptions(), boot_openrel(), check_db_file_conflict(), createdb(), do_autovacuum(), DropSetting(), DropTableSpace(), find_typed_table_dependencies(), get_all_vacuum_rels(), get_database_list(), get_subscription_list(), get_tables_to_cluster(), get_tablespace_name(), get_tablespace_oid(), GetAllTablesPublicationRelations(), getRelationsInNamespace(), gettype(), index_update_stats(), objectsInSchemaToOids(), ReindexMultipleTables(), remove_dbtablespaces(), RemoveConversionById(), RemoveSubscriptionRel(), RenameTableSpace(), ThereIsAtLeastOneRole(), and vac_truncate_clog().

1413 {
1414  Oid relid = RelationGetRelid(relation);
1415  Snapshot snapshot = RegisterSnapshot(GetCatalogSnapshot(relid));
1416 
1417  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1418  true, true, true, false, false, true);
1419 }
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:440
unsigned int Oid
Definition: postgres_ext.h:31
static HeapScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, ParallelHeapScanDesc parallel_scan, bool allow_strat, bool allow_sync, bool allow_pagemode, bool is_bitmapscan, bool is_samplescan, bool temp_snap)
Definition: heapam.c:1450
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ heap_beginscan_parallel()

HeapScanDesc heap_beginscan_parallel ( Relation  ,
ParallelHeapScanDesc   
)

Definition at line 1666 of file heapam.c.

References Assert, heap_beginscan_internal(), ParallelHeapScanDescData::phs_relid, ParallelHeapScanDescData::phs_snapshot_any, ParallelHeapScanDescData::phs_snapshot_data, RegisterSnapshot(), RelationGetRelid, RestoreSnapshot(), and SnapshotAny.

Referenced by _bt_parallel_scan_and_sort(), ExecSeqScanInitializeDSM(), and ExecSeqScanInitializeWorker().

1667 {
1668  Snapshot snapshot;
1669 
1670  Assert(RelationGetRelid(relation) == parallel_scan->phs_relid);
1671 
1672  if (!parallel_scan->phs_snapshot_any)
1673  {
1674  /* Snapshot was serialized -- restore it */
1675  snapshot = RestoreSnapshot(parallel_scan->phs_snapshot_data);
1676  RegisterSnapshot(snapshot);
1677  }
1678  else
1679  {
1680  /* SnapshotAny passed by caller (not serialized) */
1681  snapshot = SnapshotAny;
1682  }
1683 
1684  return heap_beginscan_internal(relation, snapshot, 0, NULL, parallel_scan,
1685  true, true, true, false, false,
1686  !parallel_scan->phs_snapshot_any);
1687 }
Snapshot RestoreSnapshot(char *start_address)
Definition: snapmgr.c:2127
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
static HeapScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, ParallelHeapScanDesc parallel_scan, bool allow_strat, bool allow_sync, bool allow_pagemode, bool is_bitmapscan, bool is_samplescan, bool temp_snap)
Definition: heapam.c:1450
#define SnapshotAny
Definition: tqual.h:28
#define Assert(condition)
Definition: c.h:699
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ heap_beginscan_sampling()

HeapScanDesc heap_beginscan_sampling ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key,
bool  allow_strat,
bool  allow_sync,
bool  allow_pagemode 
)

Definition at line 1440 of file heapam.c.

References heap_beginscan_internal().

Referenced by tablesample_init().

1443 {
1444  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1445  allow_strat, allow_sync, allow_pagemode,
1446  false, true, false);
1447 }
static HeapScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, ParallelHeapScanDesc parallel_scan, bool allow_strat, bool allow_sync, bool allow_pagemode, bool is_bitmapscan, bool is_samplescan, bool temp_snap)
Definition: heapam.c:1450

◆ heap_beginscan_strat()

HeapScanDesc heap_beginscan_strat ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key,
bool  allow_strat,
bool  allow_sync 
)

Definition at line 1422 of file heapam.c.

References heap_beginscan_internal().

Referenced by bt_check_every_level(), IndexBuildHeapRangeScan(), IndexCheckExclusion(), pgstat_heap(), systable_beginscan(), and validate_index_heapscan().

1425 {
1426  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1427  allow_strat, allow_sync, true,
1428  false, false, false);
1429 }
static HeapScanDesc heap_beginscan_internal(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, ParallelHeapScanDesc parallel_scan, bool allow_strat, bool allow_sync, bool allow_pagemode, bool is_bitmapscan, bool is_samplescan, bool temp_snap)
Definition: heapam.c:1450

◆ heap_delete()

HTSU_Result heap_delete ( Relation  relation,
ItemPointer  tid,
CommandId  cid,
Snapshot  crosscheck,
bool  wait,
HeapUpdateFailureData hufd,
bool  changingPart 
)

Definition at line 3060 of file heapam.c.

References Assert, buffer, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, CacheInvalidateHeapTuple(), CheckForSerializableConflictIn(), HeapUpdateFailureData::cmax, compute_infobits(), compute_new_xmax_infomask(), HeapUpdateFailureData::ctid, DoesMultiXactIdConflict(), END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, ExtractReplicaIdentity(), xl_heap_delete::flags, GetCurrentTransactionId(), heap_acquire_tuplock(), heap_freetuple(), HEAP_KEYS_UPDATED, HEAP_MOVED, HEAP_XMAX_BITS, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HeapTupleBeingUpdated, HeapTupleHasExternal, HeapTupleHeaderAdjustCmax(), HeapTupleHeaderClearHotUpdated, HeapTupleHeaderGetCmax(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderIsOnlyLocked(), HeapTupleHeaderSetCmax, HeapTupleHeaderSetMovedPartitions, HeapTupleHeaderSetXmax, HeapTupleInvisible, HeapTupleMayBeUpdated, HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVisibility, HeapTupleSelfUpdated, HeapTupleUpdated, xl_heap_delete::infobits_set, InvalidBuffer, InvalidCommandId, InvalidSnapshot, IsInParallelMode(), ItemIdGetLength, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerIsValid, LockBuffer(), LockTupleExclusive, LockWaitBlock, log_heap_new_cid(), MarkBufferDirty(), MultiXactIdSetOldestMember(), MultiXactIdWait(), MultiXactStatusUpdate, xl_heap_delete::offnum, PageClearAllVisible, PageGetItem, PageGetItemId, PageIsAllVisible, PageSetLSN, PageSetPrunable, pgstat_count_heap_delete(), RelationData::rd_rel, ReadBuffer(), REGBUF_STANDARD, RelationGetRelid, RelationIsAccessibleInLogicalDecoding, RelationNeedsWAL, ReleaseBuffer(), SizeOfHeapDelete, SizeOfHeapHeader, SizeofHeapTupleHeader, START_CRIT_SECTION, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, xl_heap_header::t_hoff, HeapTupleHeaderData::t_hoff, xl_heap_header::t_infomask, HeapTupleHeaderData::t_infomask, xl_heap_header::t_infomask2, HeapTupleHeaderData::t_infomask2, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, toast_delete(), TransactionIdEquals, TransactionIdIsCurrentTransactionId(), UnlockReleaseBuffer(), UnlockTupleTuplock, UpdateXmaxHintBits(), visibilitymap_clear(), visibilitymap_pin(), VISIBILITYMAP_VALID_BITS, XactLockTableWait(), XLH_DELETE_ALL_VISIBLE_CLEARED, XLH_DELETE_CONTAINS_OLD_KEY, XLH_DELETE_CONTAINS_OLD_TUPLE, XLH_DELETE_IS_PARTITION_MOVE, XLOG_HEAP_DELETE, XLOG_INCLUDE_ORIGIN, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), XLogRegisterData(), XLogSetRecordFlags(), XLTW_Delete, HeapUpdateFailureData::xmax, xl_heap_delete::xmax, and xmax_infomask_changed().

Referenced by ExecDelete(), and simple_heap_delete().

3063 {
3064  HTSU_Result result;
3066  ItemId lp;
3067  HeapTupleData tp;
3068  Page page;
3069  BlockNumber block;
3070  Buffer buffer;
3071  Buffer vmbuffer = InvalidBuffer;
3072  TransactionId new_xmax;
3073  uint16 new_infomask,
3074  new_infomask2;
3075  bool have_tuple_lock = false;
3076  bool iscombo;
3077  bool all_visible_cleared = false;
3078  HeapTuple old_key_tuple = NULL; /* replica identity of the tuple */
3079  bool old_key_copied = false;
3080 
3081  Assert(ItemPointerIsValid(tid));
3082 
3083  /*
3084  * Forbid this during a parallel operation, lest it allocate a combocid.
3085  * Other workers might need that combocid for visibility checks, and we
3086  * have no provision for broadcasting it to them.
3087  */
3088  if (IsInParallelMode())
3089  ereport(ERROR,
3090  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
3091  errmsg("cannot delete tuples during a parallel operation")));
3092 
3093  block = ItemPointerGetBlockNumber(tid);
3094  buffer = ReadBuffer(relation, block);
3095  page = BufferGetPage(buffer);
3096 
3097  /*
3098  * Before locking the buffer, pin the visibility map page if it appears to
3099  * be necessary. Since we haven't got the lock yet, someone else might be
3100  * in the middle of changing this, so we'll need to recheck after we have
3101  * the lock.
3102  */
3103  if (PageIsAllVisible(page))
3104  visibilitymap_pin(relation, block, &vmbuffer);
3105 
3107 
3108  /*
3109  * If we didn't pin the visibility map page and the page has become all
3110  * visible while we were busy locking the buffer, we'll have to unlock and
3111  * re-lock, to avoid holding the buffer lock across an I/O. That's a bit
3112  * unfortunate, but hopefully shouldn't happen often.
3113  */
3114  if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
3115  {
3116  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3117  visibilitymap_pin(relation, block, &vmbuffer);
3119  }
3120 
3121  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
3122  Assert(ItemIdIsNormal(lp));
3123 
3124  tp.t_tableOid = RelationGetRelid(relation);
3125  tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
3126  tp.t_len = ItemIdGetLength(lp);
3127  tp.t_self = *tid;
3128 
3129 l1:
3130  result = HeapTupleSatisfiesUpdate(&tp, cid, buffer);
3131 
3132  if (result == HeapTupleInvisible)
3133  {
3134  UnlockReleaseBuffer(buffer);
3135  ereport(ERROR,
3136  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3137  errmsg("attempted to delete invisible tuple")));
3138  }
3139  else if (result == HeapTupleBeingUpdated && wait)
3140  {
3141  TransactionId xwait;
3142  uint16 infomask;
3143 
3144  /* must copy state data before unlocking buffer */
3145  xwait = HeapTupleHeaderGetRawXmax(tp.t_data);
3146  infomask = tp.t_data->t_infomask;
3147 
3148  /*
3149  * Sleep until concurrent transaction ends -- except when there's a
3150  * single locker and it's our own transaction. Note we don't care
3151  * which lock mode the locker has, because we need the strongest one.
3152  *
3153  * Before sleeping, we need to acquire tuple lock to establish our
3154  * priority for the tuple (see heap_lock_tuple). LockTuple will
3155  * release us when we are next-in-line for the tuple.
3156  *
3157  * If we are forced to "start over" below, we keep the tuple lock;
3158  * this arranges that we stay at the head of the line while rechecking
3159  * tuple state.
3160  */
3161  if (infomask & HEAP_XMAX_IS_MULTI)
3162  {
3163  /* wait for multixact */
3164  if (DoesMultiXactIdConflict((MultiXactId) xwait, infomask,
3166  {
3167  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3168 
3169  /* acquire tuple lock, if necessary */
3171  LockWaitBlock, &have_tuple_lock);
3172 
3173  /* wait for multixact */
3175  relation, &(tp.t_self), XLTW_Delete,
3176  NULL);
3178 
3179  /*
3180  * If xwait had just locked the tuple then some other xact
3181  * could update this tuple before we get to this point. Check
3182  * for xmax change, and start over if so.
3183  */
3184  if (xmax_infomask_changed(tp.t_data->t_infomask, infomask) ||
3186  xwait))
3187  goto l1;
3188  }
3189 
3190  /*
3191  * You might think the multixact is necessarily done here, but not
3192  * so: it could have surviving members, namely our own xact or
3193  * other subxacts of this backend. It is legal for us to delete
3194  * the tuple in either case, however (the latter case is
3195  * essentially a situation of upgrading our former shared lock to
3196  * exclusive). We don't bother changing the on-disk hint bits
3197  * since we are about to overwrite the xmax altogether.
3198  */
3199  }
3200  else if (!TransactionIdIsCurrentTransactionId(xwait))
3201  {
3202  /*
3203  * Wait for regular transaction to end; but first, acquire tuple
3204  * lock.
3205  */
3206  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3208  LockWaitBlock, &have_tuple_lock);
3209  XactLockTableWait(xwait, relation, &(tp.t_self), XLTW_Delete);
3211 
3212  /*
3213  * xwait is done, but if xwait had just locked the tuple then some
3214  * other xact could update this tuple before we get to this point.
3215  * Check for xmax change, and start over if so.
3216  */
3217  if (xmax_infomask_changed(tp.t_data->t_infomask, infomask) ||
3219  xwait))
3220  goto l1;
3221 
3222  /* Otherwise check if it committed or aborted */
3223  UpdateXmaxHintBits(tp.t_data, buffer, xwait);
3224  }
3225 
3226  /*
3227  * We may overwrite if previous xmax aborted, or if it committed but
3228  * only locked the tuple without updating it.
3229  */
3230  if ((tp.t_data->t_infomask & HEAP_XMAX_INVALID) ||
3233  result = HeapTupleMayBeUpdated;
3234  else
3235  result = HeapTupleUpdated;
3236  }
3237 
3238  if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
3239  {
3240  /* Perform additional check for transaction-snapshot mode RI updates */
3241  if (!HeapTupleSatisfiesVisibility(&tp, crosscheck, buffer))
3242  result = HeapTupleUpdated;
3243  }
3244 
3245  if (result != HeapTupleMayBeUpdated)
3246  {
3247  Assert(result == HeapTupleSelfUpdated ||
3248  result == HeapTupleUpdated ||
3249  result == HeapTupleBeingUpdated);
3251  hufd->ctid = tp.t_data->t_ctid;
3253  if (result == HeapTupleSelfUpdated)
3254  hufd->cmax = HeapTupleHeaderGetCmax(tp.t_data);
3255  else
3256  hufd->cmax = InvalidCommandId;
3257  UnlockReleaseBuffer(buffer);
3258  if (have_tuple_lock)
3259  UnlockTupleTuplock(relation, &(tp.t_self), LockTupleExclusive);
3260  if (vmbuffer != InvalidBuffer)
3261  ReleaseBuffer(vmbuffer);
3262  return result;
3263  }
3264 
3265  /*
3266  * We're about to do the actual delete -- check for conflict first, to
3267  * avoid possibly having to roll back work we've just done.
3268  *
3269  * This is safe without a recheck as long as there is no possibility of
3270  * another process scanning the page between this check and the delete
3271  * being visible to the scan (i.e., an exclusive buffer content lock is
3272  * continuously held from this point until the tuple delete is visible).
3273  */
3274  CheckForSerializableConflictIn(relation, &tp, buffer);
3275 
3276  /* replace cid with a combo cid if necessary */
3277  HeapTupleHeaderAdjustCmax(tp.t_data, &cid, &iscombo);
3278 
3279  /*
3280  * Compute replica identity tuple before entering the critical section so
3281  * we don't PANIC upon a memory allocation failure.
3282  */
3283  old_key_tuple = ExtractReplicaIdentity(relation, &tp, true, &old_key_copied);
3284 
3285  /*
3286  * If this is the first possibly-multixact-able operation in the current
3287  * transaction, set my per-backend OldestMemberMXactId setting. We can be
3288  * certain that the transaction will never become a member of any older
3289  * MultiXactIds than that. (We have to do this even if we end up just
3290  * using our own TransactionId below, since some other backend could
3291  * incorporate our XID into a MultiXact immediately afterwards.)
3292  */
3294 
3297  xid, LockTupleExclusive, true,
3298  &new_xmax, &new_infomask, &new_infomask2);
3299 
3301 
3302  /*
3303  * If this transaction commits, the tuple will become DEAD sooner or
3304  * later. Set flag that this page is a candidate for pruning once our xid
3305  * falls below the OldestXmin horizon. If the transaction finally aborts,
3306  * the subsequent page pruning will be a no-op and the hint will be
3307  * cleared.
3308  */
3309  PageSetPrunable(page, xid);
3310 
3311  if (PageIsAllVisible(page))
3312  {
3313  all_visible_cleared = true;
3314  PageClearAllVisible(page);
3315  visibilitymap_clear(relation, BufferGetBlockNumber(buffer),
3316  vmbuffer, VISIBILITYMAP_VALID_BITS);
3317  }
3318 
3319  /* store transaction information of xact deleting the tuple */
3322  tp.t_data->t_infomask |= new_infomask;
3323  tp.t_data->t_infomask2 |= new_infomask2;
3325  HeapTupleHeaderSetXmax(tp.t_data, new_xmax);
3326  HeapTupleHeaderSetCmax(tp.t_data, cid, iscombo);
3327  /* Make sure there is no forward chain link in t_ctid */
3328  tp.t_data->t_ctid = tp.t_self;
3329 
3330  /* Signal that this is actually a move into another partition */
3331  if (changingPart)
3333 
3334  MarkBufferDirty(buffer);
3335 
3336  /*
3337  * XLOG stuff
3338  *
3339  * NB: heap_abort_speculative() uses the same xlog record and replay
3340  * routines.
3341  */
3342  if (RelationNeedsWAL(relation))
3343  {
3344  xl_heap_delete xlrec;
3345  XLogRecPtr recptr;
3346 
3347  /* For logical decode we need combocids to properly decode the catalog */
3349  log_heap_new_cid(relation, &tp);
3350 
3351  xlrec.flags = 0;
3352  if (all_visible_cleared)
3354  if (changingPart)
3357  tp.t_data->t_infomask2);
3359  xlrec.xmax = new_xmax;
3360 
3361  if (old_key_tuple != NULL)
3362  {
3363  if (relation->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
3365  else
3367  }
3368 
3369  XLogBeginInsert();
3370  XLogRegisterData((char *) &xlrec, SizeOfHeapDelete);
3371 
3372  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
3373 
3374  /*
3375  * Log replica identity of the deleted tuple if there is one
3376  */
3377  if (old_key_tuple != NULL)
3378  {
3379  xl_heap_header xlhdr;
3380 
3381  xlhdr.t_infomask2 = old_key_tuple->t_data->t_infomask2;
3382  xlhdr.t_infomask = old_key_tuple->t_data->t_infomask;
3383  xlhdr.t_hoff = old_key_tuple->t_data->t_hoff;
3384 
3385  XLogRegisterData((char *) &xlhdr, SizeOfHeapHeader);
3386  XLogRegisterData((char *) old_key_tuple->t_data
3388  old_key_tuple->t_len
3390  }
3391 
3392  /* filtering by origin on a row level is much more efficient */
3394 
3395  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
3396 
3397  PageSetLSN(page, recptr);
3398  }
3399 
3400  END_CRIT_SECTION();
3401 
3402  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3403 
3404  if (vmbuffer != InvalidBuffer)
3405  ReleaseBuffer(vmbuffer);
3406 
3407  /*
3408  * If the tuple has toasted out-of-line attributes, we need to delete
3409  * those items too. We have to do this before releasing the buffer
3410  * because we need to look at the contents of the tuple, but it's OK to
3411  * release the content lock on the buffer first.
3412  */
3413  if (relation->rd_rel->relkind != RELKIND_RELATION &&
3414  relation->rd_rel->relkind != RELKIND_MATVIEW)
3415  {
3416  /* toast table entries should never be recursively toasted */
3418  }
3419  else if (HeapTupleHasExternal(&tp))
3420  toast_delete(relation, &tp, false);
3421 
3422  /*
3423  * Mark tuple for invalidation from system caches at next command
3424  * boundary. We have to do this before releasing the buffer because we
3425  * need to look at the contents of the tuple.
3426  */
3427  CacheInvalidateHeapTuple(relation, &tp, NULL);
3428 
3429  /* Now we can release the buffer */
3430  ReleaseBuffer(buffer);
3431 
3432  /*
3433  * Release the lmgr tuple lock, if we had it.
3434  */
3435  if (have_tuple_lock)
3436  UnlockTupleTuplock(relation, &(tp.t_self), LockTupleExclusive);
3437 
3438  pgstat_count_heap_delete(relation);
3439 
3440  if (old_key_tuple != NULL && old_key_copied)
3441  heap_freetuple(old_key_tuple);
3442 
3443  return HeapTupleMayBeUpdated;
3444 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1596
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define SizeofHeapTupleHeader
Definition: htup_details.h:183
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup)
Definition: heapam.c:7971
#define HEAP_XMAX_BITS
Definition: htup_details.h:269
static uint8 compute_infobits(uint16 infomask, uint16 infomask2)
Definition: heapam.c:2999
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1094
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define PageIsAllVisible(page)
Definition: bufpage.h:381
uint32 TransactionId
Definition: c.h:474
HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, Buffer buffer)
Definition: tqual.c:460
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:765
void visibilitymap_pin(Relation rel, BlockNumber heapBlk, Buffer *buf)
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static bool xmax_infomask_changed(uint16 new_infomask, uint16 old_infomask)
Definition: heapam.c:3021
#define HeapTupleHeaderClearHotUpdated(tup)
Definition: htup_details.h:509
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define InvalidBuffer
Definition: buf.h:25
uint16 t_infomask2
Definition: heapam_xlog.h:144
#define PageSetPrunable(page, xid)
Definition: bufpage.h:394
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:192
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
Form_pg_class rd_rel
Definition: rel.h:84
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
void CheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: predicate.c:4280
#define UnlockTupleTuplock(rel, tup, mode)
Definition: heapam.c:187
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
OffsetNumber offnum
Definition: heapam_xlog.h:106
void MultiXactIdSetOldestMember(void)
Definition: multixact.c:623
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
unsigned short uint16
Definition: c.h:324
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
bool IsInParallelMode(void)
Definition: xact.c:905
bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:206
ItemPointerData t_ctid
Definition: htup_details.h:159
#define HeapTupleHeaderSetMovedPartitions(tup)
Definition: htup_details.h:448
ItemPointerData t_self
Definition: htup.h:65
TransactionId xmax
Definition: heapam_xlog.h:105
static void MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, Relation rel, ItemPointer ctid, XLTW_Oper oper, int *remaining)
Definition: heapam.c:7387
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define SizeOfHeapDelete
Definition: heapam_xlog.h:111
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define XLH_DELETE_CONTAINS_OLD_KEY
Definition: heapam_xlog.h:94
CommandId cmax
Definition: heapam.h:72
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:379
HTSU_Result
Definition: snapshot.h:121
Oid t_tableOid
Definition: htup.h:66
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define HeapTupleHeaderSetCmax(tup, cid, iscombo)
Definition: htup_details.h:404
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask, uint16 old_infomask2, TransactionId add_to_xmax, LockTupleMode mode, bool is_update, TransactionId *result_xmax, uint16 *result_infomask, uint16 *result_infomask2)
Definition: heapam.c:5403
TransactionId xmax
Definition: heapam.h:71
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define InvalidSnapshot
Definition: snapshot.h:25
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:564
#define InvalidCommandId
Definition: c.h:491
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:229
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define HEAP_KEYS_UPDATED
Definition: htup_details.h:277
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:207
static void UpdateXmaxHintBits(HeapTupleHeader tuple, Buffer buffer, TransactionId xid)
Definition: heapam.c:2342
#define HEAP_MOVED
Definition: htup_details.h:215
static bool heap_acquire_tuplock(Relation relation, ItemPointer tid, LockTupleMode mode, LockWaitPolicy wait_policy, bool *have_tuple_lock)
Definition: heapam.c:5354
TransactionId MultiXactId
Definition: c.h:484
#define PageClearAllVisible(page)
Definition: bufpage.h:385
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
uint8 infobits_set
Definition: heapam_xlog.h:107
static HeapTuple ExtractReplicaIdentity(Relation rel, HeapTuple tup, bool key_modified, bool *copy)
Definition: heapam.c:8047
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:119
static bool DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, LockTupleMode lockmode)
Definition: heapam.c:7220
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint16 t_infomask
Definition: heapam_xlog.h:145
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define RelationNeedsWAL(relation)
Definition: rel.h:510
void pgstat_count_heap_delete(Relation rel)
Definition: pgstat.c:1953
void HeapTupleHeaderAdjustCmax(HeapTupleHeader tup, CommandId *cmax, bool *iscombo)
Definition: combocid.c:154
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:686
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define XLH_DELETE_ALL_VISIBLE_CLEARED
Definition: heapam_xlog.h:92
#define XLH_DELETE_IS_PARTITION_MOVE
Definition: heapam_xlog.h:96
void toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)
Definition: tuptoaster.c:464
ItemPointerData ctid
Definition: heapam.h:70
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define XLOG_HEAP_DELETE
Definition: heapam_xlog.h:33
#define RelationGetRelid(relation)
Definition: rel.h:407
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
#define SizeOfHeapHeader
Definition: heapam_xlog.h:149
Pointer Page
Definition: bufpage.h:74
#define XLH_DELETE_CONTAINS_OLD_TUPLE
Definition: heapam_xlog.h:93

◆ heap_endscan()

void heap_endscan ( HeapScanDesc  scan)

Definition at line 1572 of file heapam.c.

References BufferIsValid, FreeAccessStrategy(), pfree(), RelationDecrementReferenceCount(), ReleaseBuffer(), HeapScanDescData::rs_cbuf, HeapScanDescData::rs_key, HeapScanDescData::rs_rd, HeapScanDescData::rs_snapshot, HeapScanDescData::rs_strategy, HeapScanDescData::rs_temp_snap, and UnregisterSnapshot().

Referenced by AlterDomainNotNull(), AlterTableMoveAll(), AlterTableSpaceOptions(), ATRewriteTable(), boot_openrel(), check_db_file_conflict(), check_default_allows_bound(), copy_heap_data(), CopyTo(), createdb(), DefineQueryRewrite(), do_autovacuum(), DropSetting(), DropTableSpace(), ExecEndBitmapHeapScan(), ExecEndSampleScan(), ExecEndSeqScan(), find_typed_table_dependencies(), get_all_vacuum_rels(), get_database_list(), get_subscription_list(), get_tables_to_cluster(), get_tablespace_name(), get_tablespace_oid(), GetAllTablesPublicationRelations(), getRelationsInNamespace(), gettype(), index_update_stats(), IndexBuildHeapRangeScan(), IndexCheckExclusion(), objectsInSchemaToOids(), pgrowlocks(), pgstat_collect_oids(), pgstat_heap(), ReindexMultipleTables(), RelationFindReplTupleSeq(), remove_dbtablespaces(), RemoveConversionById(), RemoveSubscriptionRel(), RenameTableSpace(), systable_endscan(), ThereIsAtLeastOneRole(), vac_truncate_clog(), validate_index_heapscan(), validateCheckConstraint(), validateDomainConstraint(), and validateForeignKeyConstraint().

1573 {
1574  /* Note: no locking manipulations needed */
1575 
1576  /*
1577  * unpin scan buffers
1578  */
1579  if (BufferIsValid(scan->rs_cbuf))
1580  ReleaseBuffer(scan->rs_cbuf);
1581 
1582  /*
1583  * decrement relation reference count and free scan descriptor storage
1584  */
1586 
1587  if (scan->rs_key)
1588  pfree(scan->rs_key);
1589 
1590  if (scan->rs_strategy != NULL)
1592 
1593  if (scan->rs_temp_snap)
1595 
1596  pfree(scan);
1597 }
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
void pfree(void *pointer)
Definition: mcxt.c:1031
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:1976
Snapshot rs_snapshot
Definition: relscan.h:50
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:905
bool rs_temp_snap
Definition: relscan.h:58
BufferAccessStrategy rs_strategy
Definition: relscan.h:65
Relation rs_rd
Definition: relscan.h:49
Buffer rs_cbuf
Definition: relscan.h:72
void FreeAccessStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:597
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
ScanKey rs_key
Definition: relscan.h:52

◆ heap_fetch()

bool heap_fetch ( Relation  relation,
Snapshot  snapshot,
HeapTuple  tuple,
Buffer userbuf,
bool  keep_buf,
Relation  stats_relation 
)

Definition at line 1903 of file heapam.c.

References buffer, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, CheckForSerializableConflictOut(), HeapTupleSatisfiesVisibility, InvalidBuffer, ItemIdGetLength, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, LockBuffer(), PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, pgstat_count_heap_fetch, PredicateLockTuple(), ReadBuffer(), RelationGetRelid, ReleaseBuffer(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, and TestForOldSnapshot().

Referenced by AfterTriggerExecute(), EvalPlanQualFetch(), EvalPlanQualFetchRowMarks(), ExecCheckTIDVisible(), ExecDelete(), ExecLockRows(), heap_lock_updated_tuple_rec(), and TidNext().

1909 {
1910  ItemPointer tid = &(tuple->t_self);
1911  ItemId lp;
1912  Buffer buffer;
1913  Page page;
1914  OffsetNumber offnum;
1915  bool valid;
1916 
1917  /*
1918  * Fetch and pin the appropriate page of the relation.
1919  */
1920  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
1921 
1922  /*
1923  * Need share lock on buffer to examine tuple commit status.
1924  */
1925  LockBuffer(buffer, BUFFER_LOCK_SHARE);
1926  page = BufferGetPage(buffer);
1927  TestForOldSnapshot(snapshot, relation, page);
1928 
1929  /*
1930  * We'd better check for out-of-range offnum in case of VACUUM since the
1931  * TID was obtained.
1932  */
1933  offnum = ItemPointerGetOffsetNumber(tid);
1934  if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(page))
1935  {
1936  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1937  if (keep_buf)
1938  *userbuf = buffer;
1939  else
1940  {
1941  ReleaseBuffer(buffer);
1942  *userbuf = InvalidBuffer;
1943  }
1944  tuple->t_data = NULL;
1945  return false;
1946  }
1947 
1948  /*
1949  * get the item line pointer corresponding to the requested tid
1950  */
1951  lp = PageGetItemId(page, offnum);
1952 
1953  /*
1954  * Must check for deleted tuple.
1955  */
1956  if (!ItemIdIsNormal(lp))
1957  {
1958  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1959  if (keep_buf)
1960  *userbuf = buffer;
1961  else
1962  {
1963  ReleaseBuffer(buffer);
1964  *userbuf = InvalidBuffer;
1965  }
1966  tuple->t_data = NULL;
1967  return false;
1968  }
1969 
1970  /*
1971  * fill in *tuple fields
1972  */
1973  tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1974  tuple->t_len = ItemIdGetLength(lp);
1975  tuple->t_tableOid = RelationGetRelid(relation);
1976 
1977  /*
1978  * check time qualification of tuple, then release lock
1979  */
1980  valid = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer);
1981 
1982  if (valid)
1983  PredicateLockTuple(relation, tuple, snapshot);
1984 
1985  CheckForSerializableConflictOut(valid, relation, tuple, buffer, snapshot);
1986 
1987  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1988 
1989  if (valid)
1990  {
1991  /*
1992  * All checks passed, so return the tuple as valid. Caller is now
1993  * responsible for releasing the buffer.
1994  */
1995  *userbuf = buffer;
1996 
1997  /* Count the successful fetch against appropriate rel, if any */
1998  if (stats_relation != NULL)
1999  pgstat_count_heap_fetch(stats_relation);
2000 
2001  return true;
2002  }
2003 
2004  /* Tuple failed time qual, but maybe caller wants to see it anyway. */
2005  if (keep_buf)
2006  *userbuf = buffer;
2007  else
2008  {
2009  ReleaseBuffer(buffer);
2010  *userbuf = InvalidBuffer;
2011  }
2012 
2013  return false;
2014 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
static void TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
Definition: bufmgr.h:265
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3899
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
ItemPointerData t_self
Definition: htup.h:65
#define pgstat_count_heap_fetch(rel)
Definition: pgstat.h:1286
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
void PredicateLockTuple(Relation relation, HeapTuple tuple, Snapshot snapshot)
Definition: predicate.c:2497
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
int Buffer
Definition: buf.h:23
#define RelationGetRelid(relation)
Definition: rel.h:407
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74

◆ heap_finish_speculative()

void heap_finish_speculative ( Relation  relation,
HeapTuple  tuple 
)

Definition at line 6158 of file heapam.c.

References Assert, buffer, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, elog, END_CRIT_SECTION, ERROR, HeapTupleHeaderIsSpeculative, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, LockBuffer(), MarkBufferDirty(), MaxOffsetNumber, xl_heap_confirm::offnum, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageSetLSN, ReadBuffer(), REGBUF_STANDARD, RelationNeedsWAL, SizeOfHeapConfirm, SpecTokenOffsetNumber, START_CRIT_SECTION, StaticAssertStmt, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, UnlockReleaseBuffer(), XLOG_HEAP_CONFIRM, XLOG_INCLUDE_ORIGIN, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), XLogRegisterData(), and XLogSetRecordFlags().

Referenced by ExecInsert().

6159 {
6160  Buffer buffer;
6161  Page page;
6162  OffsetNumber offnum;
6163  ItemId lp = NULL;
6164  HeapTupleHeader htup;
6165 
6166  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&(tuple->t_self)));
6168  page = (Page) BufferGetPage(buffer);
6169 
6170  offnum = ItemPointerGetOffsetNumber(&(tuple->t_self));
6171  if (PageGetMaxOffsetNumber(page) >= offnum)
6172  lp = PageGetItemId(page, offnum);
6173 
6174  if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
6175  elog(ERROR, "invalid lp");
6176 
6177  htup = (HeapTupleHeader) PageGetItem(page, lp);
6178 
6179  /* SpecTokenOffsetNumber should be distinguishable from any real offset */
6181  "invalid speculative token constant");
6182 
6183  /* NO EREPORT(ERROR) from here till changes are logged */
6185 
6187 
6188  MarkBufferDirty(buffer);
6189 
6190  /*
6191  * Replace the speculative insertion token with a real t_ctid, pointing to
6192  * itself like it does on regular tuples.
6193  */
6194  htup->t_ctid = tuple->t_self;
6195 
6196  /* XLOG stuff */
6197  if (RelationNeedsWAL(relation))
6198  {
6199  xl_heap_confirm xlrec;
6200  XLogRecPtr recptr;
6201 
6202  xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self);
6203 
6204  XLogBeginInsert();
6205 
6206  /* We want the same filtering on this as on a plain insert */
6208 
6209  XLogRegisterData((char *) &xlrec, SizeOfHeapConfirm);
6210  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
6211 
6212  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CONFIRM);
6213 
6214  PageSetLSN(page, recptr);
6215  }
6216 
6217  END_CRIT_SECTION();
6218 
6219  UnlockReleaseBuffer(buffer);
6220 }
OffsetNumber offnum
Definition: heapam_xlog.h:296
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define MaxOffsetNumber
Definition: off.h:28
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:428
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:192
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define SpecTokenOffsetNumber
Definition: itemptr.h:63
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:795
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
#define REGBUF_STANDARD
Definition: xloginsert.h:34
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define SizeOfHeapConfirm
Definition: heapam_xlog.h:299
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define RelationNeedsWAL(relation)
Definition: rel.h:510
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define XLOG_HEAP_CONFIRM
Definition: heapam_xlog.h:37

◆ heap_freeze_tuple()

bool heap_freeze_tuple ( HeapTupleHeader  tuple,
TransactionId  relfrozenxid,
TransactionId  relminmxid,
TransactionId  cutoff_xid,
TransactionId  cutoff_multi 
)

Definition at line 7043 of file heapam.c.

References heap_execute_freeze_tuple(), and heap_prepare_freeze_tuple().

Referenced by rewrite_heap_tuple().

7046 {
7048  bool do_freeze;
7049  bool tuple_totally_frozen;
7050 
7051  do_freeze = heap_prepare_freeze_tuple(tuple,
7053  cutoff_xid, cutoff_multi,
7054  &frz, &tuple_totally_frozen);
7055 
7056  /*
7057  * Note that because this is not a WAL-logged operation, we don't need to
7058  * fill in the offset in the freeze record.
7059  */
7060 
7061  if (do_freeze)
7062  heap_execute_freeze_tuple(tuple, &frz);
7063  return do_freeze;
7064 }
bool heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId relfrozenxid, TransactionId relminmxid, TransactionId cutoff_xid, TransactionId cutoff_multi, xl_heap_freeze_tuple *frz, bool *totally_frozen_p)
Definition: heapam.c:6800
void heap_execute_freeze_tuple(HeapTupleHeader tuple, xl_heap_freeze_tuple *frz)
Definition: heapam.c:7022
TransactionId relminmxid
Definition: pg_class.h:73
TransactionId relfrozenxid
Definition: pg_class.h:72

◆ heap_get_latest_tid()

void heap_get_latest_tid ( Relation  relation,
Snapshot  snapshot,
ItemPointer  tid 
)

Definition at line 2211 of file heapam.c.

References buffer, BUFFER_LOCK_SHARE, BufferGetPage, CheckForSerializableConflictOut(), elog, ERROR, HEAP_XMAX_INVALID, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleHeaderIndicatesMovedPartitions, HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesVisibility, InvalidTransactionId, ItemIdGetLength, ItemIdIsNormal, ItemPointerEquals(), ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerIsValid, LockBuffer(), PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, ReadBuffer(), RelationGetNumberOfBlocks, RelationGetRelationName, RelationGetRelid, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TestForOldSnapshot(), TransactionIdEquals, TransactionIdIsValid, and UnlockReleaseBuffer().

Referenced by currtid_byrelname(), currtid_byreloid(), and TidNext().

2214 {
2215  BlockNumber blk;
2216  ItemPointerData ctid;
2217  TransactionId priorXmax;
2218 
2219  /* this is to avoid Assert failures on bad input */
2220  if (!ItemPointerIsValid(tid))
2221  return;
2222 
2223  /*
2224  * Since this can be called with user-supplied TID, don't trust the input
2225  * too much. (RelationGetNumberOfBlocks is an expensive check, so we
2226  * don't check t_ctid links again this way. Note that it would not do to
2227  * call it just once and save the result, either.)
2228  */
2229  blk = ItemPointerGetBlockNumber(tid);
2230  if (blk >= RelationGetNumberOfBlocks(relation))
2231  elog(ERROR, "block number %u is out of range for relation \"%s\"",
2232  blk, RelationGetRelationName(relation));
2233 
2234  /*
2235  * Loop to chase down t_ctid links. At top of loop, ctid is the tuple we
2236  * need to examine, and *tid is the TID we will return if ctid turns out
2237  * to be bogus.
2238  *
2239  * Note that we will loop until we reach the end of the t_ctid chain.
2240  * Depending on the snapshot passed, there might be at most one visible
2241  * version of the row, but we don't try to optimize for that.
2242  */
2243  ctid = *tid;
2244  priorXmax = InvalidTransactionId; /* cannot check first XMIN */
2245  for (;;)
2246  {
2247  Buffer buffer;
2248  Page page;
2249  OffsetNumber offnum;
2250  ItemId lp;
2251  HeapTupleData tp;
2252  bool valid;
2253 
2254  /*
2255  * Read, pin, and lock the page.
2256  */
2257  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&ctid));
2258  LockBuffer(buffer, BUFFER_LOCK_SHARE);
2259  page = BufferGetPage(buffer);
2260  TestForOldSnapshot(snapshot, relation, page);
2261 
2262  /*
2263  * Check for bogus item number. This is not treated as an error
2264  * condition because it can happen while following a t_ctid link. We
2265  * just assume that the prior tid is OK and return it unchanged.
2266  */
2267  offnum = ItemPointerGetOffsetNumber(&ctid);
2268  if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(page))
2269  {
2270  UnlockReleaseBuffer(buffer);
2271  break;
2272  }
2273  lp = PageGetItemId(page, offnum);
2274  if (!ItemIdIsNormal(lp))
2275  {
2276  UnlockReleaseBuffer(buffer);
2277  break;
2278  }
2279 
2280  /* OK to access the tuple */
2281  tp.t_self = ctid;
2282  tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
2283  tp.t_len = ItemIdGetLength(lp);
2284  tp.t_tableOid = RelationGetRelid(relation);
2285 
2286  /*
2287  * After following a t_ctid link, we might arrive at an unrelated
2288  * tuple. Check for XMIN match.
2289  */
2290  if (TransactionIdIsValid(priorXmax) &&
2292  {
2293  UnlockReleaseBuffer(buffer);
2294  break;
2295  }
2296 
2297  /*
2298  * Check time qualification of tuple; if visible, set it as the new
2299  * result candidate.
2300  */
2301  valid = HeapTupleSatisfiesVisibility(&tp, snapshot, buffer);
2302  CheckForSerializableConflictOut(valid, relation, &tp, buffer, snapshot);
2303  if (valid)
2304  *tid = ctid;
2305 
2306  /*
2307  * If there's a valid t_ctid link, follow it, else we're done.
2308  */
2309  if ((tp.t_data->t_infomask & HEAP_XMAX_INVALID) ||
2313  {
2314  UnlockReleaseBuffer(buffer);
2315  break;
2316  }
2317 
2318  ctid = tp.t_data->t_ctid;
2319  priorXmax = HeapTupleHeaderGetUpdateXid(tp.t_data);
2320  UnlockReleaseBuffer(buffer);
2321  } /* end of loop */
2322 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1596
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
static void TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
Definition: bufmgr.h:265
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:474
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HeapTupleHeaderIndicatesMovedPartitions(tup)
Definition: htup_details.h:444
uint32 BlockNumber
Definition: block.h:31
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3899
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:206
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int Buffer
Definition: buf.h:23
#define RelationGetRelid(relation)
Definition: rel.h:407
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74

◆ heap_get_root_tuples()

void heap_get_root_tuples ( Page  page,
OffsetNumber root_offsets 
)

Definition at line 746 of file pruneheap.c.

References Assert, FirstOffsetNumber, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleHeaderIndicatesMovedPartitions, HeapTupleHeaderIsHeapOnly, HeapTupleHeaderIsHotUpdated, InvalidTransactionId, ItemIdGetRedirect, ItemIdIsDead, ItemIdIsNormal, ItemIdIsRedirected, ItemIdIsUsed, ItemPointerGetOffsetNumber, MaxHeapTuplesPerPage, MemSet, OffsetNumberNext, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, HeapTupleHeaderData::t_ctid, TransactionIdEquals, and TransactionIdIsValid.

Referenced by IndexBuildHeapRangeScan(), and validate_index_heapscan().

747 {
748  OffsetNumber offnum,
749  maxoff;
750 
751  MemSet(root_offsets, 0, MaxHeapTuplesPerPage * sizeof(OffsetNumber));
752 
753  maxoff = PageGetMaxOffsetNumber(page);
754  for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
755  {
756  ItemId lp = PageGetItemId(page, offnum);
757  HeapTupleHeader htup;
758  OffsetNumber nextoffnum;
759  TransactionId priorXmax;
760 
761  /* skip unused and dead items */
762  if (!ItemIdIsUsed(lp) || ItemIdIsDead(lp))
763  continue;
764 
765  if (ItemIdIsNormal(lp))
766  {
767  htup = (HeapTupleHeader) PageGetItem(page, lp);
768 
769  /*
770  * Check if this tuple is part of a HOT-chain rooted at some other
771  * tuple. If so, skip it for now; we'll process it when we find
772  * its root.
773  */
774  if (HeapTupleHeaderIsHeapOnly(htup))
775  continue;
776 
777  /*
778  * This is either a plain tuple or the root of a HOT-chain.
779  * Remember it in the mapping.
780  */
781  root_offsets[offnum - 1] = offnum;
782 
783  /* If it's not the start of a HOT-chain, we're done with it */
784  if (!HeapTupleHeaderIsHotUpdated(htup))
785  continue;
786 
787  /* Set up to scan the HOT-chain */
788  nextoffnum = ItemPointerGetOffsetNumber(&htup->t_ctid);
789  priorXmax = HeapTupleHeaderGetUpdateXid(htup);
790  }
791  else
792  {
793  /* Must be a redirect item. We do not set its root_offsets entry */
795  /* Set up to scan the HOT-chain */
796  nextoffnum = ItemIdGetRedirect(lp);
797  priorXmax = InvalidTransactionId;
798  }
799 
800  /*
801  * Now follow the HOT-chain and collect other tuples in the chain.
802  *
803  * Note: Even though this is a nested loop, the complexity of the
804  * function is O(N) because a tuple in the page should be visited not
805  * more than twice, once in the outer loop and once in HOT-chain
806  * chases.
807  */
808  for (;;)
809  {
810  lp = PageGetItemId(page, nextoffnum);
811 
812  /* Check for broken chains */
813  if (!ItemIdIsNormal(lp))
814  break;
815 
816  htup = (HeapTupleHeader) PageGetItem(page, lp);
817 
818  if (TransactionIdIsValid(priorXmax) &&
819  !TransactionIdEquals(priorXmax, HeapTupleHeaderGetXmin(htup)))
820  break;
821 
822  /* Remember the root line pointer for this item */
823  root_offsets[nextoffnum - 1] = offnum;
824 
825  /* Advance to next chain member, if any */
826  if (!HeapTupleHeaderIsHotUpdated(htup))
827  break;
828 
829  /* HOT implies it can't have moved to different partition */
831 
832  nextoffnum = ItemPointerGetOffsetNumber(&htup->t_ctid);
833  priorXmax = HeapTupleHeaderGetUpdateXid(htup);
834  }
835  }
836 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
#define ItemIdIsRedirected(itemId)
Definition: itemid.h:105
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:474
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define ItemIdGetRedirect(itemId)
Definition: itemid.h:77
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define MaxHeapTuplesPerPage
Definition: htup_details.h:587
#define MemSet(start, val, len)
Definition: c.h:908
#define HeapTupleHeaderIndicatesMovedPartitions(tup)
Definition: htup_details.h:444
#define ItemIdIsDead(itemId)
Definition: itemid.h:112
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
#define HeapTupleHeaderIsHeapOnly(tup)
Definition: htup_details.h:514
ItemPointerData t_ctid
Definition: htup_details.h:159
#define FirstOffsetNumber
Definition: off.h:27
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderIsHotUpdated(tup)
Definition: htup_details.h:497
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define Assert(condition)
Definition: c.h:699
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define PageGetItem(page, itemId)
Definition: bufpage.h:336

◆ heap_getnext()

HeapTuple heap_getnext ( HeapScanDesc  scan,
ScanDirection  direction 
)

Definition at line 1835 of file heapam.c.

References HEAPDEBUG_1, HEAPDEBUG_2, HEAPDEBUG_3, heapgettup(), heapgettup_pagemode(), pgstat_count_heap_getnext, HeapScanDescData::rs_ctup, HeapScanDescData::rs_key, HeapScanDescData::rs_nkeys, HeapScanDescData::rs_pageatatime, HeapScanDescData::rs_rd, and HeapTupleData::t_data.

Referenced by AlterDomainNotNull(), AlterTableMoveAll(), AlterTableSpaceOptions(), ATRewriteTable(), boot_openrel(), check_db_file_conflict(), check_default_allows_bound(), copy_heap_data(), CopyTo(), createdb(), DefineQueryRewrite(), do_autovacuum(), DropSetting(), DropTableSpace(), find_typed_table_dependencies(), get_all_vacuum_rels(), get_database_list(), get_subscription_list(), get_tables_to_cluster(), get_tablespace_name(), get_tablespace_oid(), GetAllTablesPublicationRelations(), getRelationsInNamespace(), gettype(), index_update_stats(), IndexBuildHeapRangeScan(), IndexCheckExclusion(), objectsInSchemaToOids(), pgrowlocks(), pgstat_collect_oids(), pgstat_heap(), ReindexMultipleTables(), RelationFindReplTupleSeq(), remove_dbtablespaces(), RemoveConversionById(), RemoveSubscriptionRel(), RenameTableSpace(), SeqNext(), systable_getnext(), ThereIsAtLeastOneRole(), vac_truncate_clog(), validate_index_heapscan(), validateCheckConstraint(), validateDomainConstraint(), and validateForeignKeyConstraint().

1836 {
1837  /* Note: no locking manipulations needed */
1838 
1839  HEAPDEBUG_1; /* heap_getnext( info ) */
1840 
1841  if (scan->rs_pageatatime)
1842  heapgettup_pagemode(scan, direction,
1843  scan->rs_nkeys, scan->rs_key);
1844  else
1845  heapgettup(scan, direction, scan->rs_nkeys, scan->rs_key);
1846 
1847  if (scan->rs_ctup.t_data == NULL)
1848  {
1849  HEAPDEBUG_2; /* heap_getnext returning EOS */
1850  return NULL;
1851  }
1852 
1853  /*
1854  * if we get here it means we have a new current scan tuple, so point to
1855  * the proper return buffer and return the tuple.
1856  */
1857  HEAPDEBUG_3; /* heap_getnext returning tuple */
1858 
1860 
1861  return &(scan->rs_ctup);
1862 }
#define HEAPDEBUG_2
Definition: heapam.c:1829
HeapTupleData rs_ctup
Definition: relscan.h:70
HeapTupleHeader t_data
Definition: htup.h:68
bool rs_pageatatime
Definition: relscan.h:55
#define HEAPDEBUG_1
Definition: heapam.c:1828
static void heapgettup(HeapScanDesc scan, ScanDirection dir, int nkeys, ScanKey key)
Definition: heapam.c:485
Relation rs_rd
Definition: relscan.h:49
#define HEAPDEBUG_3
Definition: heapam.c:1830
#define pgstat_count_heap_getnext(rel)
Definition: pgstat.h:1281
static void heapgettup_pagemode(HeapScanDesc scan, ScanDirection dir, int nkeys, ScanKey key)
Definition: heapam.c:789
ScanKey rs_key
Definition: relscan.h:52

◆ heap_hot_search()

bool heap_hot_search ( ItemPointer  tid,
Relation  relation,
Snapshot  snapshot,
bool all_dead 
)

Definition at line 2183 of file heapam.c.

References buffer, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, heap_hot_search_buffer(), ItemPointerGetBlockNumber, LockBuffer(), ReadBuffer(), and ReleaseBuffer().

Referenced by _bt_check_unique(), and unique_key_recheck().

2185 {
2186  bool result;
2187  Buffer buffer;
2188  HeapTupleData heapTuple;
2189 
2190  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
2191  LockBuffer(buffer, BUFFER_LOCK_SHARE);
2192  result = heap_hot_search_buffer(tid, relation, buffer, snapshot,
2193  &heapTuple, all_dead, true);
2194  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
2195  ReleaseBuffer(buffer);
2196  return result;
2197 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
bool heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, Snapshot snapshot, HeapTuple heapTuple, bool *all_dead, bool first_call)
Definition: heapam.c:2038
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
int Buffer
Definition: buf.h:23

◆ heap_hot_search_buffer()

bool heap_hot_search_buffer ( ItemPointer  tid,
Relation  relation,
Buffer  buffer,
Snapshot  snapshot,
HeapTuple  heapTuple,
bool all_dead,
bool  first_call 
)

Definition at line 2038 of file heapam.c.

References Assert, BufferGetBlockNumber(), BufferGetPage, CheckForSerializableConflictOut(), HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleIsHeapOnly, HeapTupleIsHotUpdated, HeapTupleIsSurelyDead(), HeapTupleSatisfiesVisibility, InvalidTransactionId, ItemIdGetLength, ItemIdGetRedirect, ItemIdIsNormal, ItemIdIsRedirected, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerSet, ItemPointerSetOffsetNumber, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PredicateLockTuple(), RecentGlobalXmin, RelationGetRelid, skip, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdEquals, and TransactionIdIsValid.

Referenced by bitgetpage(), heap_hot_search(), and index_fetch_heap().

2041 {
2042  Page dp = (Page) BufferGetPage(buffer);
2043  TransactionId prev_xmax = InvalidTransactionId;
2044  OffsetNumber offnum;
2045  bool at_chain_start;
2046  bool valid;
2047  bool skip;
2048 
2049  /* If this is not the first call, previous call returned a (live!) tuple */
2050  if (all_dead)
2051  *all_dead = first_call;
2052 
2054 
2056  offnum = ItemPointerGetOffsetNumber(tid);
2057  at_chain_start = first_call;
2058  skip = !first_call;
2059 
2060  heapTuple->t_self = *tid;
2061 
2062  /* Scan through possible multiple members of HOT-chain */
2063  for (;;)
2064  {
2065  ItemId lp;
2066 
2067  /* check for bogus TID */
2068  if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
2069  break;
2070 
2071  lp = PageGetItemId(dp, offnum);
2072 
2073  /* check for unused, dead, or redirected items */
2074  if (!ItemIdIsNormal(lp))
2075  {
2076  /* We should only see a redirect at start of chain */
2077  if (ItemIdIsRedirected(lp) && at_chain_start)
2078  {
2079  /* Follow the redirect */
2080  offnum = ItemIdGetRedirect(lp);
2081  at_chain_start = false;
2082  continue;
2083  }
2084  /* else must be end of chain */
2085  break;
2086  }
2087 
2088  heapTuple->t_data = (HeapTupleHeader) PageGetItem(dp, lp);
2089  heapTuple->t_len = ItemIdGetLength(lp);
2090  heapTuple->t_tableOid = RelationGetRelid(relation);
2091  ItemPointerSetOffsetNumber(&heapTuple->t_self, offnum);
2092 
2093  /*
2094  * Shouldn't see a HEAP_ONLY tuple at chain start.
2095  */
2096  if (at_chain_start && HeapTupleIsHeapOnly(heapTuple))
2097  break;
2098 
2099  /*
2100  * The xmin should match the previous xmax value, else chain is
2101  * broken.
2102  */
2103  if (TransactionIdIsValid(prev_xmax) &&
2104  !TransactionIdEquals(prev_xmax,
2105  HeapTupleHeaderGetXmin(heapTuple->t_data)))
2106  break;
2107 
2108  /*
2109  * When first_call is true (and thus, skip is initially false) we'll
2110  * return the first tuple we find. But on later passes, heapTuple
2111  * will initially be pointing to the tuple we returned last time.
2112  * Returning it again would be incorrect (and would loop forever), so
2113  * we skip it and return the next match we find.
2114  */
2115  if (!skip)
2116  {
2117  /*
2118  * For the benefit of logical decoding, have t_self point at the
2119  * element of the HOT chain we're currently investigating instead
2120  * of the root tuple of the HOT chain. This is important because
2121  * the *Satisfies routine for historical mvcc snapshots needs the
2122  * correct tid to decide about the visibility in some cases.
2123  */
2124  ItemPointerSet(&(heapTuple->t_self), BufferGetBlockNumber(buffer), offnum);
2125 
2126  /* If it's visible per the snapshot, we must return it */
2127  valid = HeapTupleSatisfiesVisibility(heapTuple, snapshot, buffer);
2128  CheckForSerializableConflictOut(valid, relation, heapTuple,
2129  buffer, snapshot);
2130  /* reset to original, non-redirected, tid */
2131  heapTuple->t_self = *tid;
2132 
2133  if (valid)
2134  {
2135  ItemPointerSetOffsetNumber(tid, offnum);
2136  PredicateLockTuple(relation, heapTuple, snapshot);
2137  if (all_dead)
2138  *all_dead = false;
2139  return true;
2140  }
2141  }
2142  skip = false;
2143 
2144  /*
2145  * If we can't see it, maybe no one else can either. At caller
2146  * request, check whether all chain members are dead to all
2147  * transactions.
2148  *
2149  * Note: if you change the criterion here for what is "dead", fix the
2150  * planner's get_actual_variable_range() function to match.
2151  */
2152  if (all_dead && *all_dead &&
2154  *all_dead = false;
2155 
2156  /*
2157  * Check to see if HOT chain continues past this tuple; if so fetch
2158  * the next offnum and loop around.
2159  */
2160  if (HeapTupleIsHotUpdated(heapTuple))
2161  {
2164  offnum = ItemPointerGetOffsetNumber(&heapTuple->t_data->t_ctid);
2165  at_chain_start = false;
2166  prev_xmax = HeapTupleHeaderGetUpdateXid(heapTuple->t_data);
2167  }
2168  else
2169  break; /* end of chain */
2170  }
2171 
2172  return false;
2173 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
#define ItemIdIsRedirected(itemId)
Definition: itemid.h:105
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:474
static const char * skip[]
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define ItemIdGetRedirect(itemId)
Definition: itemid.h:77
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3899
bool HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin)
Definition: tqual.c:1420
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleIsHotUpdated(tuple)
Definition: htup_details.h:689
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
TransactionId RecentGlobalXmin
Definition: snapmgr.c:166
#define InvalidTransactionId
Definition: transam.h:31
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define HeapTupleIsHeapOnly(tuple)
Definition: htup_details.h:698
#define Assert(condition)
Definition: c.h:699
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
void PredicateLockTuple(Relation relation, HeapTuple tuple, Snapshot snapshot)
Definition: predicate.c:2497
#define ItemPointerSetOffsetNumber(pointer, offsetNumber)
Definition: itemptr.h:148
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define RelationGetRelid(relation)
Definition: rel.h:407
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127

◆ heap_inplace_update()

void heap_inplace_update ( Relation  relation,
HeapTuple  tuple 
)

Definition at line 6390 of file heapam.c.

References buffer, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, CacheInvalidateHeapTuple(), elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, IsBootstrapProcessingMode, IsInParallelMode(), ItemIdGetLength, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, LockBuffer(), MarkBufferDirty(), xl_heap_inplace::offnum, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageSetLSN, ReadBuffer(), REGBUF_STANDARD, RelationNeedsWAL, SizeOfHeapInplace, START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleHeaderData::t_hoff, HeapTupleData::t_len, HeapTupleData::t_self, UnlockReleaseBuffer(), XLOG_HEAP_INPLACE, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by create_toast_table(), index_set_state_flags(), index_update_stats(), vac_update_datfrozenxid(), and vac_update_relstats().

6391 {
6392  Buffer buffer;
6393  Page page;
6394  OffsetNumber offnum;
6395  ItemId lp = NULL;
6396  HeapTupleHeader htup;
6397  uint32 oldlen;
6398  uint32 newlen;
6399 
6400  /*
6401  * For now, parallel operations are required to be strictly read-only.
6402  * Unlike a regular update, this should never create a combo CID, so it
6403  * might be possible to relax this restriction, but not without more
6404  * thought and testing. It's not clear that it would be useful, anyway.
6405  */
6406  if (IsInParallelMode())
6407  ereport(ERROR,
6408  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
6409  errmsg("cannot update tuples during a parallel operation")));
6410 
6411  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&(tuple->t_self)));
6413  page = (Page) BufferGetPage(buffer);
6414 
6415  offnum = ItemPointerGetOffsetNumber(&(tuple->t_self));
6416  if (PageGetMaxOffsetNumber(page) >= offnum)
6417  lp = PageGetItemId(page, offnum);
6418 
6419  if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
6420  elog(ERROR, "invalid lp");
6421 
6422  htup = (HeapTupleHeader) PageGetItem(page, lp);
6423 
6424  oldlen = ItemIdGetLength(lp) - htup->t_hoff;
6425  newlen = tuple->t_len - tuple->t_data->t_hoff;
6426  if (oldlen != newlen || htup->t_hoff != tuple->t_data->t_hoff)
6427  elog(ERROR, "wrong tuple length");
6428 
6429  /* NO EREPORT(ERROR) from here till changes are logged */
6431 
6432  memcpy((char *) htup + htup->t_hoff,
6433  (char *) tuple->t_data + tuple->t_data->t_hoff,
6434  newlen);
6435 
6436  MarkBufferDirty(buffer);
6437 
6438  /* XLOG stuff */
6439  if (RelationNeedsWAL(relation))
6440  {
6441  xl_heap_inplace xlrec;
6442  XLogRecPtr recptr;
6443 
6444  xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self);
6445 
6446  XLogBeginInsert();
6447  XLogRegisterData((char *) &xlrec, SizeOfHeapInplace);
6448 
6449  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
6450  XLogRegisterBufData(0, (char *) htup + htup->t_hoff, newlen);
6451 
6452  /* inplace updates aren't decoded atm, don't log the origin */
6453 
6454  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_INPLACE);
6455 
6456  PageSetLSN(page, recptr);
6457  }
6458 
6459  END_CRIT_SECTION();
6460 
6461  UnlockReleaseBuffer(buffer);
6462 
6463  /*
6464  * Send out shared cache inval if necessary. Note that because we only
6465  * pass the new version of the tuple, this mustn't be used for any
6466  * operations that could change catcache lookup keys. But we aren't
6467  * bothering with index updates either, so that's true a fortiori.
6468  */
6470  CacheInvalidateHeapTuple(relation, tuple, NULL);
6471 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1094
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define SizeOfHeapInplace
Definition: heapam_xlog.h:308
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
bool IsInParallelMode(void)
Definition: xact.c:905
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
#define REGBUF_STANDARD
Definition: xloginsert.h:34
unsigned int uint32
Definition: c.h:325
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
OffsetNumber offnum
Definition: heapam_xlog.h:304
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define XLOG_HEAP_INPLACE
Definition: heapam_xlog.h:39
#define RelationNeedsWAL(relation)
Definition: rel.h:510
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74

◆ heap_insert()

Oid heap_insert ( Relation  relation,
HeapTuple  tup,
CommandId  cid,
int  options,
BulkInsertState  bistate 
)

Definition at line 2441 of file heapam.c.

References Assert, buffer, BufferGetBlockNumber(), BufferGetPage, CacheInvalidateHeapTuple(), CheckForSerializableConflictIn(), END_CRIT_SECTION, FirstOffsetNumber, xl_heap_insert::flags, GetCurrentTransactionId(), heap_freetuple(), HEAP_INSERT_SKIP_WAL, HEAP_INSERT_SPECULATIVE, heap_prepare_insert(), HeapTupleGetOid, InvalidBuffer, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, log_heap_new_cid(), MarkBufferDirty(), xl_heap_insert::offnum, PageClearAllVisible, PageGetMaxOffsetNumber, PageIsAllVisible, PageSetLSN, pgstat_count_heap_insert(), REGBUF_KEEP_DATA, REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetBufferForTuple(), RelationIsAccessibleInLogicalDecoding, RelationIsLogicallyLogged, RelationNeedsWAL, RelationPutHeapTuple(), ReleaseBuffer(), SizeOfHeapHeader, SizeOfHeapInsert, SizeofHeapTupleHeader, START_CRIT_SECTION, HeapTupleData::t_data, xl_heap_header::t_hoff, HeapTupleHeaderData::t_hoff, xl_heap_header::t_infomask, HeapTupleHeaderData::t_infomask, xl_heap_header::t_infomask2, HeapTupleHeaderData::t_infomask2, HeapTupleData::t_len, HeapTupleData::t_self, UnlockReleaseBuffer(), visibilitymap_clear(), VISIBILITYMAP_VALID_BITS, XLH_INSERT_ALL_VISIBLE_CLEARED, XLH_INSERT_CONTAINS_NEW_TUPLE, XLH_INSERT_IS_SPECULATIVE, XLOG_HEAP_INIT_PAGE, XLOG_HEAP_INSERT, XLOG_INCLUDE_ORIGIN, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), XLogRegisterData(), and XLogSetRecordFlags().

Referenced by ATRewriteTable(), CopyFrom(), ExecInsert(), intorel_receive(), simple_heap_insert(), toast_save_datum(), and transientrel_receive().

2443 {
2445  HeapTuple heaptup;
2446  Buffer buffer;
2447  Buffer vmbuffer = InvalidBuffer;
2448  bool all_visible_cleared = false;
2449 
2450  /*
2451  * Fill in tuple header fields, assign an OID, and toast the tuple if
2452  * necessary.
2453  *
2454  * Note: below this point, heaptup is the data we actually intend to store
2455  * into the relation; tup is the caller's original untoasted data.
2456  */
2457  heaptup = heap_prepare_insert(relation, tup, xid, cid, options);
2458 
2459  /*
2460  * Find buffer to insert this tuple into. If the page is all visible,
2461  * this will also pin the requisite visibility map page.
2462  */
2463  buffer = RelationGetBufferForTuple(relation, heaptup->t_len,
2464  InvalidBuffer, options, bistate,
2465  &vmbuffer, NULL);
2466 
2467  /*
2468  * We're about to do the actual insert -- but check for conflict first, to
2469  * avoid possibly having to roll back work we've just done.
2470  *
2471  * This is safe without a recheck as long as there is no possibility of
2472  * another process scanning the page between this check and the insert
2473  * being visible to the scan (i.e., an exclusive buffer content lock is
2474  * continuously held from this point until the tuple insert is visible).
2475  *
2476  * For a heap insert, we only need to check for table-level SSI locks. Our
2477  * new tuple can't possibly conflict with existing tuple locks, and heap
2478  * page locks are only consolidated versions of tuple locks; they do not
2479  * lock "gaps" as index page locks do. So we don't need to specify a
2480  * buffer when making the call, which makes for a faster check.
2481  */
2483 
2484  /* NO EREPORT(ERROR) from here till changes are logged */
2486 
2487  RelationPutHeapTuple(relation, buffer, heaptup,
2488  (options & HEAP_INSERT_SPECULATIVE) != 0);
2489 
2490  if (PageIsAllVisible(BufferGetPage(buffer)))
2491  {
2492  all_visible_cleared = true;
2494  visibilitymap_clear(relation,
2495  ItemPointerGetBlockNumber(&(heaptup->t_self)),
2496  vmbuffer, VISIBILITYMAP_VALID_BITS);
2497  }
2498 
2499  /*
2500  * XXX Should we set PageSetPrunable on this page ?
2501  *
2502  * The inserting transaction may eventually abort thus making this tuple
2503  * DEAD and hence available for pruning. Though we don't want to optimize
2504  * for aborts, if no other tuple in this page is UPDATEd/DELETEd, the
2505  * aborted tuple will never be pruned until next vacuum is triggered.
2506  *
2507  * If you do add PageSetPrunable here, add it in heap_xlog_insert too.
2508  */
2509 
2510  MarkBufferDirty(buffer);
2511 
2512  /* XLOG stuff */
2513  if (!(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation))
2514  {
2515  xl_heap_insert xlrec;
2516  xl_heap_header xlhdr;
2517  XLogRecPtr recptr;
2518  Page page = BufferGetPage(buffer);
2519  uint8 info = XLOG_HEAP_INSERT;
2520  int bufflags = 0;
2521 
2522  /*
2523  * If this is a catalog, we need to transmit combocids to properly
2524  * decode, so log that as well.
2525  */
2527  log_heap_new_cid(relation, heaptup);
2528 
2529  /*
2530  * If this is the single and first tuple on page, we can reinit the
2531  * page instead of restoring the whole thing. Set flag, and hide
2532  * buffer references from XLogInsert.
2533  */
2534  if (ItemPointerGetOffsetNumber(&(heaptup->t_self)) == FirstOffsetNumber &&
2536  {
2537  info |= XLOG_HEAP_INIT_PAGE;
2538  bufflags |= REGBUF_WILL_INIT;
2539  }
2540 
2541  xlrec.offnum = ItemPointerGetOffsetNumber(&heaptup->t_self);
2542  xlrec.flags = 0;
2543  if (all_visible_cleared)
2548 
2549  /*
2550  * For logical decoding, we need the tuple even if we're doing a full
2551  * page write, so make sure it's included even if we take a full-page
2552  * image. (XXX We could alternatively store a pointer into the FPW).
2553  */
2554  if (RelationIsLogicallyLogged(relation))
2555  {
2557  bufflags |= REGBUF_KEEP_DATA;
2558  }
2559 
2560  XLogBeginInsert();
2561  XLogRegisterData((char *) &xlrec, SizeOfHeapInsert);
2562 
2563  xlhdr.t_infomask2 = heaptup->t_data->t_infomask2;
2564  xlhdr.t_infomask = heaptup->t_data->t_infomask;
2565  xlhdr.t_hoff = heaptup->t_data->t_hoff;
2566 
2567  /*
2568  * note we mark xlhdr as belonging to buffer; if XLogInsert decides to
2569  * write the whole page to the xlog, we don't need to store
2570  * xl_heap_header in the xlog.
2571  */
2572  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags);
2573  XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);
2574  /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
2576  (char *) heaptup->t_data + SizeofHeapTupleHeader,
2577  heaptup->t_len - SizeofHeapTupleHeader);
2578 
2579  /* filtering by origin on a row level is much more efficient */
2581 
2582  recptr = XLogInsert(RM_HEAP_ID, info);
2583 
2584  PageSetLSN(page, recptr);
2585  }
2586 
2587  END_CRIT_SECTION();
2588 
2589  UnlockReleaseBuffer(buffer);
2590  if (vmbuffer != InvalidBuffer)
2591  ReleaseBuffer(vmbuffer);
2592 
2593  /*
2594  * If tuple is cachable, mark it for invalidation from the caches in case
2595  * we abort. Note it is OK to do this after releasing the buffer, because
2596  * the heaptup data structure is all in local memory, not in the shared
2597  * buffer.
2598  */
2599  CacheInvalidateHeapTuple(relation, heaptup, NULL);
2600 
2601  /* Note: speculative insertions are counted too, even if aborted later */
2602  pgstat_count_heap_insert(relation, 1);
2603 
2604  /*
2605  * If heaptup is a private copy, release it. Don't forget to copy t_self
2606  * back to the caller's image, too.
2607  */
2608  if (heaptup != tup)
2609  {
2610  tup->t_self = heaptup->t_self;
2611  heap_freetuple(heaptup);
2612  }
2613 
2614  return HeapTupleGetOid(tup);
2615 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
#define SizeofHeapTupleHeader
Definition: htup_details.h:183
#define XLOG_HEAP_INSERT
Definition: heapam_xlog.h:32
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup)
Definition: heapam.c:7971
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1094
static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid, CommandId cid, int options)
Definition: heapam.c:2625
#define PageIsAllVisible(page)
Definition: bufpage.h:381
uint32 TransactionId
Definition: c.h:474
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
unsigned char uint8
Definition: c.h:323
#define XLH_INSERT_IS_SPECULATIVE
Definition: heapam_xlog.h:68
#define InvalidBuffer
Definition: buf.h:25
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
uint16 t_infomask2
Definition: heapam_xlog.h:144
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:192
#define HEAP_INSERT_SKIP_WAL
Definition: heapam.h:28
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define RelationIsLogicallyLogged(relation)
Definition: rel.h:580
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void RelationPutHeapTuple(Relation relation, Buffer buffer, HeapTuple tuple, bool token)
Definition: hio.c:36
void CheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: predicate.c:4280
#define XLOG_HEAP_INIT_PAGE
Definition: heapam_xlog.h:46
#define HEAP_INSERT_SPECULATIVE
Definition: heapam.h:31
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
HeapTupleHeader t_data
Definition: htup.h:68
bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define XLH_INSERT_CONTAINS_NEW_TUPLE
Definition: heapam_xlog.h:69
ItemPointerData t_self
Definition: htup.h:65
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define FirstOffsetNumber
Definition: off.h:27
#define REGBUF_STANDARD
Definition: xloginsert.h:34
Buffer RelationGetBufferForTuple(Relation relation, Size len, Buffer otherBuffer, int options, BulkInsertState bistate, Buffer *vmbuffer, Buffer *vmbuffer_other)
Definition: hio.c:313
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:564
#define REGBUF_KEEP_DATA
Definition: xloginsert.h:37
#define PageClearAllVisible(page)
Definition: bufpage.h:385
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
uint16 t_infomask
Definition: heapam_xlog.h:145
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define RelationNeedsWAL(relation)
Definition: rel.h:510
#define SizeOfHeapInsert
Definition: heapam_xlog.h:160
#define XLH_INSERT_ALL_VISIBLE_CLEARED
Definition: heapam_xlog.h:66
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
void pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
Definition: pgstat.c:1907
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
OffsetNumber offnum
Definition: heapam_xlog.h:154
#define SizeOfHeapHeader
Definition: heapam_xlog.h:149
Pointer Page
Definition: bufpage.h:74

◆ heap_lock_tuple()

HTSU_Result heap_lock_tuple ( Relation  relation,
HeapTuple  tuple,
CommandId  cid,
LockTupleMode  mode,
LockWaitPolicy  wait_policy,
bool  follow_update,
Buffer buffer,
HeapUpdateFailureData hufd 
)

Definition at line 4688 of file heapam.c.

References Assert, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetPage, BufferIsValid, HeapUpdateFailureData::cmax, compute_infobits(), compute_new_xmax_infomask(), ConditionalMultiXactIdWait(), ConditionalXactLockTableWait(), HeapUpdateFailureData::ctid, DoesMultiXactIdConflict(), elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, xl_heap_lock::flags, get_mxact_status_for_lock(), GetCurrentTransactionId(), GetMultiXactIdMembers(), heap_acquire_tuplock(), HEAP_KEYS_UPDATED, heap_lock_updated_tuple(), HEAP_XMAX_BITS, HEAP_XMAX_INVALID, HEAP_XMAX_IS_EXCL_LOCKED, HEAP_XMAX_IS_KEYSHR_LOCKED, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMAX_IS_SHR_LOCKED, HeapTupleBeingUpdated, HeapTupleHeaderClearHotUpdated, HeapTupleHeaderGetCmax(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderIsOnlyLocked(), HeapTupleHeaderSetXmax, HeapTupleInvisible, HeapTupleMayBeUpdated, HeapTupleSatisfiesUpdate(), HeapTupleSelfUpdated, HeapTupleUpdated, HeapTupleWouldBlock, i, xl_heap_lock::infobits_set, InvalidBuffer, InvalidCommandId, ItemIdGetLength, ItemIdIsNormal, ItemPointerCopy, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, LockBuffer(), xl_heap_lock::locking_xid, LockTupleExclusive, LockTupleKeyShare, LockTupleNoKeyExclusive, LockTupleShare, LockWaitBlock, LockWaitError, LockWaitSkip, MarkBufferDirty(), MultiXactIdSetOldestMember(), MultiXactIdWait(), MultiXactStatusNoKeyUpdate, xl_heap_lock::offnum, PageGetItem, PageGetItemId, PageIsAllVisible, PageSetLSN, pfree(), ReadBuffer(), REGBUF_STANDARD, RelationGetRelationName, RelationGetRelid, RelationNeedsWAL, ReleaseBuffer(), SizeOfHeapLock, START_CRIT_SECTION, status(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleHeaderData::t_infomask2, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TUPLOCK_from_mxstatus, UnlockTupleTuplock, UpdateXmaxHintBits(), VISIBILITYMAP_ALL_FROZEN, visibilitymap_clear(), visibilitymap_pin(), XactLockTableWait(), XLH_LOCK_ALL_FROZEN_CLEARED, XLOG_HEAP_LOCK, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), XLogRegisterData(), XLTW_Lock, HeapUpdateFailureData::xmax, and xmax_infomask_changed().

Referenced by EvalPlanQualFetch(), ExecLockRows(), ExecOnConflictUpdate(), GetTupleForTrigger(), RelationFindReplTupleByIndex(), and RelationFindReplTupleSeq().

4692 {
4693  HTSU_Result result;
4694  ItemPointer tid = &(tuple->t_self);
4695  ItemId lp;
4696  Page page;
4697  Buffer vmbuffer = InvalidBuffer;
4698  BlockNumber block;
4699  TransactionId xid,
4700  xmax;
4701  uint16 old_infomask,
4702  new_infomask,
4703  new_infomask2;
4704  bool first_time = true;
4705  bool have_tuple_lock = false;
4706  bool cleared_all_frozen = false;
4707 
4708  *buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
4709  block = ItemPointerGetBlockNumber(tid);
4710 
4711  /*
4712  * Before locking the buffer, pin the visibility map page if it appears to
4713  * be necessary. Since we haven't got the lock yet, someone else might be
4714  * in the middle of changing this, so we'll need to recheck after we have
4715  * the lock.
4716  */
4718  visibilitymap_pin(relation, block, &vmbuffer);
4719 
4721 
4722  page = BufferGetPage(*buffer);
4723  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
4724  Assert(ItemIdIsNormal(lp));
4725 
4726  tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
4727  tuple->t_len = ItemIdGetLength(lp);
4728  tuple->t_tableOid = RelationGetRelid(relation);
4729 
4730 l3:
4731  result = HeapTupleSatisfiesUpdate(tuple, cid, *buffer);
4732 
4733  if (result == HeapTupleInvisible)
4734  {
4735  /*
4736  * This is possible, but only when locking a tuple for ON CONFLICT
4737  * UPDATE. We return this value here rather than throwing an error in
4738  * order to give that case the opportunity to throw a more specific
4739  * error.
4740  */
4741  result = HeapTupleInvisible;
4742  goto out_locked;
4743  }
4744  else if (result == HeapTupleBeingUpdated || result == HeapTupleUpdated)
4745  {
4746  TransactionId xwait;
4747  uint16 infomask;
4748  uint16 infomask2;
4749  bool require_sleep;
4750  ItemPointerData t_ctid;
4751 
4752  /* must copy state data before unlocking buffer */
4753  xwait = HeapTupleHeaderGetRawXmax(tuple->t_data);
4754  infomask = tuple->t_data->t_infomask;
4755  infomask2 = tuple->t_data->t_infomask2;
4756  ItemPointerCopy(&tuple->t_data->t_ctid, &t_ctid);
4757 
4759 
4760  /*
4761  * If any subtransaction of the current top transaction already holds
4762  * a lock as strong as or stronger than what we're requesting, we
4763  * effectively hold the desired lock already. We *must* succeed
4764  * without trying to take the tuple lock, else we will deadlock
4765  * against anyone wanting to acquire a stronger lock.
4766  *
4767  * Note we only do this the first time we loop on the HTSU result;
4768  * there is no point in testing in subsequent passes, because
4769  * evidently our own transaction cannot have acquired a new lock after
4770  * the first time we checked.
4771  */
4772  if (first_time)
4773  {
4774  first_time = false;
4775 
4776  if (infomask & HEAP_XMAX_IS_MULTI)
4777  {
4778  int i;
4779  int nmembers;
4780  MultiXactMember *members;
4781 
4782  /*
4783  * We don't need to allow old multixacts here; if that had
4784  * been the case, HeapTupleSatisfiesUpdate would have returned
4785  * MayBeUpdated and we wouldn't be here.
4786  */
4787  nmembers =
4788  GetMultiXactIdMembers(xwait, &members, false,
4789  HEAP_XMAX_IS_LOCKED_ONLY(infomask));
4790 
4791  for (i = 0; i < nmembers; i++)
4792  {
4793  /* only consider members of our own transaction */
4794  if (!TransactionIdIsCurrentTransactionId(members[i].xid))
4795  continue;
4796 
4797  if (TUPLOCK_from_mxstatus(members[i].status) >= mode)
4798  {
4799  pfree(members);
4800  result = HeapTupleMayBeUpdated;
4801  goto out_unlocked;
4802  }
4803  }
4804 
4805  if (members)
4806  pfree(members);
4807  }
4808  else if (TransactionIdIsCurrentTransactionId(xwait))
4809  {
4810  switch (mode)
4811  {
4812  case LockTupleKeyShare:
4813  Assert(HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) ||
4814  HEAP_XMAX_IS_SHR_LOCKED(infomask) ||
4815  HEAP_XMAX_IS_EXCL_LOCKED(infomask));
4816  result = HeapTupleMayBeUpdated;
4817  goto out_unlocked;
4818  case LockTupleShare:
4819  if (HEAP_XMAX_IS_SHR_LOCKED(infomask) ||
4820  HEAP_XMAX_IS_EXCL_LOCKED(infomask))
4821  {
4822  result = HeapTupleMayBeUpdated;
4823  goto out_unlocked;
4824  }
4825  break;
4827  if (HEAP_XMAX_IS_EXCL_LOCKED(infomask))
4828  {
4829  result = HeapTupleMayBeUpdated;
4830  goto out_unlocked;
4831  }
4832  break;
4833  case LockTupleExclusive:
4834  if (HEAP_XMAX_IS_EXCL_LOCKED(infomask) &&
4835  infomask2 & HEAP_KEYS_UPDATED)
4836  {
4837  result = HeapTupleMayBeUpdated;
4838  goto out_unlocked;
4839  }
4840  break;
4841  }
4842  }
4843  }
4844 
4845  /*
4846  * Initially assume that we will have to wait for the locking
4847  * transaction(s) to finish. We check various cases below in which
4848  * this can be turned off.
4849  */
4850  require_sleep = true;
4851  if (mode == LockTupleKeyShare)
4852  {
4853  /*
4854  * If we're requesting KeyShare, and there's no update present, we
4855  * don't need to wait. Even if there is an update, we can still
4856  * continue if the key hasn't been modified.
4857  *
4858  * However, if there are updates, we need to walk the update chain
4859  * to mark future versions of the row as locked, too. That way,
4860  * if somebody deletes that future version, we're protected
4861  * against the key going away. This locking of future versions
4862  * could block momentarily, if a concurrent transaction is
4863  * deleting a key; or it could return a value to the effect that
4864  * the transaction deleting the key has already committed. So we
4865  * do this before re-locking the buffer; otherwise this would be
4866  * prone to deadlocks.
4867  *
4868  * Note that the TID we're locking was grabbed before we unlocked
4869  * the buffer. For it to change while we're not looking, the
4870  * other properties we're testing for below after re-locking the
4871  * buffer would also change, in which case we would restart this
4872  * loop above.
4873  */
4874  if (!(infomask2 & HEAP_KEYS_UPDATED))
4875  {
4876  bool updated;
4877 
4878  updated = !HEAP_XMAX_IS_LOCKED_ONLY(infomask);
4879 
4880  /*
4881  * If there are updates, follow the update chain; bail out if
4882  * that cannot be done.
4883  */
4884  if (follow_updates && updated)
4885  {
4886  HTSU_Result res;
4887 
4888  res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
4890  mode);
4891  if (res != HeapTupleMayBeUpdated)
4892  {
4893  result = res;
4894  /* recovery code expects to have buffer lock held */
4896  goto failed;
4897  }
4898  }
4899 
4901 
4902  /*
4903  * Make sure it's still an appropriate lock, else start over.
4904  * Also, if it wasn't updated before we released the lock, but
4905  * is updated now, we start over too; the reason is that we
4906  * now need to follow the update chain to lock the new
4907  * versions.
4908  */
4909  if (!HeapTupleHeaderIsOnlyLocked(tuple->t_data) &&
4910  ((tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED) ||
4911  !updated))
4912  goto l3;
4913 
4914  /* Things look okay, so we can skip sleeping */
4915  require_sleep = false;
4916 
4917  /*
4918  * Note we allow Xmax to change here; other updaters/lockers
4919  * could have modified it before we grabbed the buffer lock.
4920  * However, this is not a problem, because with the recheck we
4921  * just did we ensure that they still don't conflict with the
4922  * lock we want.
4923  */
4924  }
4925  }
4926  else if (mode == LockTupleShare)
4927  {
4928  /*
4929  * If we're requesting Share, we can similarly avoid sleeping if
4930  * there's no update and no exclusive lock present.
4931  */
4932  if (HEAP_XMAX_IS_LOCKED_ONLY(infomask) &&
4933  !HEAP_XMAX_IS_EXCL_LOCKED(infomask))
4934  {
4936 
4937  /*
4938  * Make sure it's still an appropriate lock, else start over.
4939  * See above about allowing xmax to change.
4940  */
4941  if (!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_data->t_infomask) ||
4943  goto l3;
4944  require_sleep = false;
4945  }
4946  }
4947  else if (mode == LockTupleNoKeyExclusive)
4948  {
4949  /*
4950  * If we're requesting NoKeyExclusive, we might also be able to
4951  * avoid sleeping; just ensure that there no conflicting lock
4952  * already acquired.
4953  */
4954  if (infomask & HEAP_XMAX_IS_MULTI)
4955  {
4956  if (!DoesMultiXactIdConflict((MultiXactId) xwait, infomask,
4957  mode))
4958  {
4959  /*
4960  * No conflict, but if the xmax changed under us in the
4961  * meantime, start over.
4962  */
4964  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
4966  xwait))
4967  goto l3;
4968 
4969  /* otherwise, we're good */
4970  require_sleep = false;
4971  }
4972  }
4973  else if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask))
4974  {
4976 
4977  /* if the xmax changed in the meantime, start over */
4978  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
4981  xwait))
4982  goto l3;
4983  /* otherwise, we're good */
4984  require_sleep = false;
4985  }
4986  }
4987 
4988  /*
4989  * As a check independent from those above, we can also avoid sleeping
4990  * if the current transaction is the sole locker of the tuple. Note
4991  * that the strength of the lock already held is irrelevant; this is
4992  * not about recording the lock in Xmax (which will be done regardless
4993  * of this optimization, below). Also, note that the cases where we
4994  * hold a lock stronger than we are requesting are already handled
4995  * above by not doing anything.
4996  *
4997  * Note we only deal with the non-multixact case here; MultiXactIdWait
4998  * is well equipped to deal with this situation on its own.
4999  */
5000  if (require_sleep && !(infomask & HEAP_XMAX_IS_MULTI) &&
5002  {
5003  /* ... but if the xmax changed in the meantime, start over */
5005  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
5007  xwait))
5008  goto l3;
5010  require_sleep = false;
5011  }
5012 
5013  /*
5014  * Time to sleep on the other transaction/multixact, if necessary.
5015  *
5016  * If the other transaction is an update that's already committed,
5017  * then sleeping cannot possibly do any good: if we're required to
5018  * sleep, get out to raise an error instead.
5019  *
5020  * By here, we either have already acquired the buffer exclusive lock,
5021  * or we must wait for the locking transaction or multixact; so below
5022  * we ensure that we grab buffer lock after the sleep.
5023  */
5024  if (require_sleep && result == HeapTupleUpdated)
5025  {
5027  goto failed;
5028  }
5029  else if (require_sleep)
5030  {
5031  /*
5032  * Acquire tuple lock to establish our priority for the tuple, or
5033  * die trying. LockTuple will release us when we are next-in-line
5034  * for the tuple. We must do this even if we are share-locking.
5035  *
5036  * If we are forced to "start over" below, we keep the tuple lock;
5037  * this arranges that we stay at the head of the line while
5038  * rechecking tuple state.
5039  */
5040  if (!heap_acquire_tuplock(relation, tid, mode, wait_policy,
5041  &have_tuple_lock))
5042  {
5043  /*
5044  * This can only happen if wait_policy is Skip and the lock
5045  * couldn't be obtained.
5046  */
5047  result = HeapTupleWouldBlock;
5048  /* recovery code expects to have buffer lock held */
5050  goto failed;
5051  }
5052 
5053  if (infomask & HEAP_XMAX_IS_MULTI)
5054  {
5056 
5057  /* We only ever lock tuples, never update them */
5058  if (status >= MultiXactStatusNoKeyUpdate)
5059  elog(ERROR, "invalid lock mode in heap_lock_tuple");
5060 
5061  /* wait for multixact to end, or die trying */
5062  switch (wait_policy)
5063  {
5064  case LockWaitBlock:
5065  MultiXactIdWait((MultiXactId) xwait, status, infomask,
5066  relation, &tuple->t_self, XLTW_Lock, NULL);
5067  break;
5068  case LockWaitSkip:
5070  status, infomask, relation,
5071  NULL))
5072  {
5073  result = HeapTupleWouldBlock;
5074  /* recovery code expects to have buffer lock held */
5076  goto failed;
5077  }
5078  break;
5079  case LockWaitError:
5081  status, infomask, relation,
5082  NULL))
5083  ereport(ERROR,
5084  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
5085  errmsg("could not obtain lock on row in relation \"%s\"",
5086  RelationGetRelationName(relation))));
5087 
5088  break;
5089  }
5090 
5091  /*
5092  * Of course, the multixact might not be done here: if we're
5093  * requesting a light lock mode, other transactions with light
5094  * locks could still be alive, as well as locks owned by our
5095  * own xact or other subxacts of this backend. We need to
5096  * preserve the surviving MultiXact members. Note that it
5097  * isn't absolutely necessary in the latter case, but doing so
5098  * is simpler.
5099  */
5100  }
5101  else
5102  {
5103  /* wait for regular transaction to end, or die trying */
5104  switch (wait_policy)
5105  {
5106  case LockWaitBlock:
5107  XactLockTableWait(xwait, relation, &tuple->t_self,
5108  XLTW_Lock);
5109  break;
5110  case LockWaitSkip:
5111  if (!ConditionalXactLockTableWait(xwait))
5112  {
5113  result = HeapTupleWouldBlock;
5114  /* recovery code expects to have buffer lock held */
5116  goto failed;
5117  }
5118  break;
5119  case LockWaitError:
5120  if (!ConditionalXactLockTableWait(xwait))
5121  ereport(ERROR,
5122  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
5123  errmsg("could not obtain lock on row in relation \"%s\"",
5124  RelationGetRelationName(relation))));
5125  break;
5126  }
5127  }
5128 
5129  /* if there are updates, follow the update chain */
5130  if (follow_updates && !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
5131  {
5132  HTSU_Result res;
5133 
5134  res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
5136  mode);
5137  if (res != HeapTupleMayBeUpdated)
5138  {
5139  result = res;
5140  /* recovery code expects to have buffer lock held */
5142  goto failed;
5143  }
5144  }
5145 
5147 
5148  /*
5149  * xwait is done, but if xwait had just locked the tuple then some
5150  * other xact could update this tuple before we get to this point.
5151  * Check for xmax change, and start over if so.
5152  */
5153  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
5155  xwait))
5156  goto l3;
5157 
5158  if (!(infomask & HEAP_XMAX_IS_MULTI))
5159  {
5160  /*
5161  * Otherwise check if it committed or aborted. Note we cannot
5162  * be here if the tuple was only locked by somebody who didn't
5163  * conflict with us; that would have been handled above. So
5164  * that transaction must necessarily be gone by now. But
5165  * don't check for this in the multixact case, because some
5166  * locker transactions might still be running.
5167  */
5168  UpdateXmaxHintBits(tuple->t_data, *buffer, xwait);
5169  }
5170  }
5171 
5172  /* By here, we're certain that we hold buffer exclusive lock again */
5173 
5174  /*
5175  * We may lock if previous xmax aborted, or if it committed but only
5176  * locked the tuple without updating it; or if we didn't have to wait
5177  * at all for whatever reason.
5178  */
5179  if (!require_sleep ||
5180  (tuple->t_data->t_infomask & HEAP_XMAX_INVALID) ||
5183  result = HeapTupleMayBeUpdated;
5184  else
5185  result = HeapTupleUpdated;
5186  }
5187 
5188 failed:
5189  if (result != HeapTupleMayBeUpdated)
5190  {
5191  Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated ||
5192  result == HeapTupleWouldBlock);
5193  Assert(!(tuple->t_data->t_infomask & HEAP_XMAX_INVALID));
5194  hufd->ctid = tuple->t_data->t_ctid;
5195  hufd->xmax = HeapTupleHeaderGetUpdateXid(tuple->t_data);
5196  if (result == HeapTupleSelfUpdated)
5197  hufd->cmax = HeapTupleHeaderGetCmax(tuple->t_data);
5198  else
5199  hufd->cmax = InvalidCommandId;
5200  goto out_locked;
5201  }
5202 
5203  /*
5204  * If we didn't pin the visibility map page and the page has become all
5205  * visible while we were busy locking the buffer, or during some
5206  * subsequent window during which we had it unlocked, we'll have to unlock
5207  * and re-lock, to avoid holding the buffer lock across I/O. That's a bit
5208  * unfortunate, especially since we'll now have to recheck whether the
5209  * tuple has been locked or updated under us, but hopefully it won't
5210  * happen very often.
5211  */
5212  if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
5213  {
5215  visibilitymap_pin(relation, block, &vmbuffer);
5217  goto l3;
5218  }
5219 
5220  xmax = HeapTupleHeaderGetRawXmax(tuple->t_data);
5221  old_infomask = tuple->t_data->t_infomask;
5222 
5223  /*
5224  * If this is the first possibly-multixact-able operation in the current
5225  * transaction, set my per-backend OldestMemberMXactId setting. We can be
5226  * certain that the transaction will never become a member of any older
5227  * MultiXactIds than that. (We have to do this even if we end up just
5228  * using our own TransactionId below, since some other backend could
5229  * incorporate our XID into a MultiXact immediately afterwards.)
5230  */
5232 
5233  /*
5234  * Compute the new xmax and infomask to store into the tuple. Note we do
5235  * not modify the tuple just yet, because that would leave it in the wrong
5236  * state if multixact.c elogs.
5237  */
5238  compute_new_xmax_infomask(xmax, old_infomask, tuple->t_data->t_infomask2,
5239  GetCurrentTransactionId(), mode, false,
5240  &xid, &new_infomask, &new_infomask2);
5241 
5243 
5244  /*
5245  * Store transaction information of xact locking the tuple.
5246  *
5247  * Note: Cmax is meaningless in this context, so don't set it; this avoids
5248  * possibly generating a useless combo CID. Moreover, if we're locking a
5249  * previously updated tuple, it's important to preserve the Cmax.
5250  *
5251  * Also reset the HOT UPDATE bit, but only if there's no update; otherwise
5252  * we would break the HOT chain.
5253  */
5254  tuple->t_data->t_infomask &= ~HEAP_XMAX_BITS;
5255  tuple->t_data->t_infomask2 &= ~HEAP_KEYS_UPDATED;
5256  tuple->t_data->t_infomask |= new_infomask;
5257  tuple->t_data->t_infomask2 |= new_infomask2;
5258  if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask))
5260  HeapTupleHeaderSetXmax(tuple->t_data, xid);
5261 
5262  /*
5263  * Make sure there is no forward chain link in t_ctid. Note that in the
5264  * cases where the tuple has been updated, we must not overwrite t_ctid,
5265  * because it was set by the updater. Moreover, if the tuple has been
5266  * updated, we need to follow the update chain to lock the new versions of
5267  * the tuple as well.
5268  */
5269  if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask))
5270  tuple->t_data->t_ctid = *tid;
5271 
5272  /* Clear only the all-frozen bit on visibility map if needed */
5273  if (PageIsAllVisible(page) &&
5274  visibilitymap_clear(relation, block, vmbuffer,
5276  cleared_all_frozen = true;
5277 
5278 
5280 
5281  /*
5282  * XLOG stuff. You might think that we don't need an XLOG record because
5283  * there is no state change worth restoring after a crash. You would be
5284  * wrong however: we have just written either a TransactionId or a
5285  * MultiXactId that may never have been seen on disk before, and we need
5286  * to make sure that there are XLOG entries covering those ID numbers.
5287  * Else the same IDs might be re-used after a crash, which would be
5288  * disastrous if this page made it to disk before the crash. Essentially
5289  * we have to enforce the WAL log-before-data rule even in this case.
5290  * (Also, in a PITR log-shipping or 2PC environment, we have to have XLOG
5291  * entries for everything anyway.)
5292  */
5293  if (RelationNeedsWAL(relation))
5294  {
5295  xl_heap_lock xlrec;
5296  XLogRecPtr recptr;
5297 
5298  XLogBeginInsert();
5300 
5301  xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self);
5302  xlrec.locking_xid = xid;
5303  xlrec.infobits_set = compute_infobits(new_infomask,
5304  tuple->t_data->t_infomask2);
5305  xlrec.flags = cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0;
5306  XLogRegisterData((char *) &xlrec, SizeOfHeapLock);
5307 
5308  /* we don't decode row locks atm, so no need to log the origin */
5309 
5310  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_LOCK);
5311 
5312  PageSetLSN(page, recptr);
5313  }
5314 
5315  END_CRIT_SECTION();
5316 
5317  result = HeapTupleMayBeUpdated;
5318 
5319 out_locked:
5321 
5322 out_unlocked:
5323  if (BufferIsValid(vmbuffer))
5324  ReleaseBuffer(vmbuffer);
5325 
5326  /*
5327  * Don't update the visibility map here. Locking a tuple doesn't change
5328  * visibility info.
5329  */
5330 
5331  /*
5332  * Now that we have successfully marked the tuple as locked, we can
5333  * release the lmgr tuple lock, if we had it.
5334  */
5335  if (have_tuple_lock)
5336  UnlockTupleTuplock(relation, tid, mode);
5337 
5338  return result;
5339 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1596
MultiXactStatus
Definition: multixact.h:40
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define HEAP_XMAX_BITS
Definition: htup_details.h:269
OffsetNumber offnum
Definition: heapam_xlog.h:275
static uint8 compute_infobits(uint16 infomask, uint16 infomask2)
Definition: heapam.c:2999
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define PageIsAllVisible(page)
Definition: bufpage.h:381
#define XLH_LOCK_ALL_FROZEN_CLEARED
Definition: heapam_xlog.h:269
TransactionId locking_xid
Definition: heapam_xlog.h:274
uint32 TransactionId
Definition: c.h:474
HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, Buffer buffer)
Definition: tqual.c:460
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:765
void visibilitymap_pin(Relation rel, BlockNumber heapBlk, Buffer *buf)
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define VISIBILITYMAP_ALL_FROZEN
Definition: visibilitymap.h:27
static bool xmax_infomask_changed(uint16 new_infomask, uint16 old_infomask)
Definition: heapam.c:3021
#define HeapTupleHeaderClearHotUpdated(tup)
Definition: htup_details.h:509
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define InvalidBuffer
Definition: buf.h:25
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define UnlockTupleTuplock(rel, tup, mode)
Definition: heapam.c:187
bool ConditionalXactLockTableWait(TransactionId xid)
Definition: lmgr.c:627
#define HEAP_XMAX_IS_SHR_LOCKED(infomask)
Definition: htup_details.h:261
void MultiXactIdSetOldestMember(void)
Definition: multixact.c:623
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
unsigned short uint16
Definition: c.h:324
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:206
int8 infobits_set
Definition: heapam_xlog.h:276
ItemPointerData t_ctid
Definition: htup_details.h:159
ItemPointerData t_self
Definition: htup.h:65
static void MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, Relation rel, ItemPointer ctid, XLTW_Oper oper, int *remaining)
Definition: heapam.c:7387
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define REGBUF_STANDARD
Definition: xloginsert.h:34
CommandId cmax
Definition: heapam.h:72
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:379
HTSU_Result
Definition: snapshot.h:121
#define RelationGetRelationName(relation)
Definition: rel.h:441
Oid t_tableOid
Definition: htup.h:66
#define SizeOfHeapLock
Definition: heapam_xlog.h:280
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask, uint16 old_infomask2, TransactionId add_to_xmax, LockTupleMode mode, bool is_update, TransactionId *result_xmax, uint16 *result_infomask, uint16 *result_infomask2)
Definition: heapam.c:5403
TransactionId xmax
Definition: heapam.h:71
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define InvalidCommandId
Definition: c.h:491
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:229
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define HEAP_KEYS_UPDATED
Definition: htup_details.h:277
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:207
static void UpdateXmaxHintBits(HeapTupleHeader tuple, Buffer buffer, TransactionId xid)
Definition: heapam.c:2342
static bool heap_acquire_tuplock(Relation relation, ItemPointer tid, LockTupleMode mode, LockWaitPolicy wait_policy, bool *have_tuple_lock)
Definition: heapam.c:5354
TransactionId MultiXactId
Definition: c.h:484
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
Definition: lmgr.h:29
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:119
static bool DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, LockTupleMode lockmode)
Definition: heapam.c:7220
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define RelationNeedsWAL(relation)
Definition: rel.h:510
#define TUPLOCK_from_mxstatus(status)
Definition: heapam.c:207
static HTSU_Result heap_lock_updated_tuple(Relation rel, HeapTuple tuple, ItemPointer ctid, TransactionId xid, LockTupleMode mode)
Definition: heapam.c:6113
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define XLOG_HEAP_LOCK
Definition: heapam_xlog.h:38
int i
static MultiXactStatus get_mxact_status_for_lock(LockTupleMode mode, bool is_update)
Definition: heapam.c:4635
ItemPointerData ctid
Definition: heapam.h:70
#define HEAP_XMAX_IS_EXCL_LOCKED(infomask)
Definition: htup_details.h:263
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool onlyLock)
Definition: multixact.c:1202
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98
#define HEAP_XMAX_IS_KEYSHR_LOCKED(infomask)
Definition: htup_details.h:265
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define RelationGetRelid(relation)
Definition: rel.h:407
static bool ConditionalMultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, Relation rel, int *remaining)
Definition: heapam.c:7409
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define ItemPointerCopy(fromPointer, toPointer)
Definition: itemptr.h:161

◆ heap_multi_insert()

void heap_multi_insert ( Relation  relation,
HeapTuple tuples,
int  ntuples,
CommandId  cid,
int  options,
BulkInsertState  bistate 
)

Definition at line 2705 of file heapam.c.

References Assert, buffer, BufferGetBlockNumber(), BufferGetPage, CacheInvalidateHeapTuple(), CHECK_FOR_INTERRUPTS, CheckForSerializableConflictIn(), xl_multi_insert_tuple::datalen, END_CRIT_SECTION, FirstOffsetNumber, xl_heap_multi_insert::flags, GetCurrentTransactionId(), HEAP_DEFAULT_FILLFACTOR, HEAP_INSERT_SKIP_WAL, heap_prepare_insert(), i, InvalidBuffer, IsCatalogRelation(), ItemPointerGetOffsetNumber, log_heap_new_cid(), MarkBufferDirty(), MAXALIGN, xl_heap_multi_insert::ntuples, xl_heap_multi_insert::offsets, PageClearAllVisible, PageGetHeapFreeSpace(), PageGetMaxOffsetNumber, PageIsAllVisible, PageSetLSN, palloc(), pgstat_count_heap_insert(), REGBUF_KEEP_DATA, REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetBufferForTuple(), RelationGetTargetPageFreeSpace, RelationIsAccessibleInLogicalDecoding, RelationIsLogicallyLogged, RelationNeedsWAL, RelationPutHeapTuple(), ReleaseBuffer(), SHORTALIGN, SizeOfHeapMultiInsert, SizeofHeapTupleHeader, SizeOfMultiInsertTuple, START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleHeaderData::t_hoff, xl_multi_insert_tuple::t_hoff, HeapTupleHeaderData::t_infomask, xl_multi_insert_tuple::t_infomask, HeapTupleHeaderData::t_infomask2, xl_multi_insert_tuple::t_infomask2, HeapTupleData::t_len, HeapTupleData::t_self, UnlockReleaseBuffer(), visibilitymap_clear(), VISIBILITYMAP_VALID_BITS, XLH_INSERT_ALL_VISIBLE_CLEARED, XLH_INSERT_CONTAINS_NEW_TUPLE, XLH_INSERT_LAST_IN_MULTI, XLOG_HEAP2_MULTI_INSERT, XLOG_HEAP_INIT_PAGE, XLOG_INCLUDE_ORIGIN, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), XLogRegisterData(), and XLogSetRecordFlags().

Referenced by CopyFromInsertBatch().

2707 {
2709  HeapTuple *heaptuples;
2710  int i;
2711  int ndone;
2712  char *scratch = NULL;
2713  Page page;
2714  bool needwal;
2715  Size saveFreeSpace;
2716  bool need_tuple_data = RelationIsLogicallyLogged(relation);
2717  bool need_cids = RelationIsAccessibleInLogicalDecoding(relation);
2718 
2719  needwal = !(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation);
2720  saveFreeSpace = RelationGetTargetPageFreeSpace(relation,
2722 
2723  /* Toast and set header data in all the tuples */
2724  heaptuples = palloc(ntuples * sizeof(HeapTuple));
2725  for (i = 0; i < ntuples; i++)
2726  heaptuples[i] = heap_prepare_insert(relation, tuples[i],
2727  xid, cid, options);
2728 
2729  /*
2730  * Allocate some memory to use for constructing the WAL record. Using
2731  * palloc() within a critical section is not safe, so we allocate this
2732  * beforehand.
2733  */
2734  if (needwal)
2735  scratch = palloc(BLCKSZ);
2736 
2737  /*
2738  * We're about to do the actual inserts -- but check for conflict first,
2739  * to minimize the possibility of having to roll back work we've just
2740  * done.
2741  *
2742  * A check here does not definitively prevent a serialization anomaly;
2743  * that check MUST be done at least past the point of acquiring an
2744  * exclusive buffer content lock on every buffer that will be affected,
2745  * and MAY be done after all inserts are reflected in the buffers and
2746  * those locks are released; otherwise there race condition. Since
2747  * multiple buffers can be locked and unlocked in the loop below, and it
2748  * would not be feasible to identify and lock all of those buffers before
2749  * the loop, we must do a final check at the end.
2750  *
2751  * The check here could be omitted with no loss of correctness; it is
2752  * present strictly as an optimization.
2753  *
2754  * For heap inserts, we only need to check for table-level SSI locks. Our
2755  * new tuples can't possibly conflict with existing tuple locks, and heap
2756  * page locks are only consolidated versions of tuple locks; they do not
2757  * lock "gaps" as index page locks do. So we don't need to specify a
2758  * buffer when making the call, which makes for a faster check.
2759  */
2761 
2762  ndone = 0;
2763  while (ndone < ntuples)
2764  {
2765  Buffer buffer;
2766  Buffer vmbuffer = InvalidBuffer;
2767  bool all_visible_cleared = false;
2768  int nthispage;
2769 
2771 
2772  /*
2773  * Find buffer where at least the next tuple will fit. If the page is
2774  * all-visible, this will also pin the requisite visibility map page.
2775  */
2776  buffer = RelationGetBufferForTuple(relation, heaptuples[ndone]->t_len,
2777  InvalidBuffer, options, bistate,
2778  &vmbuffer, NULL);
2779  page = BufferGetPage(buffer);
2780 
2781  /* NO EREPORT(ERROR) from here till changes are logged */
2783 
2784  /*
2785  * RelationGetBufferForTuple has ensured that the first tuple fits.
2786  * Put that on the page, and then as many other tuples as fit.
2787  */
2788  RelationPutHeapTuple(relation, buffer, heaptuples[ndone], false);
2789  for (nthispage = 1; ndone + nthispage < ntuples; nthispage++)
2790  {
2791  HeapTuple heaptup = heaptuples[ndone + nthispage];
2792 
2793  if (PageGetHeapFreeSpace(page) < MAXALIGN(heaptup->t_len) + saveFreeSpace)
2794  break;
2795 
2796  RelationPutHeapTuple(relation, buffer, heaptup, false);
2797 
2798  /*
2799  * We don't use heap_multi_insert for catalog tuples yet, but
2800  * better be prepared...
2801  */
2802  if (needwal && need_cids)
2803  log_heap_new_cid(relation, heaptup);
2804  }
2805 
2806  if (PageIsAllVisible(page))
2807  {
2808  all_visible_cleared = true;
2809  PageClearAllVisible(page);
2810  visibilitymap_clear(relation,
2811  BufferGetBlockNumber(buffer),
2812  vmbuffer, VISIBILITYMAP_VALID_BITS);
2813  }
2814 
2815  /*
2816  * XXX Should we set PageSetPrunable on this page ? See heap_insert()
2817  */
2818 
2819  MarkBufferDirty(buffer);
2820 
2821  /* XLOG stuff */
2822  if (needwal)
2823  {
2824  XLogRecPtr recptr;
2825  xl_heap_multi_insert *xlrec;
2827  char *tupledata;
2828  int totaldatalen;
2829  char *scratchptr = scratch;
2830  bool init;
2831  int bufflags = 0;
2832 
2833  /*
2834  * If the page was previously empty, we can reinit the page
2835  * instead of restoring the whole thing.
2836  */
2837  init = (ItemPointerGetOffsetNumber(&(heaptuples[ndone]->t_self)) == FirstOffsetNumber &&
2838  PageGetMaxOffsetNumber(page) == FirstOffsetNumber + nthispage - 1);
2839 
2840  /* allocate xl_heap_multi_insert struct from the scratch area */
2841  xlrec = (xl_heap_multi_insert *) scratchptr;
2842  scratchptr += SizeOfHeapMultiInsert;
2843 
2844  /*
2845  * Allocate offsets array. Unless we're reinitializing the page,
2846  * in that case the tuples are stored in order starting at
2847  * FirstOffsetNumber and we don't need to store the offsets
2848  * explicitly.
2849  */
2850  if (!init)
2851  scratchptr += nthispage * sizeof(OffsetNumber);
2852 
2853  /* the rest of the scratch space is used for tuple data */
2854  tupledata = scratchptr;
2855 
2856  xlrec->flags = all_visible_cleared ? XLH_INSERT_ALL_VISIBLE_CLEARED : 0;
2857  xlrec->ntuples = nthispage;
2858 
2859  /*
2860  * Write out an xl_multi_insert_tuple and the tuple data itself
2861  * for each tuple.
2862  */
2863  for (i = 0; i < nthispage; i++)
2864  {
2865  HeapTuple heaptup = heaptuples[ndone + i];
2866  xl_multi_insert_tuple *tuphdr;
2867  int datalen;
2868 
2869  if (!init)
2870  xlrec->offsets[i] = ItemPointerGetOffsetNumber(&heaptup->t_self);
2871  /* xl_multi_insert_tuple needs two-byte alignment. */
2872  tuphdr = (xl_multi_insert_tuple *) SHORTALIGN(scratchptr);
2873  scratchptr = ((char *) tuphdr) + SizeOfMultiInsertTuple;
2874 
2875  tuphdr->t_infomask2 = heaptup->t_data->t_infomask2;
2876  tuphdr->t_infomask = heaptup->t_data->t_infomask;
2877  tuphdr->t_hoff = heaptup->t_data->t_hoff;
2878 
2879  /* write bitmap [+ padding] [+ oid] + data */
2880  datalen = heaptup->t_len - SizeofHeapTupleHeader;
2881  memcpy(scratchptr,
2882  (char *) heaptup->t_data + SizeofHeapTupleHeader,
2883  datalen);
2884  tuphdr->datalen = datalen;
2885  scratchptr += datalen;
2886  }
2887  totaldatalen = scratchptr - tupledata;
2888  Assert((scratchptr - scratch) < BLCKSZ);
2889 
2890  if (need_tuple_data)
2892 
2893  /*
2894  * Signal that this is the last xl_heap_multi_insert record
2895  * emitted by this call to heap_multi_insert(). Needed for logical
2896  * decoding so it knows when to cleanup temporary data.
2897  */
2898  if (ndone + nthispage == ntuples)
2899  xlrec->flags |= XLH_INSERT_LAST_IN_MULTI;
2900 
2901  if (init)
2902  {
2903  info |= XLOG_HEAP_INIT_PAGE;
2904  bufflags |= REGBUF_WILL_INIT;
2905  }
2906 
2907  /*
2908  * If we're doing logical decoding, include the new tuple data
2909  * even if we take a full-page image of the page.
2910  */
2911  if (need_tuple_data)
2912  bufflags |= REGBUF_KEEP_DATA;
2913 
2914  XLogBeginInsert();
2915  XLogRegisterData((char *) xlrec, tupledata - scratch);
2916  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags);
2917 
2918  XLogRegisterBufData(0, tupledata, totaldatalen);
2919 
2920  /* filtering by origin on a row level is much more efficient */
2922 
2923  recptr = XLogInsert(RM_HEAP2_ID, info);
2924 
2925  PageSetLSN(page, recptr);
2926  }
2927 
2928  END_CRIT_SECTION();
2929 
2930  UnlockReleaseBuffer(buffer);
2931  if (vmbuffer != InvalidBuffer)
2932  ReleaseBuffer(vmbuffer);
2933 
2934  ndone += nthispage;
2935  }
2936 
2937  /*
2938  * We're done with the actual inserts. Check for conflicts again, to
2939  * ensure that all rw-conflicts in to these inserts are detected. Without
2940  * this final check, a sequential scan of the heap may have locked the
2941  * table after the "before" check, missing one opportunity to detect the
2942  * conflict, and then scanned the table before the new tuples were there,
2943  * missing the other chance to detect the conflict.
2944  *
2945  * For heap inserts, we only need to check for table-level SSI locks. Our
2946  * new tuples can't possibly conflict with existing tuple locks, and heap
2947  * page locks are only consolidated versions of tuple locks; they do not
2948  * lock "gaps" as index page locks do. So we don't need to specify a
2949  * buffer when making the call.
2950  */
2952 
2953  /*
2954  * If tuples are cachable, mark them for invalidation from the caches in
2955  * case we abort. Note it is OK to do this after releasing the buffer,
2956  * because the heaptuples data structure is all in local memory, not in
2957  * the shared buffer.
2958  */
2959  if (IsCatalogRelation(relation))
2960  {
2961  for (i = 0; i < ntuples; i++)
2962  CacheInvalidateHeapTuple(relation, heaptuples[i], NULL);
2963  }
2964 
2965  /*
2966  * Copy t_self fields back to the caller's original tuples. This does
2967  * nothing for untoasted tuples (tuples[i] == heaptuples[i)], but it's
2968  * probably faster to always copy than check.
2969  */
2970  for (i = 0; i < ntuples; i++)
2971  tuples[i]->t_self = heaptuples[i]->t_self;
2972 
2973  pgstat_count_heap_insert(relation, ntuples);
2974 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
#define SizeofHeapTupleHeader
Definition: htup_details.h:183
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:92
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup)
Definition: heapam.c:7971
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1094
static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid, CommandId cid, int options)
Definition: heapam.c:2625
#define PageIsAllVisible(page)
Definition: bufpage.h:381
uint32 TransactionId
Definition: c.h:474
OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]
Definition: heapam_xlog.h:177
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
unsigned char uint8
Definition: c.h:323
#define InvalidBuffer
Definition: buf.h:25
#define SizeOfHeapMultiInsert
Definition: heapam_xlog.h:180
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:192
#define HEAP_INSERT_SKIP_WAL
Definition: heapam.h:28
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define RelationIsLogicallyLogged(relation)
Definition: rel.h:580
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void RelationPutHeapTuple(Relation relation, Buffer buffer, HeapTuple tuple, bool token)
Definition: hio.c:36
void CheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: predicate.c:4280
#define XLOG_HEAP_INIT_PAGE
Definition: heapam_xlog.h:46
#define XLOG_HEAP2_MULTI_INSERT
Definition: heapam_xlog.h:58
uint16 OffsetNumber
Definition: off.h:24
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
HeapTupleHeader t_data
Definition: htup.h:68
bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
Size PageGetHeapFreeSpace(Page page)
Definition: bufpage.c:662
#define XLH_INSERT_CONTAINS_NEW_TUPLE
Definition: heapam_xlog.h:69
ItemPointerData t_self
Definition: htup.h:65
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define FirstOffsetNumber
Definition: off.h:27
#define REGBUF_STANDARD
Definition: xloginsert.h:34
Buffer RelationGetBufferForTuple(Relation relation, Size len, Buffer otherBuffer, int options, BulkInsertState bistate, Buffer *vmbuffer, Buffer *vmbuffer_other)
Definition: hio.c:313
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define RelationGetTargetPageFreeSpace(relation, defaultff)
Definition: rel.h:298
#define XLH_INSERT_LAST_IN_MULTI
Definition: heapam_xlog.h:67
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:564
#define REGBUF_KEEP_DATA
Definition: xloginsert.h:37
#define PageClearAllVisible(page)
Definition: bufpage.h:385
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
size_t Size
Definition: c.h:433
#define MAXALIGN(LEN)
Definition: c.h:652
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define RelationNeedsWAL(relation)
Definition: rel.h:510
#define XLH_INSERT_ALL_VISIBLE_CLEARED
Definition: heapam_xlog.h:66
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
void pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
Definition: pgstat.c:1907
void * palloc(Size size)
Definition: mcxt.c:924
int i
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define HEAP_DEFAULT_FILLFACTOR
Definition: rel.h:269
#define SHORTALIGN(LEN)
Definition: c.h:648
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
#define SizeOfMultiInsertTuple
Definition: heapam_xlog.h:191

◆ heap_open()

Relation heap_open ( Oid  relationId,
LOCKMODE  lockmode 
)

Definition at line 1294 of file heapam.c.

References ereport, errcode(), errmsg(), ERROR, RelationData::rd_rel, relation_open(), and RelationGetRelationName.

Referenced by _bt_parallel_build_main(), acquire_inherited_sample_rows(), AcquireRewriteLocks(), AddEnumLabel(), AddNewAttributeTuples(), AddRoleMems(), AddSubscriptionRelState(), AfterTriggerSetState(), AggregateCreate(), AlterCollation(), AlterConstraintNamespaces(), AlterDatabase(), AlterDatabaseOwner(), AlterDomainAddConstraint(), AlterDomainDefault(), AlterDomainDropConstraint(), AlterDomainNotNull(), AlterDomainValidateConstraint(), AlterEventTrigger(), AlterEventTriggerOwner(), AlterEventTriggerOwner_oid(), AlterExtensionNamespace(), AlterForeignDataWrapper(), AlterForeignDataWrapperOwner(), AlterForeignDataWrapperOwner_oid(), AlterForeignServer(), AlterForeignServerOwner(), AlterForeignServerOwner_oid(), AlterFunction(), AlterObjectNamespace_oid(), AlterOperator(), AlterPolicy(), AlterPublication(), AlterPublicationOwner(), AlterPublicationOwner_oid(), AlterPublicationTables(), AlterRole(), AlterSchemaOwner(), AlterSchemaOwner_oid(), AlterSeqNamespaces(), AlterSequence(), AlterSetting(), AlterSubscription(), AlterSubscriptionOwner(), AlterSubscriptionOwner_oid(), AlterTableMoveAll(), AlterTableNamespaceInternal(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeNamespaceInternal(), AlterTypeOwner(), AlterTypeOwner_oid(), AlterTypeOwnerInternal(), AlterUserMapping(), AppendAttributeTuples(), ApplyExtensionUpdates(), AssignTypeArrayOid(), ATAddCheckConstraint(), ATAddForeignKeyConstraint(), ATExecAddColumn(), ATExecAddIdentity(), ATExecAddOf(), ATExecAlterColumnGenericOptions(), ATExecAlterColumnType(), ATExecAlterConstraint(), ATExecAttachPartition(), ATExecChangeOwner(), ATExecDetachPartition(), ATExecDisableRowSecurity(), ATExecDropColumn(), ATExecDropConstraint(), ATExecDropIdentity(), ATExecDropNotNull(), ATExecDropOf(), ATExecEnableRowSecurity(), ATExecForceNoForceRowSecurity(), ATExecGenericOptions(), ATExecSetIdentity(), ATExecSetNotNull(), ATExecSetOptions(), ATExecSetRelOptions(), ATExecSetStatistics(), ATExecSetStorage(), ATExecSetTableSpace(), ATExecValidateConstraint(), ATPrepChangePersistence(), ATRewriteTable(), ATRewriteTables(), AttrDefaultFetch(), boot_openrel(), brin_desummarize_range(), brin_summarize_range(), bringetbitmap(), brinvacuumcleanup(), bt_index_check_internal(), build_indices(), build_physical_tlist(), BuildRelationExtStatistics(), CatalogCacheInitializeCache(), change_owner_fix_column_acls(), change_owner_recurse_to_sequences(), changeDependencyFor(), changeDependencyOnOwner(), check_db_file_conflict(), check_default_allows_bound(), check_selective_binary_conversion(), CheckAndCreateToastTable(), CheckConstraintFetch(), checkSharedDependencies(), ChooseConstraintName(), CloneForeignKeyConstraints(), CloneRowTriggersToPartition(), cluster(), CollationCreate(), ConstraintNameIsUsed(), ConstraintSetParentConstraint(), ConversionCreate(), copy_heap_data(), copyTemplateDependencies(), CountDBSubscriptions(), create_proc_lang(), create_toast_table(), CreateAccessMethod(), CreateCast(), CreateComments(), CreateConstraintEntry(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateInheritance(), CreateOpFamily(), CreatePolicy(), CreatePublication(), CreateRole(), CreateSharedComments(), CreateStatistics(), CreateSubscription(), CreateTableSpace(), CreateTransform(), CreateTrigger(), CreateUserMapping(), currtid_byreloid(), database_to_xmlschema_internal(), DefineIndex(), DefineOpClass(), DefineQueryRewrite(), DefineRelation(), DefineSequence(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), DeleteAttributeTuples(), DeleteComments(), deleteDependencyRecordsFor(), deleteDependencyRecordsForClass(), DeleteInheritsTuple(), DeleteInitPrivs(), deleteOneObject(), DeleteRelationTuple(), DeleteSecurityLabel(), DeleteSequenceTuple(), DeleteSharedComments(), deleteSharedDependencyRecordsFor(), DeleteSharedSecurityLabel(), DeleteSystemAttributeTuples(), DelRoleMems(), deparseColumnRef(), deparseFromExprForRel(), deparseSelectSql(), do_autovacuum(), drop_parent_dependency(), DropCastById(), dropDatabaseDependencies(), dropdb(), DropProceduralLanguageById(), DropRole(), DropSetting(), DropSubscription(), DropTableSpace(), DropTransformById(), EnableDisableRule(), EnableDisableTrigger(), ENRMetadataGetTupDesc(), enum_endpoint(), enum_range_internal(), EnumValuesCreate(), EnumValuesDelete(), EventTriggerSQLDropAddObject(), exec_object_restorecon(), ExecAlterExtensionStmt(), ExecAlterObjectSchemaStmt(), ExecAlterOwnerStmt(), ExecGetTriggerResultRel(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), ExecInitPartitionInfo(), ExecOpenScanRelation(), ExecRefreshMatView(), ExecRenameStmt(), ExecuteTruncate(), ExecuteTruncateGuts(), expand_inherited_rtentry(), expand_partitioned_rtentry(), extension_config_remove(), find_composite_type_dependencies(), find_inheritance_children(), find_language_template(), find_typed_table_dependencies(), finish_heap_swap(), fireRIRrules(), generate_partition_qual(), get_actual_variable_range(), get_all_vacuum_rels(), get_constraint_index(), get_database_list(), get_database_oid(), get_db_info(), get_domain_constraint_oid(), get_extension_name(), get_extension_oid(), get_extension_schema(), get_file_fdw_attribute_options(), get_index_constraint(), get_partition_ancestors(), get_partition_dispatch_recurse(), get_partition_parent(), get_partition_qual_relid(), get_pkey_attnames(), get_primary_key_attnos(), get_relation_constraint_attnos(), get_relation_constraint_oid(), get_relation_constraints(), get_relation_data_width(), get_relation_idx_constraint_oid(), get_relation_info(), get_relation_policy_oid(), get_rels_with_domain(), get_row_security_policies(), get_subscription_list(), get_tables_to_cluster(), get_tablespace_name(), get_tablespace_oid(), get_trigger_oid(), GetAllTablesPublicationRelations(), GetAllTablesPublications(), GetComment(), getConstraintTypeDescription(), GetDatabaseTuple(), GetDatabaseTupleByOid(), GetDefaultOpClass(), getExtensionOfObject(), getObjectDescription(), getObjectIdentityParts(), getOwnedSequences(), GetPublicationRelations(), getRelationsInNamespace(), GetSecurityLabel(), GetSharedSecurityLabel(), GetSubscriptionNotReadyRelations(), GetSubscriptionRelations(), GetSubscriptionRelState(), gettype(), GrantRole(), has_row_triggers(), has_superclass(), heap_create_with_catalog(), heap_drop_with_catalog(), heap_sync(), heap_truncate(), heap_truncate_find_FKs(), heap_truncate_one_rel(), index_build(), index_constraint_create(), index_create(), index_drop(), index_set_state_flags(), index_update_stats(), infer_arbiter_indexes(), InitPlan(), insert_event_trigger_tuple(), InsertExtensionTuple(), InsertRule(), intorel_startup(), isQueryUsingTempRelation_walker(), LargeObjectCreate(), LargeObjectDrop(), LargeObjectExists(), load_domaintype_info(), load_enum_cache_data(), LockViewRecurse(), logicalrep_rel_open(), LogicalRepSyncTableStart(), lookup_ts_config_cache(), LookupOpclassInfo(), make_new_heap(), make_ruledef(), make_viewdef(), makeArrayTypeName(), mark_index_clustered(), MergeAttributesIntoExisting(), MergeConstraintsIntoExisting(), MergeWithExistingConstraint(), movedb(), myLargeObjectExists(), NamespaceCreate(), objectsInSchemaToOids(), open_lo_relation(), OpenTableList(), OperatorCreate(), OperatorShellMake(), OperatorUpd(), performDeletion(), performMultipleDeletions(), pg_event_trigger_ddl_commands(), pg_extension_config_dump(), pg_extension_ownercheck(), pg_get_constraintdef_worker(), pg_get_replica_identity_index(), pg_get_serial_sequence(), pg_get_triggerdef_worker(), pg_identify_object(), pg_largeobject_aclmask_snapshot(), pg_largeobject_ownercheck(), pgstat_collect_oids(), plan_create_index_workers(), postgresPlanDirectModify(), postgresPlanForeignModify(), preprocess_targetlist(), ProcedureCreate(), process_settings(), publication_add_relation(), QueuePartitionConstraintValidation(), RangeCreate(), RangeDelete(), recordExtensionInitPrivWorker(), recordExtObjInitPriv(), recordMultipleDependencies(), recordSharedDependencyOn(), refresh_by_match_merge(), refuseDupeIndexAttach(), reindex_index(), reindex_relation(), ReindexMultipleTables(), relation_has_policies(), relation_mark_replica_identity(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationClearMissing(), RelationGetExclusionInfo(), RelationGetFKeyList(), RelationGetIndexList(), RelationGetStatExtList(), RelationRemoveInheritance(), RelationSetNewRelfilenode(), RelidByRelfilenode(), remove_dbtablespaces(), RemoveAccessMethodById(), RemoveAmOpEntryById(), RemoveAmProcEntryById(), RemoveAttrDefault(), RemoveAttrDefaultById(), RemoveAttributeById(), RemoveCollationById(), RemoveConstraintById(), RemoveConversionById(), RemoveDefaultACLById(), RemoveEventTriggerById(), RemoveExtensionById(), RemoveForeignDataWrapperById(), RemoveForeignServerById(), RemoveFunctionById(), RemoveInheritance(), RemoveOpClassById(), RemoveOperatorById(), RemoveOpFamilyById(), RemovePartitionKeyByRelId(), RemovePolicyById(), RemovePublicationById(), RemovePublicationRelById(), RemoveRewriteRuleById(), RemoveRoleFromObjectACL(), RemoveRoleFromObjectPolicy(), RemoveSchemaById(), RemoveStatistics(), RemoveStatisticsById(), RemoveSubscriptionRel(), RemoveTriggerById(), RemoveTSConfigurationById(), RemoveTSDictionaryById(), RemoveTSParserById(), RemoveTSTemplateById(), RemoveTypeById(), RemoveUserMappingById(), rename_policy(), renameatt_internal(), RenameConstraint(), RenameConstraintById(), RenameDatabase(), RenameEnumLabel(), RenameRelationInternal(), RenameRewriteRule(), RenameRole(), RenameSchema(), RenameTableSpace(), renametrig(), RenameType(), RenameTypeInternal(), replorigin_create(), replorigin_drop(), RewriteQuery(), rewriteTargetView(), RI_FKey_cascade_del(), RI_FKey_cascade_upd(), RI_FKey_check(), ri_restrict(), ri_setdefault(), ri_setnull(), ScanPgRelation(), schema_to_xmlschema_internal(), SearchCatCacheList(), SearchCatCacheMiss(), sepgsql_attribute_post_create(), sepgsql_database_post_create(), sepgsql_index_modify(), sepgsql_proc_post_create(), sepgsql_proc_setattr(), sepgsql_relation_post_create(), sepgsql_relation_setattr(), sepgsql_schema_post_create(), sequenceIsOwned(), SetDefaultACL(), SetFunctionArgType(), SetFunctionReturnType(), SetMatViewPopulatedState(), SetRelationHasSubclass(), SetRelationNumChecks(), SetRelationRuleStatus(), SetSecurityLabel(), SetSharedSecurityLabel(), shdepDropOwned(), shdepReassignOwned(), StoreAttrDefault(), StoreCatalogInheritance(), storeOperators(), StorePartitionBound(), StorePartitionKey(), storeProcedures(), StoreSingleInheritance(), swap_relation_files(), table_to_xml_and_xmlschema(), table_to_xmlschema(), ThereIsAtLeastOneRole(), toast_delete_datum(), toast_fetch_datum(), toast_fetch_datum_slice(), toast_get_valid_index(), toast_save_datum(), toastid_valueid_exists(), transientrel_startup(), TypeCreate(), typeInheritsFrom(), TypeShellMake(), update_attstats(), update_default_partition_oid(), update_relispartition(), updateAclDependencies(), UpdateIndexRelation(), UpdateSubscriptionRelState(), vac_truncate_clog(), vac_update_datfrozenxid(), vac_update_relstats(), validate_index(), and validatePartitionedIndex().

1295 {
1296  Relation r;
1297 
1298  r = relation_open(relationId, lockmode);
1299 
1300  if (r->rd_rel->relkind == RELKIND_INDEX ||
1301  r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
1302  ereport(ERROR,
1303  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1304  errmsg("\"%s\" is an index",
1306  else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
1307  ereport(ERROR,
1308  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1309  errmsg("\"%s\" is a composite type",
1311 
1312  return r;
1313 }
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124

◆ heap_openrv()

Relation heap_openrv ( const RangeVar relation,
LOCKMODE  lockmode 
)

Definition at line 1323 of file heapam.c.

References ereport, errcode(), errmsg(), ERROR, RelationData::rd_rel, relation_openrv(), and RelationGetRelationName.

Referenced by ATAddForeignKeyConstraint(), ATExecAddInherit(), ATExecAttachPartition(), ATExecDetachPartition(), ATExecDropInherit(), boot_openrel(), BootstrapToastTable(), CreateTrigger(), currtid_byrelname(), DefineIndex(), DoCopy(), ExecuteTruncate(), get_rel_from_relname(), MergeAttributes(), OpenTableList(), transformIndexConstraint(), and transformRuleStmt().

1324 {
1325  Relation r;
1326 
1327  r = relation_openrv(relation, lockmode);
1328 
1329  if (r->rd_rel->relkind == RELKIND_INDEX ||
1330  r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
1331  ereport(ERROR,
1332  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1333  errmsg("\"%s\" is an index",
1335  else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
1336  ereport(ERROR,
1337  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1338  errmsg("\"%s\" is a composite type",
1340 
1341  return r;
1342 }
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1202
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ heap_openrv_extended()

Relation heap_openrv_extended ( const RangeVar relation,
LOCKMODE  lockmode,
bool  missing_ok 
)

Definition at line 1353 of file heapam.c.

References ereport, errcode(), errmsg(), ERROR, RelationData::rd_rel, relation_openrv_extended(), and RelationGetRelationName.

Referenced by get_object_address_relobject(), and parserOpenTable().

1355 {
1356  Relation r;
1357 
1358  r = relation_openrv_extended(relation, lockmode, missing_ok);
1359 
1360  if (r)
1361  {
1362  if (r->rd_rel->relkind == RELKIND_INDEX ||
1363  r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
1364  ereport(ERROR,
1365  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1366  errmsg("\"%s\" is an index",
1368  else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
1369  ereport(ERROR,
1370  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1371  errmsg("\"%s\" is a composite type",
1373  }
1374 
1375  return r;
1376 }
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition: heapam.c:1237

◆ heap_page_prune()

int heap_page_prune ( Relation  relation,
Buffer  buffer,
TransactionId  OldestXmin,
bool  report_stats,
TransactionId latestRemovedXid 
)

Definition at line 181 of file pruneheap.c.

References BufferGetPage, END_CRIT_SECTION, FirstOffsetNumber, heap_page_prune_execute(), heap_prune_chain(), InvalidTransactionId, ItemIdIsDead, ItemIdIsUsed, PruneState::latestRemovedXid, log_heap_clean(), MarkBufferDirty(), MarkBufferDirtyHint(), PruneState::marked, PruneState::ndead, PruneState::new_prune_xid, PruneState::nowdead, PruneState::nowunused, PruneState::nredirected, PruneState::nunused, OffsetNumberNext, PageClearFull, PageGetItemId, PageGetMaxOffsetNumber, PageIsFull, PageSetLSN, pgstat_update_heap_dead_tuples(), PruneState::redirected, RelationNeedsWAL, and START_CRIT_SECTION.

Referenced by heap_page_prune_opt(), and lazy_scan_heap().

183 {
184  int ndeleted = 0;
185  Page page = BufferGetPage(buffer);
186  OffsetNumber offnum,
187  maxoff;
188  PruneState prstate;
189 
190  /*
191  * Our strategy is to scan the page and make lists of items to change,
192  * then apply the changes within a critical section. This keeps as much
193  * logic as possible out of the critical section, and also ensures that
194  * WAL replay will work the same as the normal case.
195  *
196  * First, initialize the new pd_prune_xid value to zero (indicating no
197  * prunable tuples). If we find any tuples which may soon become
198  * prunable, we will save the lowest relevant XID in new_prune_xid. Also
199  * initialize the rest of our working state.
200  */
202  prstate.latestRemovedXid = *latestRemovedXid;
203  prstate.nredirected = prstate.ndead = prstate.nunused = 0;
204  memset(prstate.marked, 0, sizeof(prstate.marked));
205 
206  /* Scan the page */
207  maxoff = PageGetMaxOffsetNumber(page);
208  for (offnum = FirstOffsetNumber;
209  offnum <= maxoff;
210  offnum = OffsetNumberNext(offnum))
211  {
212  ItemId itemid;
213 
214  /* Ignore items already processed as part of an earlier chain */
215  if (prstate.marked[offnum])
216  continue;
217 
218  /* Nothing to do if slot is empty or already dead */
219  itemid = PageGetItemId(page, offnum);
220  if (!ItemIdIsUsed(itemid) || ItemIdIsDead(itemid))
221  continue;
222 
223  /* Process this item or chain of items */
224  ndeleted += heap_prune_chain(relation, buffer, offnum,
225  OldestXmin,
226  &prstate);
227  }
228 
229  /* Any error while applying the changes is critical */
231 
232  /* Have we found any prunable items? */
233  if (prstate.nredirected > 0 || prstate.ndead > 0 || prstate.nunused > 0)
234  {
235  /*
236  * Apply the planned item changes, then repair page fragmentation, and
237  * update the page's hint bit about whether it has free line pointers.
238  */
240  prstate.redirected, prstate.nredirected,
241  prstate.nowdead, prstate.ndead,
242  prstate.nowunused, prstate.nunused);
243 
244  /*
245  * Update the page's pd_prune_xid field to either zero, or the lowest
246  * XID of any soon-prunable tuple.
247  */
248  ((PageHeader) page)->pd_prune_xid = prstate.new_prune_xid;
249 
250  /*
251  * Also clear the "page is full" flag, since there's no point in
252  * repeating the prune/defrag process until something else happens to
253  * the page.
254  */
255  PageClearFull(page);
256 
258 
259  /*
260  * Emit a WAL HEAP_CLEAN record showing what we did
261  */
262  if (RelationNeedsWAL(relation))
263  {
264  XLogRecPtr recptr;
265 
266  recptr = log_heap_clean(relation, buffer,
267  prstate.redirected, prstate.nredirected,
268  prstate.nowdead, prstate.ndead,
269  prstate.nowunused, prstate.nunused,
270  prstate.latestRemovedXid);
271 
272  PageSetLSN(BufferGetPage(buffer), recptr);
273  }
274  }
275  else
276  {
277  /*
278  * If we didn't prune anything, but have found a new value for the
279  * pd_prune_xid field, update it and mark the buffer dirty. This is
280  * treated as a non-WAL-logged hint.
281  *
282  * Also clear the "page is full" flag if it is set, since there's no
283  * point in repeating the prune/defrag process until something else
284  * happens to the page.
285  */
286  if (((PageHeader) page)->pd_prune_xid != prstate.new_prune_xid ||
287  PageIsFull(page))
288  {
289  ((PageHeader) page)->pd_prune_xid = prstate.new_prune_xid;
290  PageClearFull(page);
292  }
293  }
294 
296 
297  /*
298  * If requested, report the number of tuples reclaimed to pgstats. This is
299  * ndeleted minus ndead, because we don't want to count a now-DEAD root
300  * item as a deletion for this purpose.
301  */
302  if (report_stats && ndeleted > prstate.ndead)
303  pgstat_update_heap_dead_tuples(relation, ndeleted - prstate.ndead);
304 
305  *latestRemovedXid = prstate.latestRemovedXid;
306 
307  /*
308  * XXX Should we update the FSM information of this page ?
309  *
310  * There are two schools of thought here. We may not want to update FSM
311  * information so that the page is not used for unrelated UPDATEs/INSERTs
312  * and any free space in this page will remain available for further
313  * UPDATEs in *this* page, thus improving chances for doing HOT updates.
314  *
315  * But for a large table and where a page does not receive further UPDATEs
316  * for a long time, we might waste this space by not updating the FSM
317  * information. The relation may get extended and fragmented further.
318  *
319  * On