PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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
BulkInsertStateData
BulkInsertState
 
typedef enum LockTupleMode LockTupleMode
 
typedef struct
HeapUpdateFailureData 
HeapUpdateFailureData
 
typedef struct HeapScanDescDataHeapScanDesc
 
typedef struct
ParallelHeapScanDescData
ParallelHeapScanDesc
 

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

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

Definition at line 97 of file heapam.h.

Referenced by acquire_inherited_sample_rows(), AcquireRewriteLocks(), AddEnumLabel(), AddNewAttributeTuples(), addRangeTableEntry(), AddRoleMems(), afterTriggerInvokeEvents(), 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_selective_binary_conversion(), CheckAndCreateToastTable(), CheckConstraintFetch(), checkSharedDependencies(), ChooseConstraintName(), close_lo_relation(), closerel(), CloseTableList(), cluster(), CollationCreate(), ConstraintNameIsUsed(), ConversionCreate(), copy_heap_data(), CopyFrom(), 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(), 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(), EvalPlanQualEnd(), EventTriggerSQLDropAddObject(), exec_object_restorecon(), ExecAlterExtensionStmt(), ExecAlterObjectDependsStmt(), ExecAlterObjectSchemaStmt(), ExecAlterOwnerStmt(), ExecCloseScanRelation(), ExecEndModifyTable(), ExecEndPlan(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), ExecInitModifyTable(), ExecRefreshMatView(), ExecRenameStmt(), ExecuteTruncate(), expand_inherited_rtentry(), expand_targetlist(), 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_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_parent(), get_pkey_attnames(), get_primary_key_attnos(), get_rel_oids(), get_relation_constraint_oid(), get_relation_constraints(), get_relation_data_width(), 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(), 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(), logicalrep_rel_close(), LogicalRepSyncTableStart(), lookup_ts_config_cache(), LookupOpclassInfo(), make_new_heap(), 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(), postgresPlanDirectModify(), postgresPlanForeignModify(), ProcedureCreate(), process_settings(), publication_add_relation(), RangeCreate(), RangeDelete(), rebuild_relation(), recordExtensionInitPrivWorker(), recordMultipleDependencies(), recordSharedDependencyOn(), refresh_by_match_merge(), reindex_index(), reindex_relation(), ReindexMultipleTables(), relation_has_policies(), relation_mark_replica_identity(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationGetExclusionInfo(), RelationGetFKeyList(), RelationGetIndexList(), RelationGetPartitionDispatchInfo(), 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(), RemoveStatisticsExt(), 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_FKey_setdefault_del(), RI_FKey_setdefault_upd(), RI_FKey_setnull_del(), RI_FKey_setnull_upd(), ri_restrict_del(), ri_restrict_upd(), ScanPgRelation(), schema_to_xmlschema_internal(), SearchCatCache(), SearchCatCacheList(), 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(), SetSubscriptionRelState(), setTargetTable(), shdepDropOwned(), shdepReassignOwned(), StoreAttrDefault(), StoreCatalogInheritance(), storeOperators(), StorePartitionBound(), StorePartitionKey(), storeProcedures(), 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(), updateAclDependencies(), UpdateIndexRelation(), vac_truncate_clog(), vac_update_datfrozenxid(), vac_update_relstats(), validate_index(), and validateDomainConstraint().

#define HEAP_INSERT_FROZEN   0x0004

Definition at line 30 of file heapam.h.

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

#define HEAP_INSERT_SKIP_FSM   0x0002
#define HEAP_INSERT_SPECULATIVE   0x0008

Definition at line 31 of file heapam.h.

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

#define HeapScanIsValid (   scan)    PointerIsValid(scan)

Definition at line 107 of file heapam.h.

#define MaxLockTupleMode   LockTupleExclusive

Definition at line 50 of file heapam.h.

Typedef Documentation

Definition at line 33 of file heapam.h.

Definition at line 100 of file heapam.h.

Definition at line 101 of file heapam.h.

Enumeration Type Documentation

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

void FreeBulkInsertState ( BulkInsertState  )

Definition at line 2333 of file heapam.c.

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

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

2334 {
2335  if (bistate->current_buf != InvalidBuffer)
2336  ReleaseBuffer(bistate->current_buf);
2337  FreeAccessStrategy(bistate->strategy);
2338  pfree(bistate);
2339 }
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
void pfree(void *pointer)
Definition: mcxt.c:950
void FreeAccessStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:580
BulkInsertState GetBulkInsertState ( void  )

Definition at line 2319 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().

2320 {
2321  BulkInsertState bistate;
2322 
2323  bistate = (BulkInsertState) palloc(sizeof(BulkInsertStateData));
2325  bistate->current_buf = InvalidBuffer;
2326  return bistate;
2327 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:525
#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:849
Buffer current_buf
Definition: hio.h:34
void heap_abort_speculative ( Relation  relation,
HeapTuple  tuple 
)

Definition at line 6053 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().

6054 {
6056  ItemPointer tid = &(tuple->t_self);
6057  ItemId lp;
6058  HeapTupleData tp;
6059  Page page;
6060  BlockNumber block;
6061  Buffer buffer;
6062 
6063  Assert(ItemPointerIsValid(tid));
6064 
6065  block = ItemPointerGetBlockNumber(tid);
6066  buffer = ReadBuffer(relation, block);
6067  page = BufferGetPage(buffer);
6068 
6070 
6071  /*
6072  * Page can't be all visible, we just inserted into it, and are still
6073  * running.
6074  */
6075  Assert(!PageIsAllVisible(page));
6076 
6077  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
6078  Assert(ItemIdIsNormal(lp));
6079 
6080  tp.t_tableOid = RelationGetRelid(relation);
6081  tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
6082  tp.t_len = ItemIdGetLength(lp);
6083  tp.t_self = *tid;
6084 
6085  /*
6086  * Sanity check that the tuple really is a speculatively inserted tuple,
6087  * inserted by us.
6088  */
6089  if (tp.t_data->t_choice.t_heap.t_xmin != xid)
6090  elog(ERROR, "attempted to kill a tuple inserted by another transaction");
6091  if (!(IsToastRelation(relation) || HeapTupleHeaderIsSpeculative(tp.t_data)))
6092  elog(ERROR, "attempted to kill a non-speculative tuple");
6094 
6095  /*
6096  * No need to check for serializable conflicts here. There is never a
6097  * need for a combocid, either. No need to extract replica identity, or
6098  * do anything special with infomask bits.
6099  */
6100 
6102 
6103  /*
6104  * The tuple will become DEAD immediately. Flag that this page
6105  * immediately is a candidate for pruning by setting xmin to
6106  * RecentGlobalXmin. That's not pretty, but it doesn't seem worth
6107  * inventing a nicer API for this.
6108  */
6111 
6112  /* store transaction information of xact deleting the tuple */
6115 
6116  /*
6117  * Set the tuple header xmin to InvalidTransactionId. This makes the
6118  * tuple immediately invisible everyone. (In particular, to any
6119  * transactions waiting on the speculative token, woken up later.)
6120  */
6122 
6123  /* Clear the speculative insertion token too */
6124  tp.t_data->t_ctid = tp.t_self;
6125 
6126  MarkBufferDirty(buffer);
6127 
6128  /*
6129  * XLOG stuff
6130  *
6131  * The WAL records generated here match heap_delete(). The same recovery
6132  * routines are used.
6133  */
6134  if (RelationNeedsWAL(relation))
6135  {
6136  xl_heap_delete xlrec;
6137  XLogRecPtr recptr;
6138 
6139  xlrec.flags = XLH_DELETE_IS_SUPER;
6141  tp.t_data->t_infomask2);
6143  xlrec.xmax = xid;
6144 
6145  XLogBeginInsert();
6146  XLogRegisterData((char *) &xlrec, SizeOfHeapDelete);
6147  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
6148 
6149  /* No replica identity & replication origin logged */
6150 
6151  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
6152 
6153  PageSetLSN(page, recptr);
6154  }
6155 
6156  END_CRIT_SECTION();
6157 
6158  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6159 
6160  if (HeapTupleHasExternal(&tp))
6161  {
6162  Assert(!IsToastRelation(relation));
6163  toast_delete(relation, &tp, true);
6164  }
6165 
6166  /*
6167  * Never need to mark tuple for invalidation, since catalogs don't support
6168  * speculative insertion
6169  */
6170 
6171  /* Now we can release the buffer */
6172  ReleaseBuffer(buffer);
6173 
6174  /* count deletion, as we counted the insertion too */
6175  pgstat_count_heap_delete(relation);
6176 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
bool IsToastRelation(Relation relation)
Definition: catalog.c:135
#define HEAP_XMAX_BITS
Definition: htup_details.h:256
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:2952
HeapTupleFields t_heap
Definition: htup_details.h:146
#define PageIsAllVisible(page)
Definition: bufpage.h:382
uint32 TransactionId
Definition: c.h:397
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:132
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:423
#define PageSetPrunable(page, xid)
Definition: bufpage.h:395
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
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:105
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderIsHeapOnly(tup)
Definition: htup_details.h:502
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
ItemPointerData t_ctid
Definition: htup_details.h:150
ItemPointerData t_self
Definition: htup.h:65
TransactionId xmax
Definition: heapam_xlog.h:104
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define SizeOfHeapDelete
Definition: heapam_xlog.h:110
TransactionId RecentGlobalXmin
Definition: snapmgr.c:166
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#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:118
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
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:264
#define HEAP_MOVED
Definition: htup_details.h:202
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
uint8 infobits_set
Definition: heapam_xlog.h:106
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
#define RelationNeedsWAL(relation)
Definition: rel.h:506
void pgstat_count_heap_delete(Relation rel)
Definition: pgstat.c:1917
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:674
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:75
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
#define XLOG_HEAP_DELETE
Definition: heapam_xlog.h:33
#define RelationGetRelid(relation)
Definition: rel.h:417
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:313
HeapScanDesc heap_beginscan ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key 
)

Definition at line 1391 of file heapam.c.

References heap_beginscan_internal().

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

1393 {
1394  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1395  true, true, true, false, false, false);
1396 }
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:1437
#define NULL
Definition: c.h:229
HeapScanDesc heap_beginscan_bm ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key 
)

Definition at line 1419 of file heapam.c.

References heap_beginscan_internal().

Referenced by ExecInitBitmapHeapScan().

1421 {
1422  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1423  false, false, true, true, false, false);
1424 }
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:1437
#define NULL
Definition: c.h:229
HeapScanDesc heap_beginscan_catalog ( Relation  relation,
int  nkeys,
ScanKey  key 
)

Definition at line 1399 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_database_list(), get_rel_oids(), 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().

1400 {
1401  Oid relid = RelationGetRelid(relation);
1402  Snapshot snapshot = RegisterSnapshot(GetCatalogSnapshot(relid));
1403 
1404  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1405  true, true, true, false, false, true);
1406 }
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:858
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:436
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:1437
#define NULL
Definition: c.h:229
#define RelationGetRelid(relation)
Definition: rel.h:417
HeapScanDesc heap_beginscan_parallel ( Relation  ,
ParallelHeapScanDesc   
)

Definition at line 1650 of file heapam.c.

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

Referenced by ExecSeqScanInitializeDSM(), and ExecSeqScanInitializeWorker().

1651 {
1652  Snapshot snapshot;
1653 
1654  Assert(RelationGetRelid(relation) == parallel_scan->phs_relid);
1655  snapshot = RestoreSnapshot(parallel_scan->phs_snapshot_data);
1656  RegisterSnapshot(snapshot);
1657 
1658  return heap_beginscan_internal(relation, snapshot, 0, NULL, parallel_scan,
1659  true, true, true, false, false, true);
1660 }
Snapshot RestoreSnapshot(char *start_address)
Definition: snapmgr.c:2084
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:858
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:1437
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define RelationGetRelid(relation)
Definition: rel.h:417
HeapScanDesc heap_beginscan_sampling ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key,
bool  allow_strat,
bool  allow_sync,
bool  allow_pagemode 
)

Definition at line 1427 of file heapam.c.

References heap_beginscan_internal().

Referenced by tablesample_init().

1430 {
1431  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1432  allow_strat, allow_sync, allow_pagemode,
1433  false, true, false);
1434 }
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:1437
#define NULL
Definition: c.h:229
HeapScanDesc heap_beginscan_strat ( Relation  relation,
Snapshot  snapshot,
int  nkeys,
ScanKey  key,
bool  allow_strat,
bool  allow_sync 
)

Definition at line 1409 of file heapam.c.

References heap_beginscan_internal().

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

1412 {
1413  return heap_beginscan_internal(relation, snapshot, nkeys, key, NULL,
1414  allow_strat, allow_sync, true,
1415  false, false, false);
1416 }
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:1437
#define NULL
Definition: c.h:229
HTSU_Result heap_delete ( Relation  relation,
ItemPointer  tid,
CommandId  cid,
Snapshot  crosscheck,
bool  wait,
HeapUpdateFailureData hufd 
)

Definition at line 3011 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, 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, NULL, xl_heap_delete::offnum, PageClearAllVisible, PageGetItem, PageGetItemId, PageIsAllVisible, PageSetLSN, PageSetPrunable, pgstat_count_heap_delete(), RelationData::rd_rel, ReadBuffer(), REGBUF_STANDARD, RelationGetRelid, RelationIsAccessibleInLogicalDecoding, RelationNeedsWAL, ReleaseBuffer(), RELKIND_MATVIEW, RELKIND_RELATION, REPLICA_IDENTITY_FULL, result, 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, 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().

3014 {
3017  ItemId lp;
3018  HeapTupleData tp;
3019  Page page;
3020  BlockNumber block;
3021  Buffer buffer;
3022  Buffer vmbuffer = InvalidBuffer;
3023  TransactionId new_xmax;
3024  uint16 new_infomask,
3025  new_infomask2;
3026  bool have_tuple_lock = false;
3027  bool iscombo;
3028  bool all_visible_cleared = false;
3029  HeapTuple old_key_tuple = NULL; /* replica identity of the tuple */
3030  bool old_key_copied = false;
3031 
3032  Assert(ItemPointerIsValid(tid));
3033 
3034  /*
3035  * Forbid this during a parallel operation, lest it allocate a combocid.
3036  * Other workers might need that combocid for visibility checks, and we
3037  * have no provision for broadcasting it to them.
3038  */
3039  if (IsInParallelMode())
3040  ereport(ERROR,
3041  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
3042  errmsg("cannot delete tuples during a parallel operation")));
3043 
3044  block = ItemPointerGetBlockNumber(tid);
3045  buffer = ReadBuffer(relation, block);
3046  page = BufferGetPage(buffer);
3047 
3048  /*
3049  * Before locking the buffer, pin the visibility map page if it appears to
3050  * be necessary. Since we haven't got the lock yet, someone else might be
3051  * in the middle of changing this, so we'll need to recheck after we have
3052  * the lock.
3053  */
3054  if (PageIsAllVisible(page))
3055  visibilitymap_pin(relation, block, &vmbuffer);
3056 
3058 
3059  /*
3060  * If we didn't pin the visibility map page and the page has become all
3061  * visible while we were busy locking the buffer, we'll have to unlock and
3062  * re-lock, to avoid holding the buffer lock across an I/O. That's a bit
3063  * unfortunate, but hopefully shouldn't happen often.
3064  */
3065  if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
3066  {
3067  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3068  visibilitymap_pin(relation, block, &vmbuffer);
3070  }
3071 
3072  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
3073  Assert(ItemIdIsNormal(lp));
3074 
3075  tp.t_tableOid = RelationGetRelid(relation);
3076  tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
3077  tp.t_len = ItemIdGetLength(lp);
3078  tp.t_self = *tid;
3079 
3080 l1:
3081  result = HeapTupleSatisfiesUpdate(&tp, cid, buffer);
3082 
3083  if (result == HeapTupleInvisible)
3084  {
3085  UnlockReleaseBuffer(buffer);
3086  ereport(ERROR,
3087  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3088  errmsg("attempted to delete invisible tuple")));
3089  }
3090  else if (result == HeapTupleBeingUpdated && wait)
3091  {
3092  TransactionId xwait;
3093  uint16 infomask;
3094 
3095  /* must copy state data before unlocking buffer */
3096  xwait = HeapTupleHeaderGetRawXmax(tp.t_data);
3097  infomask = tp.t_data->t_infomask;
3098 
3099  /*
3100  * Sleep until concurrent transaction ends -- except when there's a
3101  * single locker and it's our own transaction. Note we don't care
3102  * which lock mode the locker has, because we need the strongest one.
3103  *
3104  * Before sleeping, we need to acquire tuple lock to establish our
3105  * priority for the tuple (see heap_lock_tuple). LockTuple will
3106  * release us when we are next-in-line for the tuple.
3107  *
3108  * If we are forced to "start over" below, we keep the tuple lock;
3109  * this arranges that we stay at the head of the line while rechecking
3110  * tuple state.
3111  */
3112  if (infomask & HEAP_XMAX_IS_MULTI)
3113  {
3114  /* wait for multixact */
3115  if (DoesMultiXactIdConflict((MultiXactId) xwait, infomask,
3117  {
3118  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3119 
3120  /* acquire tuple lock, if necessary */
3122  LockWaitBlock, &have_tuple_lock);
3123 
3124  /* wait for multixact */
3126  relation, &(tp.t_self), XLTW_Delete,
3127  NULL);
3129 
3130  /*
3131  * If xwait had just locked the tuple then some other xact
3132  * could update this tuple before we get to this point. Check
3133  * for xmax change, and start over if so.
3134  */
3135  if (xmax_infomask_changed(tp.t_data->t_infomask, infomask) ||
3137  xwait))
3138  goto l1;
3139  }
3140 
3141  /*
3142  * You might think the multixact is necessarily done here, but not
3143  * so: it could have surviving members, namely our own xact or
3144  * other subxacts of this backend. It is legal for us to delete
3145  * the tuple in either case, however (the latter case is
3146  * essentially a situation of upgrading our former shared lock to
3147  * exclusive). We don't bother changing the on-disk hint bits
3148  * since we are about to overwrite the xmax altogether.
3149  */
3150  }
3151  else if (!TransactionIdIsCurrentTransactionId(xwait))
3152  {
3153  /*
3154  * Wait for regular transaction to end; but first, acquire tuple
3155  * lock.
3156  */
3157  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3159  LockWaitBlock, &have_tuple_lock);
3160  XactLockTableWait(xwait, relation, &(tp.t_self), XLTW_Delete);
3162 
3163  /*
3164  * xwait is done, but if xwait had just locked the tuple then some
3165  * other xact could update this tuple before we get to this point.
3166  * Check for xmax change, and start over if so.
3167  */
3168  if (xmax_infomask_changed(tp.t_data->t_infomask, infomask) ||
3170  xwait))
3171  goto l1;
3172 
3173  /* Otherwise check if it committed or aborted */
3174  UpdateXmaxHintBits(tp.t_data, buffer, xwait);
3175  }
3176 
3177  /*
3178  * We may overwrite if previous xmax aborted, or if it committed but
3179  * only locked the tuple without updating it.
3180  */
3181  if ((tp.t_data->t_infomask & HEAP_XMAX_INVALID) ||
3184  result = HeapTupleMayBeUpdated;
3185  else
3186  result = HeapTupleUpdated;
3187  }
3188 
3189  if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
3190  {
3191  /* Perform additional check for transaction-snapshot mode RI updates */
3192  if (!HeapTupleSatisfiesVisibility(&tp, crosscheck, buffer))
3193  result = HeapTupleUpdated;
3194  }
3195 
3196  if (result != HeapTupleMayBeUpdated)
3197  {
3198  Assert(result == HeapTupleSelfUpdated ||
3199  result == HeapTupleUpdated ||
3200  result == HeapTupleBeingUpdated);
3202  hufd->ctid = tp.t_data->t_ctid;
3204  if (result == HeapTupleSelfUpdated)
3205  hufd->cmax = HeapTupleHeaderGetCmax(tp.t_data);
3206  else
3207  hufd->cmax = InvalidCommandId;
3208  UnlockReleaseBuffer(buffer);
3209  if (have_tuple_lock)
3210  UnlockTupleTuplock(relation, &(tp.t_self), LockTupleExclusive);
3211  if (vmbuffer != InvalidBuffer)
3212  ReleaseBuffer(vmbuffer);
3213  return result;
3214  }
3215 
3216  /*
3217  * We're about to do the actual delete -- check for conflict first, to
3218  * avoid possibly having to roll back work we've just done.
3219  *
3220  * This is safe without a recheck as long as there is no possibility of
3221  * another process scanning the page between this check and the delete
3222  * being visible to the scan (i.e., an exclusive buffer content lock is
3223  * continuously held from this point until the tuple delete is visible).
3224  */
3225  CheckForSerializableConflictIn(relation, &tp, buffer);
3226 
3227  /* replace cid with a combo cid if necessary */
3228  HeapTupleHeaderAdjustCmax(tp.t_data, &cid, &iscombo);
3229 
3230  /*
3231  * Compute replica identity tuple before entering the critical section so
3232  * we don't PANIC upon a memory allocation failure.
3233  */
3234  old_key_tuple = ExtractReplicaIdentity(relation, &tp, true, &old_key_copied);
3235 
3236  /*
3237  * If this is the first possibly-multixact-able operation in the current
3238  * transaction, set my per-backend OldestMemberMXactId setting. We can be
3239  * certain that the transaction will never become a member of any older
3240  * MultiXactIds than that. (We have to do this even if we end up just
3241  * using our own TransactionId below, since some other backend could
3242  * incorporate our XID into a MultiXact immediately afterwards.)
3243  */
3245 
3248  xid, LockTupleExclusive, true,
3249  &new_xmax, &new_infomask, &new_infomask2);
3250 
3252 
3253  /*
3254  * If this transaction commits, the tuple will become DEAD sooner or
3255  * later. Set flag that this page is a candidate for pruning once our xid
3256  * falls below the OldestXmin horizon. If the transaction finally aborts,
3257  * the subsequent page pruning will be a no-op and the hint will be
3258  * cleared.
3259  */
3260  PageSetPrunable(page, xid);
3261 
3262  if (PageIsAllVisible(page))
3263  {
3264  all_visible_cleared = true;
3265  PageClearAllVisible(page);
3266  visibilitymap_clear(relation, BufferGetBlockNumber(buffer),
3267  vmbuffer, VISIBILITYMAP_VALID_BITS);
3268  }
3269 
3270  /* store transaction information of xact deleting the tuple */
3273  tp.t_data->t_infomask |= new_infomask;
3274  tp.t_data->t_infomask2 |= new_infomask2;
3276  HeapTupleHeaderSetXmax(tp.t_data, new_xmax);
3277  HeapTupleHeaderSetCmax(tp.t_data, cid, iscombo);
3278  /* Make sure there is no forward chain link in t_ctid */
3279  tp.t_data->t_ctid = tp.t_self;
3280 
3281  MarkBufferDirty(buffer);
3282 
3283  /*
3284  * XLOG stuff
3285  *
3286  * NB: heap_abort_speculative() uses the same xlog record and replay
3287  * routines.
3288  */
3289  if (RelationNeedsWAL(relation))
3290  {
3291  xl_heap_delete xlrec;
3292  XLogRecPtr recptr;
3293 
3294  /* For logical decode we need combocids to properly decode the catalog */
3296  log_heap_new_cid(relation, &tp);
3297 
3298  xlrec.flags = all_visible_cleared ? XLH_DELETE_ALL_VISIBLE_CLEARED : 0;
3300  tp.t_data->t_infomask2);
3302  xlrec.xmax = new_xmax;
3303 
3304  if (old_key_tuple != NULL)
3305  {
3306  if (relation->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
3308  else
3310  }
3311 
3312  XLogBeginInsert();
3313  XLogRegisterData((char *) &xlrec, SizeOfHeapDelete);
3314 
3315  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
3316 
3317  /*
3318  * Log replica identity of the deleted tuple if there is one
3319  */
3320  if (old_key_tuple != NULL)
3321  {
3322  xl_heap_header xlhdr;
3323 
3324  xlhdr.t_infomask2 = old_key_tuple->t_data->t_infomask2;
3325  xlhdr.t_infomask = old_key_tuple->t_data->t_infomask;
3326  xlhdr.t_hoff = old_key_tuple->t_data->t_hoff;
3327 
3328  XLogRegisterData((char *) &xlhdr, SizeOfHeapHeader);
3329  XLogRegisterData((char *) old_key_tuple->t_data
3331  old_key_tuple->t_len
3333  }
3334 
3335  /* filtering by origin on a row level is much more efficient */
3337 
3338  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
3339 
3340  PageSetLSN(page, recptr);
3341  }
3342 
3343  END_CRIT_SECTION();
3344 
3345  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3346 
3347  if (vmbuffer != InvalidBuffer)
3348  ReleaseBuffer(vmbuffer);
3349 
3350  /*
3351  * If the tuple has toasted out-of-line attributes, we need to delete
3352  * those items too. We have to do this before releasing the buffer
3353  * because we need to look at the contents of the tuple, but it's OK to
3354  * release the content lock on the buffer first.
3355  */
3356  if (relation->rd_rel->relkind != RELKIND_RELATION &&
3357  relation->rd_rel->relkind != RELKIND_MATVIEW)
3358  {
3359  /* toast table entries should never be recursively toasted */
3361  }
3362  else if (HeapTupleHasExternal(&tp))
3363  toast_delete(relation, &tp, false);
3364 
3365  /*
3366  * Mark tuple for invalidation from system caches at next command
3367  * boundary. We have to do this before releasing the buffer because we
3368  * need to look at the contents of the tuple.
3369  */
3370  CacheInvalidateHeapTuple(relation, &tp, NULL);
3371 
3372  /* Now we can release the buffer */
3373  ReleaseBuffer(buffer);
3374 
3375  /*
3376  * Release the lmgr tuple lock, if we had it.
3377  */
3378  if (have_tuple_lock)
3379  UnlockTupleTuplock(relation, &(tp.t_self), LockTupleExclusive);
3380 
3381  pgstat_count_heap_delete(relation);
3382 
3383  if (old_key_tuple != NULL && old_key_copied)
3384  heap_freetuple(old_key_tuple);
3385 
3386  return HeapTupleMayBeUpdated;
3387 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1585
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define SizeofHeapTupleHeader
Definition: htup_details.h:170
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup)
Definition: heapam.c:7693
#define HEAP_XMAX_BITS
Definition: htup_details.h:256
static uint8 compute_infobits(uint16 infomask, uint16 infomask2)
Definition: heapam.c:2952
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1087
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define PageIsAllVisible(page)
Definition: bufpage.h:382
uint32 TransactionId
Definition: c.h:397
HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, Buffer buffer)
Definition: tqual.c:460
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:773
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:2974
#define HeapTupleHeaderClearHotUpdated(tup)
Definition: htup_details.h:497
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define InvalidBuffer
Definition: buf.h:25
uint16 t_infomask2
Definition: heapam_xlog.h:122
#define PageSetPrunable(page, xid)
Definition: bufpage.h:395
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
int errcode(int sqlerrcode)
Definition: elog.c:575
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:192
return result
Definition: formatting.c:1618
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:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
void CheckForSerializableConflictIn(Relation relation, HeapTuple tuple, Buffer buffer)
Definition: predicate.c:4307
#define UnlockTupleTuplock(rel, tup, mode)
Definition: heapam.c:181
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
OffsetNumber offnum
Definition: heapam_xlog.h:105
void MultiXactIdSetOldestMember(void)
Definition: multixact.c:623
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
unsigned short uint16
Definition: c.h:267
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
bool IsInParallelMode(void)
Definition: xact.c:913
bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define REPLICA_IDENTITY_FULL
Definition: pg_class.h:179
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_ctid
Definition: htup_details.h:150
ItemPointerData t_self
Definition: htup.h:65
TransactionId xmax
Definition: heapam_xlog.h:104
static void MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, Relation rel, ItemPointer ctid, XLTW_Oper oper, int *remaining)
Definition: heapam.c:7109
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define SizeOfHeapDelete
Definition: heapam_xlog.h:110
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#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:374
HTSU_Result
Definition: snapshot.h:119
Oid t_tableOid
Definition: htup.h:66
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define HeapTupleHeaderSetCmax(tup, cid, iscombo)
Definition: htup_details.h:399
#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:5254
TransactionId xmax
Definition: heapam.h:71
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
#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:560
#define InvalidCommandId
Definition: c.h:414
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define HEAP_KEYS_UPDATED
Definition: htup_details.h:264
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
static void UpdateXmaxHintBits(HeapTupleHeader tuple, Buffer buffer, TransactionId xid)
Definition: heapam.c:2297
#define HEAP_MOVED
Definition: htup_details.h:202
static bool heap_acquire_tuplock(Relation relation, ItemPointer tid, LockTupleMode mode, LockWaitPolicy wait_policy, bool *have_tuple_lock)
Definition: heapam.c:5205
TransactionId MultiXactId
Definition: c.h:407
#define PageClearAllVisible(page)
Definition: bufpage.h:386
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
uint8 infobits_set
Definition: heapam_xlog.h:106
static HeapTuple ExtractReplicaIdentity(Relation rel, HeapTuple tup, bool key_modified, bool *copy)
Definition: heapam.c:7769
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:119
static bool DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, LockTupleMode lockmode)
Definition: heapam.c:6942
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
uint16 t_infomask
Definition: heapam_xlog.h:123
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
#define RelationNeedsWAL(relation)
Definition: rel.h:506
void pgstat_count_heap_delete(Relation rel)
Definition: pgstat.c:1917
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:674
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define XLH_DELETE_ALL_VISIBLE_CLEARED
Definition: heapam_xlog.h:92
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:75
#define RELKIND_RELATION
Definition: pg_class.h:160
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
#define XLOG_HEAP_DELETE
Definition: heapam_xlog.h:33
#define RelationGetRelid(relation)
Definition: rel.h:417
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
#define SizeOfHeapHeader
Definition: heapam_xlog.h:127
Pointer Page
Definition: bufpage.h:74
#define XLH_DELETE_CONTAINS_OLD_TUPLE
Definition: heapam_xlog.h:93
void heap_endscan ( HeapScanDesc  scan)

Definition at line 1578 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(), copy_heap_data(), CopyTo(), createdb(), DefineQueryRewrite(), do_autovacuum(), DropSetting(), DropTableSpace(), ExecEndBitmapHeapScan(), ExecEndSampleScan(), ExecEndSeqScan(), find_typed_table_dependencies(), get_database_list(), get_rel_oids(), 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().

1579 {
1580  /* Note: no locking manipulations needed */
1581 
1582  /*
1583  * unpin scan buffers
1584  */
1585  if (BufferIsValid(scan->rs_cbuf))
1586  ReleaseBuffer(scan->rs_cbuf);
1587 
1588  /*
1589  * decrement relation reference count and free scan descriptor storage
1590  */
1592 
1593  if (scan->rs_key)
1594  pfree(scan->rs_key);
1595 
1596  if (scan->rs_strategy != NULL)
1598 
1599  if (scan->rs_temp_snap)
1601 
1602  pfree(scan);
1603 }
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
void pfree(void *pointer)
Definition: mcxt.c:950
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2136
Snapshot rs_snapshot
Definition: relscan.h:48
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:900
bool rs_temp_snap
Definition: relscan.h:56
BufferAccessStrategy rs_strategy
Definition: relscan.h:63
Relation rs_rd
Definition: relscan.h:47
Buffer rs_cbuf
Definition: relscan.h:70
void FreeAccessStrategy(BufferAccessStrategy strategy)
Definition: freelist.c:580
#define NULL
Definition: c.h:229
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
ScanKey rs_key
Definition: relscan.h:50
bool heap_fetch ( Relation  relation,
Snapshot  snapshot,
HeapTuple  tuple,
Buffer userbuf,
bool  keep_buf,
Relation  stats_relation 
)

Definition at line 1862 of file heapam.c.

References buffer, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, CheckForSerializableConflictOut(), HeapTupleSatisfiesVisibility, InvalidBuffer, ItemIdGetLength, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, LockBuffer(), NULL, 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().

1868 {
1869  ItemPointer tid = &(tuple->t_self);
1870  ItemId lp;
1871  Buffer buffer;
1872  Page page;
1873  OffsetNumber offnum;
1874  bool valid;
1875 
1876  /*
1877  * Fetch and pin the appropriate page of the relation.
1878  */
1879  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
1880 
1881  /*
1882  * Need share lock on buffer to examine tuple commit status.
1883  */
1884  LockBuffer(buffer, BUFFER_LOCK_SHARE);
1885  page = BufferGetPage(buffer);
1886  TestForOldSnapshot(snapshot, relation, page);
1887 
1888  /*
1889  * We'd better check for out-of-range offnum in case of VACUUM since the
1890  * TID was obtained.
1891  */
1892  offnum = ItemPointerGetOffsetNumber(tid);
1893  if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(page))
1894  {
1895  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1896  if (keep_buf)
1897  *userbuf = buffer;
1898  else
1899  {
1900  ReleaseBuffer(buffer);
1901  *userbuf = InvalidBuffer;
1902  }
1903  tuple->t_data = NULL;
1904  return false;
1905  }
1906 
1907  /*
1908  * get the item line pointer corresponding to the requested tid
1909  */
1910  lp = PageGetItemId(page, offnum);
1911 
1912  /*
1913  * Must check for deleted tuple.
1914  */
1915  if (!ItemIdIsNormal(lp))
1916  {
1917  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1918  if (keep_buf)
1919  *userbuf = buffer;
1920  else
1921  {
1922  ReleaseBuffer(buffer);
1923  *userbuf = InvalidBuffer;
1924  }
1925  tuple->t_data = NULL;
1926  return false;
1927  }
1928 
1929  /*
1930  * fill in *tuple fields
1931  */
1932  tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1933  tuple->t_len = ItemIdGetLength(lp);
1934  tuple->t_tableOid = RelationGetRelid(relation);
1935 
1936  /*
1937  * check time qualification of tuple, then release lock
1938  */
1939  valid = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer);
1940 
1941  if (valid)
1942  PredicateLockTuple(relation, tuple, snapshot);
1943 
1944  CheckForSerializableConflictOut(valid, relation, tuple, buffer, snapshot);
1945 
1946  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1947 
1948  if (valid)
1949  {
1950  /*
1951  * All checks passed, so return the tuple as valid. Caller is now
1952  * responsible for releasing the buffer.
1953  */
1954  *userbuf = buffer;
1955 
1956  /* Count the successful fetch against appropriate rel, if any */
1957  if (stats_relation != NULL)
1958  pgstat_count_heap_fetch(stats_relation);
1959 
1960  return true;
1961  }
1962 
1963  /* Tuple failed time qual, but maybe caller wants to see it anyway. */
1964  if (keep_buf)
1965  *userbuf = buffer;
1966  else
1967  {
1968  ReleaseBuffer(buffer);
1969  *userbuf = InvalidBuffer;
1970  }
1971 
1972  return false;
1973 }
#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:354
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3926
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
ItemPointerData t_self
Definition: htup.h:65
#define pgstat_count_heap_fetch(rel)
Definition: pgstat.h:1258
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:232
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define NULL
Definition: c.h:229
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
void PredicateLockTuple(Relation relation, HeapTuple tuple, Snapshot snapshot)
Definition: predicate.c:2524
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
int Buffer
Definition: buf.h:23
#define RelationGetRelid(relation)
Definition: rel.h:417
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
void heap_finish_speculative ( Relation  relation,
HeapTuple  tuple 
)

Definition at line 5962 of file heapam.c.

References Assert, buffer, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, elog, END_CRIT_SECTION, ERROR, HeapTupleHeaderIsSpeculative, ItemIdIsNormal, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, LockBuffer(), MarkBufferDirty(), MaxOffsetNumber, NULL, 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().

5963 {
5964  Buffer buffer;
5965  Page page;
5966  OffsetNumber offnum;
5967  ItemId lp = NULL;
5968  HeapTupleHeader htup;
5969 
5970  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&(tuple->t_self)));
5972  page = (Page) BufferGetPage(buffer);
5973 
5974  offnum = ItemPointerGetOffsetNumber(&(tuple->t_self));
5975  if (PageGetMaxOffsetNumber(page) >= offnum)
5976  lp = PageGetItemId(page, offnum);
5977 
5978  if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
5979  elog(ERROR, "invalid lp");
5980 
5981  htup = (HeapTupleHeader) PageGetItem(page, lp);
5982 
5983  /* SpecTokenOffsetNumber should be distinguishable from any real offset */
5985  "invalid speculative token constant");
5986 
5987  /* NO EREPORT(ERROR) from here till changes are logged */
5989 
5991 
5992  MarkBufferDirty(buffer);
5993 
5994  /*
5995  * Replace the speculative insertion token with a real t_ctid, pointing to
5996  * itself like it does on regular tuples.
5997  */
5998  htup->t_ctid = tuple->t_self;
5999 
6000  /* XLOG stuff */
6001  if (RelationNeedsWAL(relation))
6002  {
6003  xl_heap_confirm xlrec;
6004  XLogRecPtr recptr;
6005 
6006  xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self);
6007 
6008  XLogBeginInsert();
6009 
6010  /* We want the same filtering on this as on a plain insert */
6012 
6013  XLogRegisterData((char *) &xlrec, SizeOfHeapConfirm);
6014  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
6015 
6016  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CONFIRM);
6017 
6018  PageSetLSN(page, recptr);
6019  }
6020 
6021  END_CRIT_SECTION();
6022 
6023  UnlockReleaseBuffer(buffer);
6024 }
OffsetNumber offnum
Definition: heapam_xlog.h:274
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:132
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:423
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:192
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:757
#define SpecTokenOffsetNumber
Definition: htup_details.h:285
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
ItemPointerData t_ctid
Definition: htup_details.h:150
ItemPointerData t_self
Definition: htup.h:65
#define REGBUF_STANDARD
Definition: xloginsert.h:35
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define SizeOfHeapConfirm
Definition: heapam_xlog.h:277
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
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 NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
#define RelationNeedsWAL(relation)
Definition: rel.h:506
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
#define XLOG_HEAP_CONFIRM
Definition: heapam_xlog.h:37
bool heap_freeze_tuple ( HeapTupleHeader  tuple,
TransactionId  cutoff_xid,
TransactionId  cutoff_multi 
)

Definition at line 6768 of file heapam.c.

References heap_execute_freeze_tuple(), and heap_prepare_freeze_tuple().

Referenced by rewrite_heap_tuple().

6770 {
6772  bool do_freeze;
6773  bool tuple_totally_frozen;
6774 
6775  do_freeze = heap_prepare_freeze_tuple(tuple, cutoff_xid, cutoff_multi,
6776  &frz, &tuple_totally_frozen);
6777 
6778  /*
6779  * Note that because this is not a WAL-logged operation, we don't need to
6780  * fill in the offset in the freeze record.
6781  */
6782 
6783  if (do_freeze)
6784  heap_execute_freeze_tuple(tuple, &frz);
6785  return do_freeze;
6786 }
void heap_execute_freeze_tuple(HeapTupleHeader tuple, xl_heap_freeze_tuple *frz)
Definition: heapam.c:6747
bool heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid, TransactionId cutoff_multi, xl_heap_freeze_tuple *frz, bool *totally_frozen_p)
Definition: heapam.c:6569
void heap_get_latest_tid ( Relation  relation,
Snapshot  snapshot,
ItemPointer  tid 
)

Definition at line 2167 of file heapam.c.

References buffer, BUFFER_LOCK_SHARE, BufferGetPage, CheckForSerializableConflictOut(), elog, ERROR, HEAP_XMAX_INVALID, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, 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().

2170 {
2171  BlockNumber blk;
2172  ItemPointerData ctid;
2173  TransactionId priorXmax;
2174 
2175  /* this is to avoid Assert failures on bad input */
2176  if (!ItemPointerIsValid(tid))
2177  return;
2178 
2179  /*
2180  * Since this can be called with user-supplied TID, don't trust the input
2181  * too much. (RelationGetNumberOfBlocks is an expensive check, so we
2182  * don't check t_ctid links again this way. Note that it would not do to
2183  * call it just once and save the result, either.)
2184  */
2185  blk = ItemPointerGetBlockNumber(tid);
2186  if (blk >= RelationGetNumberOfBlocks(relation))
2187  elog(ERROR, "block number %u is out of range for relation \"%s\"",
2188  blk, RelationGetRelationName(relation));
2189 
2190  /*
2191  * Loop to chase down t_ctid links. At top of loop, ctid is the tuple we
2192  * need to examine, and *tid is the TID we will return if ctid turns out
2193  * to be bogus.
2194  *
2195  * Note that we will loop until we reach the end of the t_ctid chain.
2196  * Depending on the snapshot passed, there might be at most one visible
2197  * version of the row, but we don't try to optimize for that.
2198  */
2199  ctid = *tid;
2200  priorXmax = InvalidTransactionId; /* cannot check first XMIN */
2201  for (;;)
2202  {
2203  Buffer buffer;
2204  Page page;
2205  OffsetNumber offnum;
2206  ItemId lp;
2207  HeapTupleData tp;
2208  bool valid;
2209 
2210  /*
2211  * Read, pin, and lock the page.
2212  */
2213  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&ctid));
2214  LockBuffer(buffer, BUFFER_LOCK_SHARE);
2215  page = BufferGetPage(buffer);
2216  TestForOldSnapshot(snapshot, relation, page);
2217 
2218  /*
2219  * Check for bogus item number. This is not treated as an error
2220  * condition because it can happen while following a t_ctid link. We
2221  * just assume that the prior tid is OK and return it unchanged.
2222  */
2223  offnum = ItemPointerGetOffsetNumber(&ctid);
2224  if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(page))
2225  {
2226  UnlockReleaseBuffer(buffer);
2227  break;
2228  }
2229  lp = PageGetItemId(page, offnum);
2230  if (!ItemIdIsNormal(lp))
2231  {
2232  UnlockReleaseBuffer(buffer);
2233  break;
2234  }
2235 
2236  /* OK to access the tuple */
2237  tp.t_self = ctid;
2238  tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
2239  tp.t_len = ItemIdGetLength(lp);
2240  tp.t_tableOid = RelationGetRelid(relation);
2241 
2242  /*
2243  * After following a t_ctid link, we might arrive at an unrelated
2244  * tuple. Check for XMIN match.
2245  */
2246  if (TransactionIdIsValid(priorXmax) &&
2248  {
2249  UnlockReleaseBuffer(buffer);
2250  break;
2251  }
2252 
2253  /*
2254  * Check time qualification of tuple; if visible, set it as the new
2255  * result candidate.
2256  */
2257  valid = HeapTupleSatisfiesVisibility(&tp, snapshot, buffer);
2258  CheckForSerializableConflictOut(valid, relation, &tp, buffer, snapshot);
2259  if (valid)
2260  *tid = ctid;
2261 
2262  /*
2263  * If there's a valid t_ctid link, follow it, else we're done.
2264  */
2265  if ((tp.t_data->t_infomask & HEAP_XMAX_INVALID) ||
2268  {
2269  UnlockReleaseBuffer(buffer);
2270  break;
2271  }
2272 
2273  ctid = tp.t_data->t_ctid;
2274  priorXmax = HeapTupleHeaderGetUpdateXid(tp.t_data);
2275  UnlockReleaseBuffer(buffer);
2276  } /* end of loop */
2277 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1585
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
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:397
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
uint32 BlockNumber
Definition: block.h:31
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3926
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
#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:193
ItemPointerData t_ctid
Definition: htup_details.h:150
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:437
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
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:207
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
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:75
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int Buffer
Definition: buf.h:23
#define RelationGetRelid(relation)
Definition: rel.h:417
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
void heap_get_root_tuples ( Page  page,
OffsetNumber root_offsets 
)

Definition at line 744 of file pruneheap.c.

References Assert, FirstOffsetNumber, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, 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().

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

Definition at line 1794 of file heapam.c.

References HEAPDEBUG_1, HEAPDEBUG_2, HEAPDEBUG_3, heapgettup(), heapgettup_pagemode(), NULL, 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(), copy_heap_data(), CopyTo(), createdb(), DefineQueryRewrite(), do_autovacuum(), DropSetting(), DropTableSpace(), find_typed_table_dependencies(), get_database_list(), get_rel_oids(), 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().

1795 {
1796  /* Note: no locking manipulations needed */
1797 
1798  HEAPDEBUG_1; /* heap_getnext( info ) */
1799 
1800  if (scan->rs_pageatatime)
1801  heapgettup_pagemode(scan, direction,
1802  scan->rs_nkeys, scan->rs_key);
1803  else
1804  heapgettup(scan, direction, scan->rs_nkeys, scan->rs_key);
1805 
1806  if (scan->rs_ctup.t_data == NULL)
1807  {
1808  HEAPDEBUG_2; /* heap_getnext returning EOS */
1809  return NULL;
1810  }
1811 
1812  /*
1813  * if we get here it means we have a new current scan tuple, so point to
1814  * the proper return buffer and return the tuple.
1815  */
1816  HEAPDEBUG_3; /* heap_getnext returning tuple */
1817 
1819 
1820  return &(scan->rs_ctup);
1821 }
#define HEAPDEBUG_2
Definition: heapam.c:1788
HeapTupleData rs_ctup
Definition: relscan.h:68
HeapTupleHeader t_data
Definition: htup.h:67
bool rs_pageatatime
Definition: relscan.h:53
#define HEAPDEBUG_1
Definition: heapam.c:1787
static void heapgettup(HeapScanDesc scan, ScanDirection dir, int nkeys, ScanKey key)
Definition: heapam.c:479
Relation rs_rd
Definition: relscan.h:47
#define NULL
Definition: c.h:229
#define HEAPDEBUG_3
Definition: heapam.c:1789
#define pgstat_count_heap_getnext(rel)
Definition: pgstat.h:1253
static void heapgettup_pagemode(HeapScanDesc scan, ScanDirection dir, int nkeys, ScanKey key)
Definition: heapam.c:781
ScanKey rs_key
Definition: relscan.h:50
bool heap_hot_search ( ItemPointer  tid,
Relation  relation,
Snapshot  snapshot,
bool all_dead 
)

Definition at line 2139 of file heapam.c.

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

Referenced by _bt_check_unique(), and unique_key_recheck().

2141 {
2142  bool result;
2143  Buffer buffer;
2144  HeapTupleData heapTuple;
2145 
2146  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
2147  LockBuffer(buffer, BUFFER_LOCK_SHARE);
2148  result = heap_hot_search_buffer(tid, relation, buffer, snapshot,
2149  &heapTuple, all_dead, true);
2150  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
2151  ReleaseBuffer(buffer);
2152  return result;
2153 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
return result
Definition: formatting.c:1618
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:1997
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
int Buffer
Definition: buf.h:23
bool heap_hot_search_buffer ( ItemPointer  tid,
Relation  relation,
Buffer  buffer,
Snapshot  snapshot,
HeapTuple  heapTuple,
bool all_dead,
bool  first_call 
)

Definition at line 1997 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().

2000 {
2001  Page dp = (Page) BufferGetPage(buffer);
2002  TransactionId prev_xmax = InvalidTransactionId;
2003  OffsetNumber offnum;
2004  bool at_chain_start;
2005  bool valid;
2006  bool skip;
2007 
2008  /* If this is not the first call, previous call returned a (live!) tuple */
2009  if (all_dead)
2010  *all_dead = first_call;
2011 
2013 
2015  offnum = ItemPointerGetOffsetNumber(tid);
2016  at_chain_start = first_call;
2017  skip = !first_call;
2018 
2019  heapTuple->t_self = *tid;
2020 
2021  /* Scan through possible multiple members of HOT-chain */
2022  for (;;)
2023  {
2024  ItemId lp;
2025 
2026  /* check for bogus TID */
2027  if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
2028  break;
2029 
2030  lp = PageGetItemId(dp, offnum);
2031 
2032  /* check for unused, dead, or redirected items */
2033  if (!ItemIdIsNormal(lp))
2034  {
2035  /* We should only see a redirect at start of chain */
2036  if (ItemIdIsRedirected(lp) && at_chain_start)
2037  {
2038  /* Follow the redirect */
2039  offnum = ItemIdGetRedirect(lp);
2040  at_chain_start = false;
2041  continue;
2042  }
2043  /* else must be end of chain */
2044  break;
2045  }
2046 
2047  heapTuple->t_data = (HeapTupleHeader) PageGetItem(dp, lp);
2048  heapTuple->t_len = ItemIdGetLength(lp);
2049  heapTuple->t_tableOid = RelationGetRelid(relation);
2050  ItemPointerSetOffsetNumber(&heapTuple->t_self, offnum);
2051 
2052  /*
2053  * Shouldn't see a HEAP_ONLY tuple at chain start.
2054  */
2055  if (at_chain_start && HeapTupleIsHeapOnly(heapTuple))
2056  break;
2057 
2058  /*
2059  * The xmin should match the previous xmax value, else chain is
2060  * broken.
2061  */
2062  if (TransactionIdIsValid(prev_xmax) &&
2063  !TransactionIdEquals(prev_xmax,
2064  HeapTupleHeaderGetXmin(heapTuple->t_data)))
2065  break;
2066 
2067  /*
2068  * When first_call is true (and thus, skip is initially false) we'll
2069  * return the first tuple we find. But on later passes, heapTuple
2070  * will initially be pointing to the tuple we returned last time.
2071  * Returning it again would be incorrect (and would loop forever), so
2072  * we skip it and return the next match we find.
2073  */
2074  if (!skip)
2075  {
2076  /*
2077  * For the benefit of logical decoding, have t_self point at the
2078  * element of the HOT chain we're currently investigating instead
2079  * of the root tuple of the HOT chain. This is important because
2080  * the *Satisfies routine for historical mvcc snapshots needs the
2081  * correct tid to decide about the visibility in some cases.
2082  */
2083  ItemPointerSet(&(heapTuple->t_self), BufferGetBlockNumber(buffer), offnum);
2084 
2085  /* If it's visible per the snapshot, we must return it */
2086  valid = HeapTupleSatisfiesVisibility(heapTuple, snapshot, buffer);
2087  CheckForSerializableConflictOut(valid, relation, heapTuple,
2088  buffer, snapshot);
2089  /* reset to original, non-redirected, tid */
2090  heapTuple->t_self = *tid;
2091 
2092  if (valid)
2093  {
2094  ItemPointerSetOffsetNumber(tid, offnum);
2095  PredicateLockTuple(relation, heapTuple, snapshot);
2096  if (all_dead)
2097  *all_dead = false;
2098  return true;
2099  }
2100  }
2101  skip = false;
2102 
2103  /*
2104  * If we can't see it, maybe no one else can either. At caller
2105  * request, check whether all chain members are dead to all
2106  * transactions.
2107  */
2108  if (all_dead && *all_dead &&
2110  *all_dead = false;
2111 
2112  /*
2113  * Check to see if HOT chain continues past this tuple; if so fetch
2114  * the next offnum and loop around.
2115  */
2116  if (HeapTupleIsHotUpdated(heapTuple))
2117  {
2120  offnum = ItemPointerGetOffsetNumber(&heapTuple->t_data->t_ctid);
2121  at_chain_start = false;
2122  prev_xmax = HeapTupleHeaderGetUpdateXid(heapTuple->t_data);
2123  }
2124  else
2125  break; /* end of chain */
2126  }
2127 
2128  return false;
2129 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
static void skip(struct vars *v)
Definition: regc_lex.c:1109
#define ItemIdIsRedirected(itemId)
Definition: itemid.h:105
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:397
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define ItemIdGetRedirect(itemId)
Definition: itemid.h:77
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3926
bool HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin)
Definition: tqual.c:1409
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleIsHotUpdated(tuple)
Definition: htup_details.h:677
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
ItemPointerData t_ctid
Definition: htup_details.h:150
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:232
#define HeapTupleIsHeapOnly(tuple)
Definition: htup_details.h:686
#define Assert(condition)
Definition: c.h:675
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
void PredicateLockTuple(Relation relation, HeapTuple tuple, Snapshot snapshot)
Definition: predicate.c:2524
#define ItemPointerSetOffsetNumber(pointer, offsetNumber)
Definition: itemptr.h:125
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define RelationGetRelid(relation)
Definition: rel.h:417
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:104
void heap_inplace_update ( Relation  relation,
HeapTuple  tuple 
)

Definition at line 6194 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(), NULL, 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().

6195 {
6196  Buffer buffer;
6197  Page page;
6198  OffsetNumber offnum;
6199  ItemId lp = NULL;
6200  HeapTupleHeader htup;
6201  uint32 oldlen;
6202  uint32 newlen;
6203 
6204  /*
6205  * For now, parallel operations are required to be strictly read-only.
6206  * Unlike a regular update, this should never create a combo CID, so it
6207  * might be possible to relax this restriction, but not without more
6208  * thought and testing. It's not clear that it would be useful, anyway.
6209  */
6210  if (IsInParallelMode())
6211  ereport(ERROR,
6212  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
6213  errmsg("cannot update tuples during a parallel operation")));
6214 
6215  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&(tuple->t_self)));
6217  page = (Page) BufferGetPage(buffer);
6218 
6219  offnum = ItemPointerGetOffsetNumber(&(tuple->t_self));
6220  if (PageGetMaxOffsetNumber(page) >= offnum)
6221  lp = PageGetItemId(page, offnum);
6222 
6223  if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
6224  elog(ERROR, "invalid lp");
6225 
6226  htup = (HeapTupleHeader) PageGetItem(page, lp);
6227 
6228  oldlen = ItemIdGetLength(lp) - htup->t_hoff;
6229  newlen = tuple->t_len - tuple->t_data->t_hoff;
6230  if (oldlen != newlen || htup->t_hoff != tuple->t_data->t_hoff)
6231  elog(ERROR, "wrong tuple length");
6232 
6233  /* NO EREPORT(ERROR) from here till changes are logged */
6235 
6236  memcpy((char *) htup + htup->t_hoff,
6237  (char *) tuple->t_data + tuple->t_data->t_hoff,
6238  newlen);
6239 
6240  MarkBufferDirty(buffer);
6241 
6242  /* XLOG stuff */
6243  if (RelationNeedsWAL(relation))
6244  {
6245  xl_heap_inplace xlrec;
6246  XLogRecPtr recptr;
6247 
6248  xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self);
6249 
6250  XLogBeginInsert();
6251  XLogRegisterData((char *) &xlrec, SizeOfHeapInplace);
6252 
6253  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
6254  XLogRegisterBufData(0, (char *) htup + htup->t_hoff, newlen);
6255 
6256  /* inplace updates aren't decoded atm, don't log the origin */
6257 
6258  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_INPLACE);
6259 
6260  PageSetLSN(page, recptr);
6261  }
6262 
6263  END_CRIT_SECTION();
6264 
6265  UnlockReleaseBuffer(buffer);
6266 
6267  /*
6268  * Send out shared cache inval if necessary. Note that because we only
6269  * pass the new version of the tuple, this mustn't be used for any
6270  * operations that could change catcache lookup keys. But we aren't
6271  * bothering with index updates either, so that's true a fortiori.
6272  */
6274  CacheInvalidateHeapTuple(relation, tuple, NULL);
6275 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1087
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:132
#define SizeOfHeapInplace
Definition: heapam_xlog.h:286
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
int errcode(int sqlerrcode)
Definition: elog.c:575
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
bool IsInParallelMode(void)
Definition: xact.c:913
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:35
unsigned int uint32
Definition: c.h:268
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
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:282
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
#define XLOG_HEAP_INPLACE
Definition: heapam_xlog.h:39
#define RelationNeedsWAL(relation)
Definition: rel.h:506
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
Oid heap_insert ( Relation  relation,
HeapTuple  tup,
CommandId  cid,
int  options,
BulkInsertState  bistate 
)

Definition at line 2396 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().

2398 {
2400  HeapTuple heaptup;
2401  Buffer buffer;
2402  Buffer vmbuffer = InvalidBuffer;
2403  bool all_visible_cleared = false;
2404 
2405  /*
2406  * Fill in tuple header fields, assign an OID, and toast the tuple if
2407  * necessary.
2408  *
2409  * Note: below this point, heaptup is the data we actually intend to store
2410  * into the relation; tup is the caller's original untoasted data.
2411  */
2412  heaptup = heap_prepare_insert(relation, tup, xid, cid, options);
2413 
2414  /*
2415  * Find buffer to insert this tuple into. If the page is all visible,
2416  * this will also pin the requisite visibility map page.
2417  */
2418  buffer = RelationGetBufferForTuple(relation, heaptup->t_len,
2419  InvalidBuffer, options, bistate,
2420  &vmbuffer, NULL);
2421 
2422  /*
2423  * We're about to do the actual insert -- but check for conflict first, to
2424  * avoid possibly having to roll back work we've just done.
2425  *
2426  * This is safe without a recheck as long as there is no possibility of
2427  * another process scanning the page between this check and the insert
2428  * being visible to the scan (i.e., an exclusive buffer content lock is
2429  * continuously held from this point until the tuple insert is visible).
2430  *
2431  * For a heap insert, we only need to check for table-level SSI locks. Our
2432  * new tuple can't possibly conflict with existing tuple locks, and heap
2433  * page locks are only consolidated versions of tuple locks; they do not
2434  * lock "gaps" as index page locks do. So we don't need to specify a
2435  * buffer when making the call, which makes for a faster check.
2436  */
2438 
2439  /* NO EREPORT(ERROR) from here till changes are logged */
2441 
2442  RelationPutHeapTuple(relation, buffer, heaptup,
2443  (options & HEAP_INSERT_SPECULATIVE) != 0);
2444 
2445  if (PageIsAllVisible(BufferGetPage(buffer)))
2446  {
2447  all_visible_cleared = true;
2449  visibilitymap_clear(relation,
2450  ItemPointerGetBlockNumber(&(heaptup->t_self)),
2451  vmbuffer, VISIBILITYMAP_VALID_BITS);
2452  }
2453 
2454  /*
2455  * XXX Should we set PageSetPrunable on this page ?
2456  *
2457  * The inserting transaction may eventually abort thus making this tuple
2458  * DEAD and hence available for pruning. Though we don't want to optimize
2459  * for aborts, if no other tuple in this page is UPDATEd/DELETEd, the
2460  * aborted tuple will never be pruned until next vacuum is triggered.
2461  *
2462  * If you do add PageSetPrunable here, add it in heap_xlog_insert too.
2463  */
2464 
2465  MarkBufferDirty(buffer);
2466 
2467  /* XLOG stuff */
2468  if (!(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation))
2469  {
2470  xl_heap_insert xlrec;
2471  xl_heap_header xlhdr;
2472  XLogRecPtr recptr;
2473  Page page = BufferGetPage(buffer);
2474  uint8 info = XLOG_HEAP_INSERT;
2475  int bufflags = 0;
2476 
2477  /*
2478  * If this is a catalog, we need to transmit combocids to properly
2479  * decode, so log that as well.
2480  */
2482  log_heap_new_cid(relation, heaptup);
2483 
2484  /*
2485  * If this is the single and first tuple on page, we can reinit the
2486  * page instead of restoring the whole thing. Set flag, and hide
2487  * buffer references from XLogInsert.
2488  */
2489  if (ItemPointerGetOffsetNumber(&(heaptup->t_self)) == FirstOffsetNumber &&
2491  {
2492  info |= XLOG_HEAP_INIT_PAGE;
2493  bufflags |= REGBUF_WILL_INIT;
2494  }
2495 
2496  xlrec.offnum = ItemPointerGetOffsetNumber(&heaptup->t_self);
2497  xlrec.flags = 0;
2498  if (all_visible_cleared)
2503 
2504  /*
2505  * For logical decoding, we need the tuple even if we're doing a full
2506  * page write, so make sure it's included even if we take a full-page
2507  * image. (XXX We could alternatively store a pointer into the FPW).
2508  */
2509  if (RelationIsLogicallyLogged(relation))
2510  {
2512  bufflags |= REGBUF_KEEP_DATA;
2513  }
2514 
2515  XLogBeginInsert();
2516  XLogRegisterData((char *) &xlrec, SizeOfHeapInsert);
2517 
2518  xlhdr.t_infomask2 = heaptup->t_data->t_infomask2;
2519  xlhdr.t_infomask = heaptup->t_data->t_infomask;
2520  xlhdr.t_hoff = heaptup->t_data->t_hoff;
2521 
2522  /*
2523  * note we mark xlhdr as belonging to buffer; if XLogInsert decides to
2524  * write the whole page to the xlog, we don't need to store
2525  * xl_heap_header in the xlog.
2526  */
2527  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags);
2528  XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);
2529  /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
2531  (char *) heaptup->t_data + SizeofHeapTupleHeader,
2532  heaptup->t_len - SizeofHeapTupleHeader);
2533 
2534  /* filtering by origin on a row level is much more efficient */
2536 
2537  recptr = XLogInsert(RM_HEAP_ID, info);
2538 
2539  PageSetLSN(page, recptr);
2540  }
2541 
2542  END_CRIT_SECTION();
2543 
2544  UnlockReleaseBuffer(buffer);
2545  if (vmbuffer != InvalidBuffer)
2546  ReleaseBuffer(vmbuffer);
2547 
2548  /*
2549  * If tuple is cachable, mark it for invalidation from the caches in case
2550  * we abort. Note it is OK to do this after releasing the buffer, because
2551  * the heaptup data structure is all in local memory, not in the shared
2552  * buffer.
2553  */
2554  CacheInvalidateHeapTuple(relation, heaptup, NULL);
2555 
2556  /* Note: speculative insertions are counted too, even if aborted later */
2557  pgstat_count_heap_insert(relation, 1);
2558 
2559  /*
2560  * If heaptup is a private copy, release it. Don't forget to copy t_self
2561  * back to the caller's image, too.
2562  */
2563  if (heaptup != tup)
2564  {
2565  tup->t_self = heaptup->t_self;
2566  heap_freetuple(heaptup);
2567  }
2568 
2569  return HeapTupleGetOid(tup);
2570 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
#define SizeofHeapTupleHeader
Definition: htup_details.h:170
#define XLOG_HEAP_INSERT
Definition: heapam_xlog.h:32
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup)
Definition: heapam.c:7693
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1087
static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid, CommandId cid, int options)
Definition: heapam.c:2580
#define PageIsAllVisible(page)
Definition: bufpage.h:382
uint32 TransactionId
Definition: c.h:397
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:132
unsigned char uint8
Definition: c.h:266
#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:122
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
#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:576
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
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:4307
#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:67
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:35
Buffer RelationGetBufferForTuple(Relation relation, Size len, Buffer otherBuffer, int options, BulkInsertState bistate, Buffer *vmbuffer, Buffer *vmbuffer_other)
Definition: hio.c:297
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:560
#define REGBUF_KEEP_DATA
Definition: xloginsert.h:38
#define PageClearAllVisible(page)
Definition: bufpage.h:386
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
uint16 t_infomask
Definition: heapam_xlog.h:123
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
#define RelationNeedsWAL(relation)
Definition: rel.h:506
#define SizeOfHeapInsert
Definition: heapam_xlog.h:138
#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:1871
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
OffsetNumber offnum
Definition: heapam_xlog.h:132
#define SizeOfHeapHeader
Definition: heapam_xlog.h:127
Pointer Page
Definition: bufpage.h:74
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 4539 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(), result, 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().

4543 {
4545  ItemPointer tid = &(tuple->t_self);
4546  ItemId lp;
4547  Page page;
4548  Buffer vmbuffer = InvalidBuffer;
4549  BlockNumber block;
4550  TransactionId xid,
4551  xmax;
4552  uint16 old_infomask,
4553  new_infomask,
4554  new_infomask2;
4555  bool first_time = true;
4556  bool have_tuple_lock = false;
4557  bool cleared_all_frozen = false;
4558 
4559  *buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
4560  block = ItemPointerGetBlockNumber(tid);
4561 
4562  /*
4563  * Before locking the buffer, pin the visibility map page if it appears to
4564  * be necessary. Since we haven't got the lock yet, someone else might be
4565  * in the middle of changing this, so we'll need to recheck after we have
4566  * the lock.
4567  */
4569  visibilitymap_pin(relation, block, &vmbuffer);
4570 
4572 
4573  page = BufferGetPage(*buffer);
4574  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
4575  Assert(ItemIdIsNormal(lp));
4576 
4577  tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
4578  tuple->t_len = ItemIdGetLength(lp);
4579  tuple->t_tableOid = RelationGetRelid(relation);
4580 
4581 l3:
4582  result = HeapTupleSatisfiesUpdate(tuple, cid, *buffer);
4583 
4584  if (result == HeapTupleInvisible)
4585  {
4586  /*
4587  * This is possible, but only when locking a tuple for ON CONFLICT
4588  * UPDATE. We return this value here rather than throwing an error in
4589  * order to give that case the opportunity to throw a more specific
4590  * error.
4591  */
4592  result = HeapTupleInvisible;
4593  goto out_locked;
4594  }
4595  else if (result == HeapTupleBeingUpdated || result == HeapTupleUpdated)
4596  {
4597  TransactionId xwait;
4598  uint16 infomask;
4599  uint16 infomask2;
4600  bool require_sleep;
4601  ItemPointerData t_ctid;
4602 
4603  /* must copy state data before unlocking buffer */
4604  xwait = HeapTupleHeaderGetRawXmax(tuple->t_data);
4605  infomask = tuple->t_data->t_infomask;
4606  infomask2 = tuple->t_data->t_infomask2;
4607  ItemPointerCopy(&tuple->t_data->t_ctid, &t_ctid);
4608 
4610 
4611  /*
4612  * If any subtransaction of the current top transaction already holds
4613  * a lock as strong as or stronger than what we're requesting, we
4614  * effectively hold the desired lock already. We *must* succeed
4615  * without trying to take the tuple lock, else we will deadlock
4616  * against anyone wanting to acquire a stronger lock.
4617  *
4618  * Note we only do this the first time we loop on the HTSU result;
4619  * there is no point in testing in subsequent passes, because
4620  * evidently our own transaction cannot have acquired a new lock after
4621  * the first time we checked.
4622  */
4623  if (first_time)
4624  {
4625  first_time = false;
4626 
4627  if (infomask & HEAP_XMAX_IS_MULTI)
4628  {
4629  int i;
4630  int nmembers;
4631  MultiXactMember *members;
4632 
4633  /*
4634  * We don't need to allow old multixacts here; if that had
4635  * been the case, HeapTupleSatisfiesUpdate would have returned
4636  * MayBeUpdated and we wouldn't be here.
4637  */
4638  nmembers =
4639  GetMultiXactIdMembers(xwait, &members, false,
4640  HEAP_XMAX_IS_LOCKED_ONLY(infomask));
4641 
4642  for (i = 0; i < nmembers; i++)
4643  {
4644  /* only consider members of our own transaction */
4645  if (!TransactionIdIsCurrentTransactionId(members[i].xid))
4646  continue;
4647 
4648  if (TUPLOCK_from_mxstatus(members[i].status) >= mode)
4649  {
4650  pfree(members);
4651  result = HeapTupleMayBeUpdated;
4652  goto out_unlocked;
4653  }
4654  }
4655 
4656  if (members)
4657  pfree(members);
4658  }
4659  else if (TransactionIdIsCurrentTransactionId(xwait))
4660  {
4661  switch (mode)
4662  {
4663  case LockTupleKeyShare:
4664  Assert(HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) ||
4665  HEAP_XMAX_IS_SHR_LOCKED(infomask) ||
4666  HEAP_XMAX_IS_EXCL_LOCKED(infomask));
4667  result = HeapTupleMayBeUpdated;
4668  goto out_unlocked;
4669  case LockTupleShare:
4670  if (HEAP_XMAX_IS_SHR_LOCKED(infomask) ||
4671  HEAP_XMAX_IS_EXCL_LOCKED(infomask))
4672  {
4673  result = HeapTupleMayBeUpdated;
4674  goto out_unlocked;
4675  }
4676  break;
4678  if (HEAP_XMAX_IS_EXCL_LOCKED(infomask))
4679  {
4680  result = HeapTupleMayBeUpdated;
4681  goto out_unlocked;
4682  }
4683  break;
4684  case LockTupleExclusive:
4685  if (HEAP_XMAX_IS_EXCL_LOCKED(infomask) &&
4686  infomask2 & HEAP_KEYS_UPDATED)
4687  {
4688  result = HeapTupleMayBeUpdated;
4689  goto out_unlocked;
4690  }
4691  break;
4692  }
4693  }
4694  }
4695 
4696  /*
4697  * Initially assume that we will have to wait for the locking
4698  * transaction(s) to finish. We check various cases below in which
4699  * this can be turned off.
4700  */
4701  require_sleep = true;
4702  if (mode == LockTupleKeyShare)
4703  {
4704  /*
4705  * If we're requesting KeyShare, and there's no update present, we
4706  * don't need to wait. Even if there is an update, we can still
4707  * continue if the key hasn't been modified.
4708  *
4709  * However, if there are updates, we need to walk the update chain
4710  * to mark future versions of the row as locked, too. That way,
4711  * if somebody deletes that future version, we're protected
4712  * against the key going away. This locking of future versions
4713  * could block momentarily, if a concurrent transaction is
4714  * deleting a key; or it could return a value to the effect that
4715  * the transaction deleting the key has already committed. So we
4716  * do this before re-locking the buffer; otherwise this would be
4717  * prone to deadlocks.
4718  *
4719  * Note that the TID we're locking was grabbed before we unlocked
4720  * the buffer. For it to change while we're not looking, the
4721  * other properties we're testing for below after re-locking the
4722  * buffer would also change, in which case we would restart this
4723  * loop above.
4724  */
4725  if (!(infomask2 & HEAP_KEYS_UPDATED))
4726  {
4727  bool updated;
4728 
4729  updated = !HEAP_XMAX_IS_LOCKED_ONLY(infomask);
4730 
4731  /*
4732  * If there are updates, follow the update chain; bail out if
4733  * that cannot be done.
4734  */
4735  if (follow_updates && updated)
4736  {
4737  HTSU_Result res;
4738 
4739  res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
4741  mode);
4742  if (res != HeapTupleMayBeUpdated)
4743  {
4744  result = res;
4745  /* recovery code expects to have buffer lock held */
4747  goto failed;
4748  }
4749  }
4750 
4752 
4753  /*
4754  * Make sure it's still an appropriate lock, else start over.
4755  * Also, if it wasn't updated before we released the lock, but
4756  * is updated now, we start over too; the reason is that we
4757  * now need to follow the update chain to lock the new
4758  * versions.
4759  */
4760  if (!HeapTupleHeaderIsOnlyLocked(tuple->t_data) &&
4761  ((tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED) ||
4762  !updated))
4763  goto l3;
4764 
4765  /* Things look okay, so we can skip sleeping */
4766  require_sleep = false;
4767 
4768  /*
4769  * Note we allow Xmax to change here; other updaters/lockers
4770  * could have modified it before we grabbed the buffer lock.
4771  * However, this is not a problem, because with the recheck we
4772  * just did we ensure that they still don't conflict with the
4773  * lock we want.
4774  */
4775  }
4776  }
4777  else if (mode == LockTupleShare)
4778  {
4779  /*
4780  * If we're requesting Share, we can similarly avoid sleeping if
4781  * there's no update and no exclusive lock present.
4782  */
4783  if (HEAP_XMAX_IS_LOCKED_ONLY(infomask) &&
4784  !HEAP_XMAX_IS_EXCL_LOCKED(infomask))
4785  {
4787 
4788  /*
4789  * Make sure it's still an appropriate lock, else start over.
4790  * See above about allowing xmax to change.
4791  */
4792  if (!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_data->t_infomask) ||
4794  goto l3;
4795  require_sleep = false;
4796  }
4797  }
4798  else if (mode == LockTupleNoKeyExclusive)
4799  {
4800  /*
4801  * If we're requesting NoKeyExclusive, we might also be able to
4802  * avoid sleeping; just ensure that there no conflicting lock
4803  * already acquired.
4804  */
4805  if (infomask & HEAP_XMAX_IS_MULTI)
4806  {
4807  if (!DoesMultiXactIdConflict((MultiXactId) xwait, infomask,
4808  mode))
4809  {
4810  /*
4811  * No conflict, but if the xmax changed under us in the
4812  * meantime, start over.
4813  */
4815  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
4817  xwait))
4818  goto l3;
4819 
4820  /* otherwise, we're good */
4821  require_sleep = false;
4822  }
4823  }
4824  else if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask))
4825  {
4827 
4828  /* if the xmax changed in the meantime, start over */
4829  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
4832  xwait))
4833  goto l3;
4834  /* otherwise, we're good */
4835  require_sleep = false;
4836  }
4837  }
4838 
4839  /*
4840  * As a check independent from those above, we can also avoid sleeping
4841  * if the current transaction is the sole locker of the tuple. Note
4842  * that the strength of the lock already held is irrelevant; this is
4843  * not about recording the lock in Xmax (which will be done regardless
4844  * of this optimization, below). Also, note that the cases where we
4845  * hold a lock stronger than we are requesting are already handled
4846  * above by not doing anything.
4847  *
4848  * Note we only deal with the non-multixact case here; MultiXactIdWait
4849  * is well equipped to deal with this situation on its own.
4850  */
4851  if (require_sleep && !(infomask & HEAP_XMAX_IS_MULTI) &&
4853  {
4854  /* ... but if the xmax changed in the meantime, start over */
4856  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
4858  xwait))
4859  goto l3;
4861  require_sleep = false;
4862  }
4863 
4864  /*
4865  * Time to sleep on the other transaction/multixact, if necessary.
4866  *
4867  * If the other transaction is an update that's already committed,
4868  * then sleeping cannot possibly do any good: if we're required to
4869  * sleep, get out to raise an error instead.
4870  *
4871  * By here, we either have already acquired the buffer exclusive lock,
4872  * or we must wait for the locking transaction or multixact; so below
4873  * we ensure that we grab buffer lock after the sleep.
4874  */
4875  if (require_sleep && result == HeapTupleUpdated)
4876  {
4878  goto failed;
4879  }
4880  else if (require_sleep)
4881  {
4882  /*
4883  * Acquire tuple lock to establish our priority for the tuple, or
4884  * die trying. LockTuple will release us when we are next-in-line
4885  * for the tuple. We must do this even if we are share-locking.
4886  *
4887  * If we are forced to "start over" below, we keep the tuple lock;
4888  * this arranges that we stay at the head of the line while
4889  * rechecking tuple state.
4890  */
4891  if (!heap_acquire_tuplock(relation, tid, mode, wait_policy,
4892  &have_tuple_lock))
4893  {
4894  /*
4895  * This can only happen if wait_policy is Skip and the lock
4896  * couldn't be obtained.
4897  */
4898  result = HeapTupleWouldBlock;
4899  /* recovery code expects to have buffer lock held */
4901  goto failed;
4902  }
4903 
4904  if (infomask & HEAP_XMAX_IS_MULTI)
4905  {
4907 
4908  /* We only ever lock tuples, never update them */
4909  if (status >= MultiXactStatusNoKeyUpdate)
4910  elog(ERROR, "invalid lock mode in heap_lock_tuple");
4911 
4912  /* wait for multixact to end, or die trying */
4913  switch (wait_policy)
4914  {
4915  case LockWaitBlock:
4916  MultiXactIdWait((MultiXactId) xwait, status, infomask,
4917  relation, &tuple->t_self, XLTW_Lock, NULL);
4918  break;
4919  case LockWaitSkip:
4921  status, infomask, relation,
4922  NULL))
4923  {
4924  result = HeapTupleWouldBlock;
4925  /* recovery code expects to have buffer lock held */
4927  goto failed;
4928  }
4929  break;
4930  case LockWaitError:
4932  status, infomask, relation,
4933  NULL))
4934  ereport(ERROR,
4935  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4936  errmsg("could not obtain lock on row in relation \"%s\"",
4937  RelationGetRelationName(relation))));
4938 
4939  break;
4940  }
4941 
4942  /*
4943  * Of course, the multixact might not be done here: if we're
4944  * requesting a light lock mode, other transactions with light
4945  * locks could still be alive, as well as locks owned by our
4946  * own xact or other subxacts of this backend. We need to
4947  * preserve the surviving MultiXact members. Note that it
4948  * isn't absolutely necessary in the latter case, but doing so
4949  * is simpler.
4950  */
4951  }
4952  else
4953  {
4954  /* wait for regular transaction to end, or die trying */
4955  switch (wait_policy)
4956  {
4957  case LockWaitBlock:
4958  XactLockTableWait(xwait, relation, &tuple->t_self,
4959  XLTW_Lock);
4960  break;
4961  case LockWaitSkip:
4962  if (!ConditionalXactLockTableWait(xwait))
4963  {
4964  result = HeapTupleWouldBlock;
4965  /* recovery code expects to have buffer lock held */
4967  goto failed;
4968  }
4969  break;
4970  case LockWaitError:
4971  if (!ConditionalXactLockTableWait(xwait))
4972  ereport(ERROR,
4973  (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
4974  errmsg("could not obtain lock on row in relation \"%s\"",
4975  RelationGetRelationName(relation))));
4976  break;
4977  }
4978  }
4979 
4980  /* if there are updates, follow the update chain */
4981  if (follow_updates && !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
4982  {
4983  HTSU_Result res;
4984 
4985  res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
4987  mode);
4988  if (res != HeapTupleMayBeUpdated)
4989  {
4990  result = res;
4991  /* recovery code expects to have buffer lock held */
4993  goto failed;
4994  }
4995  }
4996 
4998 
4999  /*
5000  * xwait is done, but if xwait had just locked the tuple then some
5001  * other xact could update this tuple before we get to this point.
5002  * Check for xmax change, and start over if so.
5003  */
5004  if (xmax_infomask_changed(tuple->t_data->t_infomask, infomask) ||
5006  xwait))
5007  goto l3;
5008 
5009  if (!(infomask & HEAP_XMAX_IS_MULTI))
5010  {
5011  /*
5012  * Otherwise check if it committed or aborted. Note we cannot
5013  * be here if the tuple was only locked by somebody who didn't
5014  * conflict with us; that would have been handled above. So
5015  * that transaction must necessarily be gone by now. But
5016  * don't check for this in the multixact case, because some
5017  * locker transactions might still be running.
5018  */
5019  UpdateXmaxHintBits(tuple->t_data, *buffer, xwait);
5020  }
5021  }
5022 
5023  /* By here, we're certain that we hold buffer exclusive lock again */
5024 
5025  /*
5026  * We may lock if previous xmax aborted, or if it committed but only
5027  * locked the tuple without updating it; or if we didn't have to wait
5028  * at all for whatever reason.
5029  */
5030  if (!require_sleep ||
5031  (tuple->t_data->t_infomask & HEAP_XMAX_INVALID) ||
5034  result = HeapTupleMayBeUpdated;
5035  else
5036  result = HeapTupleUpdated;
5037  }
5038 
5039 failed:
5040  if (result != HeapTupleMayBeUpdated)
5041  {
5042  Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated ||
5043  result == HeapTupleWouldBlock);
5044  Assert(!(tuple->t_data->t_infomask & HEAP_XMAX_INVALID));
5045  hufd->ctid = tuple->t_data->t_ctid;
5046  hufd->xmax = HeapTupleHeaderGetUpdateXid(tuple->t_data);
5047  if (result == HeapTupleSelfUpdated)
5048  hufd->cmax = HeapTupleHeaderGetCmax(tuple->t_data);
5049  else
5050  hufd->cmax = InvalidCommandId;
5051  goto out_locked;
5052  }
5053 
5054  /*
5055  * If we didn't pin the visibility map page and the page has become all
5056  * visible while we were busy locking the buffer, or during some
5057  * subsequent window during which we had it unlocked, we'll have to unlock
5058  * and re-lock, to avoid holding the buffer lock across I/O. That's a bit
5059  * unfortunate, especially since we'll now have to recheck whether the
5060  * tuple has been locked or updated under us, but hopefully it won't
5061  * happen very often.
5062  */
5063  if (vmbuffer == InvalidBuffer && PageIsAllVisible(page))
5064  {
5066  visibilitymap_pin(relation, block, &vmbuffer);
5068  goto l3;
5069  }
5070 
5071  xmax = HeapTupleHeaderGetRawXmax(tuple->t_data);
5072  old_infomask = tuple->t_data->t_infomask;
5073 
5074  /*
5075  * If this is the first possibly-multixact-able operation in the current
5076  * transaction, set my per-backend OldestMemberMXactId setting. We can be
5077  * certain that the transaction will never become a member of any older
5078  * MultiXactIds than that. (We have to do this even if we end up just
5079  * using our own TransactionId below, since some other backend could
5080  * incorporate our XID into a MultiXact immediately afterwards.)
5081  */
5083 
5084  /*
5085  * Compute the new xmax and infomask to store into the tuple. Note we do
5086  * not modify the tuple just yet, because that would leave it in the wrong
5087  * state if multixact.c elogs.
5088  */
5089  compute_new_xmax_infomask(xmax, old_infomask, tuple->t_data->t_infomask2,
5090  GetCurrentTransactionId(), mode, false,
5091  &xid, &new_infomask, &new_infomask2);
5092 
5094 
5095  /*
5096  * Store transaction information of xact locking the tuple.
5097  *
5098  * Note: Cmax is meaningless in this context, so don't set it; this avoids
5099  * possibly generating a useless combo CID. Moreover, if we're locking a
5100  * previously updated tuple, it's important to preserve the Cmax.
5101  *
5102  * Also reset the HOT UPDATE bit, but only if there's no update; otherwise
5103  * we would break the HOT chain.
5104  */
5105  tuple->t_data->t_infomask &= ~HEAP_XMAX_BITS;
5106  tuple->t_data->t_infomask2 &= ~HEAP_KEYS_UPDATED;
5107  tuple->t_data->t_infomask |= new_infomask;
5108  tuple->t_data->t_infomask2 |= new_infomask2;
5109  if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask))
5111  HeapTupleHeaderSetXmax(tuple->t_data, xid);
5112 
5113  /*
5114  * Make sure there is no forward chain link in t_ctid. Note that in the
5115  * cases where the tuple has been updated, we must not overwrite t_ctid,
5116  * because it was set by the updater. Moreover, if the tuple has been
5117  * updated, we need to follow the update chain to lock the new versions of
5118  * the tuple as well.
5119  */
5120  if (HEAP_XMAX_IS_LOCKED_ONLY(new_infomask))
5121  tuple->t_data->t_ctid = *tid;
5122 
5123  /* Clear only the all-frozen bit on visibility map if needed */
5124  if (PageIsAllVisible(page) &&
5125  visibilitymap_clear(relation, block, vmbuffer,
5127  cleared_all_frozen = true;
5128 
5129 
5131 
5132  /*
5133  * XLOG stuff. You might think that we don't need an XLOG record because
5134  * there is no state change worth restoring after a crash. You would be
5135  * wrong however: we have just written either a TransactionId or a
5136  * MultiXactId that may never have been seen on disk before, and we need
5137  * to make sure that there are XLOG entries covering those ID numbers.
5138  * Else the same IDs might be re-used after a crash, which would be
5139  * disastrous if this page made it to disk before the crash. Essentially
5140  * we have to enforce the WAL log-before-data rule even in this case.
5141  * (Also, in a PITR log-shipping or 2PC environment, we have to have XLOG
5142  * entries for everything anyway.)
5143  */
5144  if (RelationNeedsWAL(relation))
5145  {
5146  xl_heap_lock xlrec;
5147  XLogRecPtr recptr;
5148 
5149  XLogBeginInsert();
5151 
5152  xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self);
5153  xlrec.locking_xid = xid;
5154  xlrec.infobits_set = compute_infobits(new_infomask,
5155  tuple->t_data->t_infomask2);
5156  xlrec.flags = cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0;
5157  XLogRegisterData((char *) &xlrec, SizeOfHeapLock);
5158 
5159  /* we don't decode row locks atm, so no need to log the origin */
5160 
5161  recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_LOCK);
5162 
5163  PageSetLSN(page, recptr);
5164  }
5165 
5166  END_CRIT_SECTION();
5167 
5168  result = HeapTupleMayBeUpdated;
5169 
5170 out_locked:
5172 
5173 out_unlocked:
5174  if (BufferIsValid(vmbuffer))
5175  ReleaseBuffer(vmbuffer);
5176 
5177  /*
5178  * Don't update the visibility map here. Locking a tuple doesn't change
5179  * visibility info.
5180  */
5181 
5182  /*
5183  * Now that we have successfully marked the tuple as locked, we can
5184  * release the lmgr tuple lock, if we had it.
5185  */
5186  if (have_tuple_lock)
5187  UnlockTupleTuplock(relation, tid, mode);
5188 
5189  return result;
5190 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1585
MultiXactStatus
Definition: multixact.h:40
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define HEAP_XMAX_BITS
Definition: htup_details.h:256
OffsetNumber offnum
Definition: heapam_xlog.h:253
static uint8 compute_infobits(uint16 infomask, uint16 infomask2)
Definition: heapam.c:2952
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define PageIsAllVisible(page)
Definition: bufpage.h:382
#define XLH_LOCK_ALL_FROZEN_CLEARED
Definition: heapam_xlog.h:247
TransactionId locking_xid
Definition: heapam_xlog.h:252
uint32 TransactionId
Definition: c.h:397
HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid, Buffer buffer)
Definition: tqual.c:460
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:773
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:2974
#define HeapTupleHeaderClearHotUpdated(tup)
Definition: htup_details.h:497
#define END_CRIT_SECTION()
Definition: miscadmin.h:132
#define InvalidBuffer
Definition: buf.h:25
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1618
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:181
bool ConditionalXactLockTableWait(TransactionId xid)
Definition: lmgr.c:607
#define HEAP_XMAX_IS_SHR_LOCKED(infomask)
Definition: htup_details.h:248
void MultiXactIdSetOldestMember(void)
Definition: multixact.c:623
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
unsigned short uint16
Definition: c.h:267
void pfree(void *pointer)
Definition: mcxt.c:950
#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:193
int8 infobits_set
Definition: heapam_xlog.h:254
ItemPointerData t_ctid
Definition: htup_details.h:150
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:7109
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:417
uint32 t_len
Definition: htup.h:64
#define REGBUF_STANDARD
Definition: xloginsert.h:35
CommandId cmax
Definition: heapam.h:72
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:374
HTSU_Result
Definition: snapshot.h:119
#define RelationGetRelationName(relation)
Definition: rel.h:437
Oid t_tableOid
Definition: htup.h:66
#define SizeOfHeapLock
Definition: heapam_xlog.h:258
#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:5254
TransactionId xmax
Definition: heapam.h:71
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
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:414
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define HEAP_KEYS_UPDATED
Definition: htup_details.h:264
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
static void UpdateXmaxHintBits(HeapTupleHeader tuple, Buffer buffer, TransactionId xid)
Definition: heapam.c:2297
static bool heap_acquire_tuplock(Relation relation, ItemPointer tid, LockTupleMode mode, LockWaitPolicy wait_policy, bool *have_tuple_lock)
Definition: heapam.c:5205
TransactionId MultiXactId
Definition: c.h:407
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
Definition: lmgr.c:554
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
Definition: lmgr.h:29
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:119
static bool DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, LockTupleMode lockmode)
Definition: heapam.c:6942
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
#define RelationNeedsWAL(relation)
Definition: rel.h:506
#define TUPLOCK_from_mxstatus(status)
Definition: heapam.c:201
static HTSU_Result heap_lock_updated_tuple(Relation rel, HeapTuple tuple, ItemPointer ctid, TransactionId xid, LockTupleMode mode)
Definition: heapam.c:5922
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:4486
ItemPointerData ctid
Definition: heapam.h:70
#define HEAP_XMAX_IS_EXCL_LOCKED(infomask)
Definition: htup_details.h:250
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:75
#define HEAP_XMAX_IS_KEYSHR_LOCKED(infomask)
Definition: htup_details.h:252
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
#define RelationGetRelid(relation)
Definition: rel.h:417
static bool ConditionalMultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, Relation rel, int *remaining)
Definition: heapam.c:7131
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
#define ItemPointerCopy(fromPointer, toPointer)
Definition: itemptr.h:138
void heap_multi_insert ( Relation  relation,
HeapTuple tuples,
int  ntuples,
CommandId  cid,
int  options,
BulkInsertState  bistate 
)

Definition at line 2658 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, init(), InvalidBuffer, IsCatalogRelation(), ItemPointerGetOffsetNumber, log_heap_new_cid(), MarkBufferDirty(), MAXALIGN, xl_heap_multi_insert::ntuples, NULL, 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().

2660 {
2662  HeapTuple *heaptuples;
2663  int i;
2664  int ndone;
2665  char *scratch = NULL;
2666  Page page;
2667  bool needwal;
2668  Size saveFreeSpace;
2669  bool need_tuple_data = RelationIsLogicallyLogged(relation);
2670  bool need_cids = RelationIsAccessibleInLogicalDecoding(relation);
2671 
2672  needwal = !(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation);
2673  saveFreeSpace = RelationGetTargetPageFreeSpace(relation,
2675 
2676  /* Toast and set header data in all the tuples */
2677  heaptuples = palloc(ntuples * sizeof(HeapTuple));
2678  for (i = 0; i < ntuples; i++)
2679  heaptuples[i] = heap_prepare_insert(relation, tuples[i],
2680  xid, cid, options);
2681 
2682  /*
2683  * Allocate some memory to use for constructing the WAL record. Using
2684  * palloc() within a critical section is not safe, so we allocate this
2685  * beforehand.
2686  */
2687  if (needwal)
2688  scratch = palloc(BLCKSZ);
2689 
2690  /*
2691  * We're about to do the actual inserts -- but check for conflict first,
2692  * to minimize the possibility of having to roll back work we've just
2693  * done.
2694  *
2695  * A check here does not definitively prevent a serialization anomaly;
2696  * that check MUST be done at least past the point of acquiring an
2697  * exclusive buffer content lock on every buffer that will be affected,
2698  * and MAY be done after all inserts are reflected in the buffers and
2699  * those locks are released; otherwise there race condition. Since
2700  * multiple buffers can be locked and unlocked in the loop below, and it
2701  * would not be feasible to identify and lock all of those buffers before
2702  * the loop, we must do a final check at the end.
2703  *
2704  * The check here could be omitted with no loss of correctness; it is
2705  * present strictly as an optimization.
2706  *
2707  * For heap inserts, we only need to check for table-level SSI locks. Our
2708  * new tuples can't possibly conflict with existing tuple locks, and heap
2709  * page locks are only consolidated versions of tuple locks; they do not
2710  * lock "gaps" as index page locks do. So we don't need to specify a
2711  * buffer when making the call, which makes for a faster check.
2712  */
2714 
2715  ndone = 0;
2716  while (ndone < ntuples)
2717  {
2718  Buffer buffer;
2719  Buffer vmbuffer = InvalidBuffer;
2720  bool all_visible_cleared = false;
2721  int nthispage;
2722 
2724 
2725  /*
2726  * Find buffer where at least the next tuple will fit. If the page is
2727  * all-visible, this will also pin the requisite visibility map page.
2728  */
2729  buffer = RelationGetBufferForTuple(relation, heaptuples[ndone]->t_len,
2730  InvalidBuffer, options, bistate,
2731  &vmbuffer, NULL);
2732  page = BufferGetPage(buffer);
2733 
2734  /* NO EREPORT(ERROR) from here till changes are logged */
2736 
2737  /*
2738  * RelationGetBufferForTuple has ensured that the first tuple fits.
2739  * Put that on the page, and then as many other tuples as fit.
2740  */
2741  RelationPutHeapTuple(relation, buffer, heaptuples[ndone], false);
2742  for (nthispage = 1; ndone + nthispage < ntuples; nthispage++)
2743  {
2744  HeapTuple heaptup = heaptuples[ndone + nthispage];
2745 
2746  if (PageGetHeapFreeSpace(page) < MAXALIGN(heaptup->t_len) + saveFreeSpace)
2747  break;
2748 
2749  RelationPutHeapTuple(relation, buffer, heaptup, false);
2750 
2751  /*
2752  * We don't use heap_multi_insert for catalog tuples yet, but
2753  * better be prepared...
2754  */
2755  if (needwal && need_cids)
2756  log_heap_new_cid(relation, heaptup);
2757  }
2758 
2759  if (PageIsAllVisible(page))
2760  {
2761  all_visible_cleared = true;
2762  PageClearAllVisible(page);
2763  visibilitymap_clear(relation,
2764  BufferGetBlockNumber(buffer),
2765  vmbuffer, VISIBILITYMAP_VALID_BITS);
2766  }
2767 
2768  /*
2769  * XXX Should we set PageSetPrunable on this page ? See heap_insert()
2770  */
2771 
2772  MarkBufferDirty(buffer);
2773 
2774  /* XLOG stuff */
2775  if (needwal)
2776  {
2777  XLogRecPtr recptr;
2778  xl_heap_multi_insert *xlrec;
2780  char *tupledata;
2781  int totaldatalen;
2782  char *scratchptr = scratch;
2783  bool init;
2784  int bufflags = 0;
2785 
2786  /*
2787  * If the page was previously empty, we can reinit the page
2788  * instead of restoring the whole thing.
2789  */
2790  init = (ItemPointerGetOffsetNumber(&(heaptuples[ndone]->t_self)) == FirstOffsetNumber &&
2791  PageGetMaxOffsetNumber(page) == FirstOffsetNumber + nthispage - 1);
2792 
2793  /* allocate xl_heap_multi_insert struct from the scratch area */
2794  xlrec = (xl_heap_multi_insert *) scratchptr;
2795  scratchptr += SizeOfHeapMultiInsert;
2796 
2797  /*
2798  * Allocate offsets array. Unless we're reinitializing the page,
2799  * in that case the tuples are stored in order starting at
2800  * FirstOffsetNumber and we don't need to store the offsets
2801  * explicitly.
2802  */
2803  if (!init)
2804  scratchptr += nthispage * sizeof(OffsetNumber);
2805 
2806  /* the rest of the scratch space is used for tuple data */
2807  tupledata = scratchptr;
2808 
2809  xlrec->flags = all_visible_cleared ? XLH_INSERT_ALL_VISIBLE_CLEARED : 0;
2810  xlrec->ntuples = nthispage;
2811 
2812  /*
2813  * Write out an xl_multi_insert_tuple and the tuple data itself
2814  * for each tuple.
2815  */
2816  for (i = 0; i < nthispage; i++)
2817  {
2818  HeapTuple heaptup = heaptuples[ndone + i];
2819  xl_multi_insert_tuple *tuphdr;
2820  int datalen;
2821 
2822  if (!init)
2823  xlrec->offsets[i] = ItemPointerGetOffsetNumber(&heaptup->t_self);
2824  /* xl_multi_insert_tuple needs two-byte alignment. */
2825  tuphdr = (xl_multi_insert_tuple *) SHORTALIGN(scratchptr);
2826  scratchptr = ((char *) tuphdr) + SizeOfMultiInsertTuple;
2827 
2828  tuphdr->t_infomask2 = heaptup->t_data->t_infomask2;
2829  tuphdr->t_infomask = heaptup->t_data->t_infomask;
2830  tuphdr->t_hoff = heaptup->t_data->t_hoff;
2831 
2832  /* write bitmap [+ padding] [+ oid] + data */
2833  datalen = heaptup->t_len - SizeofHeapTupleHeader;
2834  memcpy(scratchptr,
2835  (char *) heaptup->t_data + SizeofHeapTupleHeader,
2836  datalen);
2837  tuphdr->datalen = datalen;
2838  scratchptr += datalen;
2839  }
2840  totaldatalen = scratchptr - tupledata;
2841  Assert((scratchptr - scratch) < BLCKSZ);
2842 
2843  if (need_tuple_data)
2845 
2846  /*
2847  * Signal that this is the last xl_heap_multi_insert record
2848  * emitted by this call to heap_multi_insert(). Needed for logical
2849  * decoding so it knows when to cleanup temporary data.
2850  */
2851  if (ndone + nthispage == ntuples)
2852  xlrec->flags |= XLH_INSERT_LAST_IN_MULTI;
2853 
2854  if (init)
2855  {
2856  info |= XLOG_HEAP_INIT_PAGE;
2857  bufflags |= REGBUF_WILL_INIT;
2858  }
2859 
2860  /*
2861  * If we're doing logical decoding, include the new tuple data
2862  * even if we take a full-page image of the page.
2863  */
2864  if (need_tuple_data)
2865  bufflags |= REGBUF_KEEP_DATA;
2866 
2867  XLogBeginInsert();
2868  XLogRegisterData((char *) xlrec, tupledata - scratch);
2869  XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags);
2870 
2871  XLogRegisterBufData(0, tupledata, totaldatalen);
2872 
2873  /* filtering by origin on a row level is much more efficient */
2875 
2876  recptr = XLogInsert(RM_HEAP2_ID, info);
2877 
2878  PageSetLSN(page, recptr);
2879  }
2880 
2881  END_CRIT_SECTION();
2882 
2883  UnlockReleaseBuffer(buffer);
2884  if (vmbuffer != InvalidBuffer)
2885  ReleaseBuffer(vmbuffer);
2886 
2887  ndone += nthispage;
2888  }
2889 
2890  /*
2891  * We're done with the actual inserts. Check for conflicts again, to
2892  * ensure that all rw-conflicts in to these inserts are detected. Without
2893  * this final check, a sequential scan of the heap may have locked the
2894  * table after the "before" check, missing one opportunity to detect the
2895  * conflict, and then scanned the table before the new tuples were there,
2896  * missing the other chance to detect the conflict.
2897  *
2898  * For heap inserts, we only need to check for table-level SSI locks. Our
2899  * new tuples can't possibly conflict with existing tuple locks, and heap
2900  * page locks are only consolidated versions of tuple locks; they do not
2901  * lock "gaps" as index page locks do. So we don't need to specify a
2902  * buffer when making the call.
2903  */
2905 
2906  /*
2907  * If tuples are cachable, mark them for invalidation from the caches in
2908  * case we abort. Note it is OK to do this after releasing the buffer,
2909  * because the heaptuples data structure is all in local memory, not in
2910  * the shared buffer.
2911  */
2912  if (IsCatalogRelation(relation))
2913  {
2914  for (i = 0; i < ntuples; i++)
2915  CacheInvalidateHeapTuple(relation, heaptuples[i], NULL);
2916  }
2917 
2918  /*
2919  * Copy t_self fields back to the caller's original tuples. This does
2920  * nothing for untoasted tuples (tuples[i] == heaptuples[i)], but it's
2921  * probably faster to always copy than check.
2922  */
2923  for (i = 0; i < ntuples; i++)
2924  tuples[i]->t_self = heaptuples[i]->t_self;
2925 
2926  pgstat_count_heap_insert(relation, ntuples);
2927 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
#define SizeofHeapTupleHeader
Definition: htup_details.h:170
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:91
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup)
Definition: heapam.c:7693
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition: inval.c:1087
static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid, CommandId cid, int options)
Definition: heapam.c:2580
#define PageIsAllVisible(page)
Definition: bufpage.h:382
uint32 TransactionId
Definition: c.h:397
OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]
Definition: heapam_xlog.h:155
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:132
unsigned char uint8
Definition: c.h:266
#define InvalidBuffer
Definition: buf.h:25
#define SizeOfHeapMultiInsert
Definition: heapam_xlog.h:158
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:130
#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:576
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
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:4307
#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:67
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:666
#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:35
Buffer RelationGetBufferForTuple(Relation relation, Size len, Buffer otherBuffer, int options, BulkInsertState bistate, Buffer *vmbuffer, Buffer *vmbuffer_other)
Definition: hio.c:297
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:397
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define RelationGetTargetPageFreeSpace(relation, defaultff)
Definition: rel.h:308
#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:560
#define REGBUF_KEEP_DATA
Definition: xloginsert.h:38
#define PageClearAllVisible(page)
Definition: bufpage.h:386
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
size_t Size
Definition: c.h:356
#define MAXALIGN(LEN)
Definition: c.h:588
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:94
static void init(bool is_no_vacuum)
Definition: pgbench.c:2571
#define RelationNeedsWAL(relation)
Definition: rel.h:506
#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:1871
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define HEAP_DEFAULT_FILLFACTOR
Definition: rel.h:287
#define SHORTALIGN(LEN)
Definition: c.h:584
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
#define SizeOfMultiInsertTuple
Definition: heapam_xlog.h:169
Relation heap_open ( Oid  relationId,
LOCKMODE  lockmode 
)

Definition at line 1284 of file heapam.c.

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

Referenced by acquire_inherited_sample_rows(), AcquireRewriteLocks(), AddEnumLabel(), AddNewAttributeTuples(), AddRoleMems(), 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_selective_binary_conversion(), CheckAndCreateToastTable(), CheckConstraintFetch(), checkSharedDependencies(), ChooseConstraintName(), cluster(), CollationCreate(), ConstraintNameIsUsed(), 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(), 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(), ExecInitModifyTable(), ExecOpenScanRelation(), ExecRefreshMatView(), ExecRenameStmt(), ExecSetupPartitionTupleRouting(), ExecuteTruncate(), expand_inherited_rtentry(), expand_targetlist(), 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_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_parent(), get_pkey_attnames(), get_primary_key_attnos(), get_rel_oids(), get_relation_constraint_oid(), get_relation_constraints(), get_relation_data_width(), 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(), 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(), logicalrep_rel_open(), LogicalRepSyncTableStart(), lookup_ts_config_cache(), LookupOpclassInfo(), make_new_heap(), 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(), postgresPlanDirectModify(), postgresPlanForeignModify(), ProcedureCreate(), process_settings(), publication_add_relation(), RangeCreate(), RangeDelete(), recordExtensionInitPrivWorker(), recordExtObjInitPriv(), recordMultipleDependencies(), recordSharedDependencyOn(), refresh_by_match_merge(), reindex_index(), reindex_relation(), ReindexMultipleTables(), relation_has_policies(), relation_mark_replica_identity(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationGetExclusionInfo(), RelationGetFKeyList(), RelationGetIndexList(), RelationGetPartitionDispatchInfo(), 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(), RemoveStatisticsExt(), 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_FKey_setdefault_del(), RI_FKey_setdefault_upd(), RI_FKey_setnull_del(), RI_FKey_setnull_upd(), ri_restrict_del(), ri_restrict_upd(), ScanPgRelation(), schema_to_xmlschema_internal(), SearchCatCache(), SearchCatCacheList(), 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(), SetSubscriptionRelState(), shdepDropOwned(), shdepReassignOwned(), StoreAttrDefault(), StoreCatalogInheritance(), storeOperators(), StorePartitionBound(), StorePartitionKey(), storeProcedures(), 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(), updateAclDependencies(), UpdateIndexRelation(), vac_truncate_clog(), vac_update_datfrozenxid(), vac_update_relstats(), and validate_index().

1285 {
1286  Relation r;
1287 
1288  r = relation_open(relationId, lockmode);
1289 
1290  if (r->rd_rel->relkind == RELKIND_INDEX)
1291  ereport(ERROR,
1292  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1293  errmsg("\"%s\" is an index",
1295  else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
1296  ereport(ERROR,
1297  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1298  errmsg("\"%s\" is a composite type",
1300 
1301  return r;
1302 }
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
Relation heap_openrv ( const RangeVar relation,
LOCKMODE  lockmode 
)

Definition at line 1312 of file heapam.c.

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

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

1313 {
1314  Relation r;
1315 
1316  r = relation_openrv(relation, lockmode);
1317 
1318  if (r->rd_rel->relkind == RELKIND_INDEX)
1319  ereport(ERROR,
1320  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1321  errmsg("\"%s\" is an index",
1323  else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
1324  ereport(ERROR,
1325  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1326  errmsg("\"%s\" is a composite type",
1328 
1329  return r;
1330 }
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1192
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation heap_openrv_extended ( const RangeVar relation,
LOCKMODE  lockmode,
bool  missing_ok 
)

Definition at line 1341 of file heapam.c.

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

Referenced by get_object_address_relobject(), and parserOpenTable().

1343 {
1344  Relation r;
1345 
1346  r = relation_openrv_extended(relation, lockmode, missing_ok);
1347 
1348  if (r)
1349  {
1350  if (r->rd_rel->relkind == RELKIND_INDEX)
1351  ereport(ERROR,
1352  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1353  errmsg("\"%s\" is an index",
1355  else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
1356  ereport(ERROR,
1357  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1358  errmsg("\"%s\" is a composite type",
1360  }
1361 
1362  return r;
1363 }
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok)
Definition: heapam.c:1227
int heap_page_prune ( Relation  relation,
Buffer  buffer,
TransactionId  OldestXmin,
bool  report_stats,
TransactionId latestRemovedXid 
)

Definition at line 182 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().

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