25#include "catalog/pg_am_d.h"
67 Anum_pg_index_indclass);
78 int table_attno = indkey->
values[index_attoff];
102 elog(
ERROR,
"missing operator %d(%u,%u) in opfamily %u",
103 eq_strategy, optype, optype, opfamily);
138 bool refetch =
false;
149 errmsg(
"tuple to be locked was already moved to another partition due to concurrent update, retrying")));
153 errmsg(
"concurrent update, retrying")));
160 errmsg(
"concurrent delete, retrying")));
164 elog(
ERROR,
"attempted to lock invisible tuple");
167 elog(
ERROR,
"unexpected table_tuple_lock status: %u", res);
194 bool isIdxSafeToSkipDuplicates;
221 if (!isIdxSafeToSkipDuplicates)
310 if (att->attisdropped || att->attgenerated)
334 typentry = eq[attrnum];
335 if (typentry == NULL)
341 (
errcode(ERRCODE_UNDEFINED_FUNCTION),
342 errmsg(
"could not identify an equality operator for type %s",
344 eq[attrnum] = typentry;
487 bool recently_dead =
false;
507 recently_dead =
true;
523 *delete_time = localts;
524 *delete_origin = localorigin;
612 if (!
tuples_equal(scanslot, searchslot, eq, indexbitmap))
616 delete_time, delete_origin);
622 return *delete_time != 0;
643 bool isIdxSafeToSkipDuplicates;
679 if (!isIdxSafeToSkipDuplicates)
689 delete_time, delete_origin);
698 return *delete_time != 0;
720 *conflictslot = NULL;
736 *conflictslot = NULL;
781 conflicttuple->
slot = conflictslot;
782 conflicttuple->
indexoid = uniqueidx;
785 &conflicttuple->
origin, &conflicttuple->
ts);
787 conflicttuples =
lappend(conflicttuples, conflicttuple);
795 searchslot, remoteslot, conflicttuples);
808 bool skip_tuple =
false;
827 List *conflictindexes;
828 bool conflict =
false;
839 if (rel->
rd_rel->relispartition)
850 conflictindexes ?
true :
false,
852 conflictindexes,
false);
871 recheckIndexes, NULL, slot);
875 recheckIndexes, NULL);
898 bool skip_tuple =
false;
916 tid, NULL, slot, NULL, NULL,
false))
924 List *conflictindexes;
925 bool conflict =
false;
936 if (rel->
rd_rel->relispartition)
947 conflictindexes ?
true :
false,
948 &conflict, conflictindexes,
958 recheckIndexes, searchslot, slot);
964 recheckIndexes, NULL,
false);
981 bool skip_tuple =
false;
992 tid, NULL, NULL, NULL, NULL,
false);
1002 tid, NULL, NULL,
false);
1018 if (rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1051 (
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1052 errmsg(
"cannot update table \"%s\"",
1054 errdetail(
"Column used in the publication WHERE expression is not part of the replica identity.")));
1057 (
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1058 errmsg(
"cannot update table \"%s\"",
1060 errdetail(
"Column list used by the publication does not cover the replica identity.")));
1063 (
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1064 errmsg(
"cannot update table \"%s\"",
1066 errdetail(
"Replica identity must not contain unpublished generated columns.")));
1069 (
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1070 errmsg(
"cannot delete from table \"%s\"",
1072 errdetail(
"Column used in the publication WHERE expression is not part of the replica identity.")));
1075 (
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1076 errmsg(
"cannot delete from table \"%s\"",
1078 errdetail(
"Column list used by the publication does not cover the replica identity.")));
1081 (
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1082 errmsg(
"cannot delete from table \"%s\"",
1084 errdetail(
"Replica identity must not contain unpublished generated columns.")));
1091 if (rel->
rd_rel->relreplident == REPLICA_IDENTITY_FULL)
1101 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1102 errmsg(
"cannot update table \"%s\" because it does not have a replica identity and publishes updates",
1104 errhint(
"To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.")));
1107 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1108 errmsg(
"cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
1110 errhint(
"To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
1123 if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
1125 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1126 errmsg(
"cannot use relation \"%s.%s\" as logical replication target",
StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
#define AttributeNumberIsValid(attributeNumber)
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
bool bms_is_member(int x, const Bitmapset *a)
void LockBuffer(Buffer buffer, int mode)
#define BUFFER_LOCK_UNLOCK
#define BUFFER_LOCK_SHARE
#define PG_USED_FOR_ASSERTS_ONLY
#define OidIsValid(objectId)
bool IsCatalogRelation(Relation relation)
bool TransactionIdGetCommitTsData(TransactionId xid, TimestampTz *ts, RepOriginId *nodeid)
void ReportApplyConflict(EState *estate, ResultRelInfo *relinfo, int elevel, ConflictType type, TupleTableSlot *searchslot, TupleTableSlot *remoteslot, List *conflicttuples)
bool GetTupleTransactionInfo(TupleTableSlot *localslot, TransactionId *xmin, RepOriginId *localorigin, TimestampTz *localts)
@ CT_MULTIPLE_UNIQUE_CONFLICTS
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, ItemPointer tupleid, List *arbiterIndexes)
List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
static void BuildConflictIndexInfo(ResultRelInfo *resultRelInfo, Oid conflictindex)
static bool tuples_equal(TupleTableSlot *slot1, TupleTableSlot *slot2, TypeCacheEntry **eq, Bitmapset *columns)
bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot)
void ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo, EState *estate, EPQState *epqstate, TupleTableSlot *searchslot)
void CheckSubscriptionRelkind(char relkind, const char *nspname, const char *relname)
bool RelationFindDeletedTupleInfoSeq(Relation rel, TupleTableSlot *searchslot, TransactionId oldestxmin, TransactionId *delete_xid, RepOriginId *delete_origin, TimestampTz *delete_time)
static bool should_refetch_tuple(TM_Result res, TM_FailureData *tmfd)
void ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo, EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot)
void CheckCmdReplicaIdentity(Relation rel, CmdType cmd)
void ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot)
bool RelationFindDeletedTupleInfoByIndex(Relation rel, Oid idxoid, TupleTableSlot *searchslot, TransactionId oldestxmin, TransactionId *delete_xid, RepOriginId *delete_origin, TimestampTz *delete_time)
static bool FindConflictTuple(ResultRelInfo *resultRelInfo, EState *estate, Oid conflictindex, TupleTableSlot *slot, TupleTableSlot **conflictslot)
static int build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel, TupleTableSlot *searchslot)
static void CheckAndReportConflict(ResultRelInfo *resultRelInfo, EState *estate, ConflictType type, List *recheckIndexes, TupleTableSlot *searchslot, TupleTableSlot *remoteslot)
static void update_most_recent_deletion_info(TupleTableSlot *scanslot, TransactionId oldestxmin, TransactionId *delete_xid, TimestampTz *delete_time, RepOriginId *delete_origin)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
#define palloc0_object(type)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Assert(PointerIsAligned(start, uint64))
@ HEAPTUPLE_RECENTLY_DEAD
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
static TransactionId HeapTupleHeaderGetUpdateXid(const HeapTupleHeaderData *tup)
void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction, TupleTableSlot *slot)
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, IndexScanInstrumentation *instrument, int nkeys, int norderbys)
void index_close(Relation relation, LOCKMODE lockmode)
void index_endscan(IndexScanDesc scan)
Relation index_open(Oid relationId, LOCKMODE lockmode)
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
static bool ItemPointerIndicatesMovedPartitions(const ItemPointerData *pointer)
List * lappend(List *list, void *datum)
void list_free(List *list)
bool list_member_oid(const List *list, Oid datum)
void XactLockTableWait(TransactionId xid, Relation rel, const ItemPointerData *ctid, XLTW_Oper oper)
Oid get_opclass_input_type(Oid opclass)
Oid get_opclass_family(Oid opclass)
RegProcedure get_opcode(Oid opno)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
void * palloc0(Size size)
void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, CmdType cmdtype)
#define InvalidRepOriginId
FormData_pg_attribute * Form_pg_attribute
int errdetail_relkind_not_supported(char relkind)
static int list_length(const List *l)
#define list_make1_oid(x1)
#define foreach_oid(var, lst)
#define ERRCODE_T_R_SERIALIZATION_FAILURE
static bool DatumGetBool(Datum X)
static Pointer DatumGetPointer(Datum X)
#define RelationGetRelid(relation)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Bitmapset * RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Oid RelationGetReplicaIndex(Relation relation)
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Snapshot GetLatestSnapshot(void)
void PushActiveSnapshot(Snapshot snapshot)
void PopActiveSnapshot(void)
Snapshot GetActiveSnapshot(void)
#define InitDirtySnapshot(snapshotdata)
Oid GetRelationIdentityOrPK(Relation rel)
PublicationActions pubactions
bool cols_valid_for_delete
bool gencols_valid_for_update
bool cols_valid_for_update
bool gencols_valid_for_delete
struct HeapTupleData * rd_indextuple
List * ri_onConflictArbiterIndexes
RelationPtr ri_IndexRelationDescs
TriggerDesc * ri_TrigDesc
IndexInfo ** ri_IndexRelationInfo
bool trig_delete_before_row
bool trig_update_before_row
bool trig_insert_before_row
bool has_generated_stored
TupleDesc tts_tupleDescriptor
int16 values[FLEXIBLE_ARRAY_MEMBER]
Oid values[FLEXIBLE_ARRAY_MEMBER]
#define FirstLowInvalidHeapAttributeNumber
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
void simple_table_tuple_update(Relation rel, ItemPointer otid, TupleTableSlot *slot, Snapshot snapshot, TU_UpdateIndexes *update_indexes)
void simple_table_tuple_insert(Relation rel, TupleTableSlot *slot)
void simple_table_tuple_delete(Relation rel, ItemPointer tid, Snapshot snapshot)
static void table_endscan(TableScanDesc scan)
static TM_Result table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, uint8 flags, TM_FailureData *tmfd)
static void table_rescan(TableScanDesc scan, ScanKeyData *key)
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
#define InvalidTransactionId
#define TransactionIdIsValid(xid)
bool ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, TM_Result *tmresult, TM_FailureData *tmfd, bool is_merge_update)
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture, bool is_crosspart_update)
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, List *recheckIndexes, TransitionCaptureState *transition_capture, bool is_crosspart_update)
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot **epqslot, TM_Result *tmresult, TM_FailureData *tmfd, bool is_merge_delete)
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static void slot_getallattrs(TupleTableSlot *slot)
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
static void ExecMaterializeSlot(TupleTableSlot *slot)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define TYPECACHE_EQ_OPR_FINFO
CommandId GetCurrentCommandId(bool used)