48#include "utils/fmgroids.h"
64#define RI_MAX_NUMKEYS INDEX_MAX_KEYS
66#define RI_INIT_CONSTRAINTHASHSIZE 64
67#define RI_INIT_QUERYHASHSIZE (RI_INIT_CONSTRAINTHASHSIZE * 4)
69#define RI_KEYS_ALL_NULL 0
70#define RI_KEYS_SOME_NULL 1
71#define RI_KEYS_NONE_NULL 2
75#define RI_PLAN_CHECK_LOOKUPPK 1
76#define RI_PLAN_CHECK_LOOKUPPK_FROM_PK 2
77#define RI_PLAN_LAST_ON_PK RI_PLAN_CHECK_LOOKUPPK_FROM_PK
79#define RI_PLAN_CASCADE_ONDELETE 3
80#define RI_PLAN_CASCADE_ONUPDATE 4
81#define RI_PLAN_NO_ACTION 5
83#define RI_PLAN_RESTRICT 6
84#define RI_PLAN_SETNULL_ONDELETE 7
85#define RI_PLAN_SETNULL_ONUPDATE 8
86#define RI_PLAN_SETDEFAULT_ONDELETE 9
87#define RI_PLAN_SETDEFAULT_ONUPDATE 10
89#define MAX_QUOTED_NAME_LEN (NAMEDATALEN*2+3)
90#define MAX_QUOTED_REL_NAME_LEN (MAX_QUOTED_NAME_LEN*2)
92#define RIAttName(rel, attnum) NameStr(*attnumAttName(rel, attnum))
93#define RIAttType(rel, attnum) attnumTypeId(rel, attnum)
94#define RIAttCollation(rel, attnum) attnumCollationId(rel, attnum)
96#define RI_TRIGTYPE_INSERT 1
97#define RI_TRIGTYPE_UPDATE 2
98#define RI_TRIGTYPE_DELETE 3
213#define RI_FASTPATH_BATCH_SIZE 64
284 int32 constr_queryno);
340 Datum *vals,
char *nulls);
403 switch (
riinfo->confmatchtype)
413 errmsg(
"insert or update on table \"%s\" violates foreign key constraint \"%s\"",
416 errdetail(
"MATCH FULL does not allow mixing of null and nonnull key values."),
532 "SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
565 riinfo->agged_period_contained_by_oper,
702 "SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
734 riinfo->agged_period_contained_by_oper,
974 riinfo->period_intersect_oper,
1007 riinfo->agged_period_contained_by_oper,
1366 elog(
ERROR,
"invalid tgkind passed to ri_set");
1397 if (
riinfo->ndelsetcols != 0)
1409 elog(
ERROR,
"invalid tgkind passed to ri_set");
1577 switch (
riinfo->confmatchtype)
1723 ((pk_rel->
rd_rel->relrowsecurity &&
1726 (
fk_rel->rd_rel->relrowsecurity &&
1764 " FROM %s%s fk LEFT OUTER JOIN %s%s pk ON",
1802 "%sfk.%s IS NOT NULL",
1804 switch (
riinfo->confmatchtype)
1849 elog(
ERROR,
"SPI_prepare returned %s for %s",
1905 errmsg(
"insert or update on table \"%s\" violates foreign key constraint \"%s\"",
1908 errdetail(
"MATCH FULL does not allow mixing of null and nonnull key values."),
1999 " FROM %s%s fk JOIN %s pk ON",
2041 "%sfk.%s IS NOT NULL",
2043 switch (
riinfo->confmatchtype)
2088 elog(
ERROR,
"SPI_prepare returned %s for %s",
2136 slot, tupdesc, 0,
false,
true);
2169 *buffer++ = *
name++;
2184 buffer +=
strlen(buffer);
2238 elog(
ERROR,
"cache lookup failed for collation %u", collation);
2267 int32 constr_queryno)
2288 key->constr_id =
riinfo->constraint_root_id;
2290 key->constr_id =
riinfo->constraint_id;
2291 key->constr_queryno = constr_queryno;
2305 errmsg(
"function \"%s\" was not called by trigger manager",
funcname)));
2357 errmsg(
"no pg_constraint entry for trigger \"%s\" on table \"%s\"",
2359 errhint(
"Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT.")));
2369 elog(
ERROR,
"wrong pg_constraint entry for trigger \"%s\" on table \"%s\"",
2376 elog(
ERROR,
"wrong pg_constraint entry for trigger \"%s\" on table \"%s\"",
2383 elog(
ERROR,
"unrecognized confmatchtype: %d",
2389 errmsg(
"MATCH PARTIAL not yet implemented")));
2431 elog(
ERROR,
"constraint %u is not a foreign key constraint",
2437 riinfo->constraint_root_id =
2473 &
riinfo->period_contained_by_oper,
2474 &
riinfo->agged_period_contained_by_oper,
2475 &
riinfo->period_intersect_oper);
2480 riinfo->pk_is_partitioned =
2556 valid_link, iter.
cur);
2563 if (hashvalue == 0 ||
2564 riinfo->oidHashValue == hashvalue ||
2565 riinfo->rootHashValue == hashvalue)
2590 int save_sec_context;
2642 int save_sec_context;
2736 false,
false, limit);
2748 errmsg(
"referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result",
2752 errhint(
"This is most likely due to a rule having rewritten the query.")));
2898 if (
fpentry->batch_count == 0)
2951 fk_rel, snapshot, scandesc);
2954 fk_rel, snapshot, scandesc);
2999 for (
int i = 0;
i <
fpentry->batch_count;
i++)
3245 errmsg(
"could not serialize access due to concurrent update")));
3252 errmsg(
"could not serialize access due to concurrent update")));
3273 elog(
ERROR,
"attempted to lock invisible tuple");
3292 if (
riinfo->pk_is_partitioned)
3355 bool matched =
true;
3364 for (
int i = 0;
i < nkeys;
i++)
3373 skey->sk_argument)))
3479 Datum *vals,
char *nulls)
3481 const int16 *attnums;
3485 attnums =
riinfo->pk_attnums;
3487 attnums =
riinfo->fk_attnums;
3492 nulls[
i] = isnull ?
'n' :
' ';
3514 const int16 *attnums;
3526 attnums =
riinfo->fk_attnums;
3528 if (tupdesc ==
NULL)
3529 tupdesc =
fk_rel->rd_att;
3533 attnums =
riinfo->pk_attnums;
3535 if (tupdesc ==
NULL)
3536 tupdesc = pk_rel->
rd_att;
3619 errmsg(
"removing partition \"%s\" violates foreign key constraint \"%s\"",
3622 errdetail(
"Key (%s)=(%s) is still referenced from table \"%s\".",
3629 errmsg(
"insert or update on table \"%s\" violates foreign key constraint \"%s\"",
3633 errdetail(
"Key (%s)=(%s) is not present in table \"%s\".",
3636 errdetail(
"Key is not present in table \"%s\".",
3642 errmsg(
"update or delete on table \"%s\" violates RESTRICT setting of foreign key constraint \"%s\" on table \"%s\"",
3647 errdetail(
"Key (%s)=(%s) is referenced from table \"%s\".",
3650 errdetail(
"Key is referenced from table \"%s\".",
3656 errmsg(
"update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"",
3661 errdetail(
"Key (%s)=(%s) is still referenced from table \"%s\".",
3664 errdetail(
"Key is still referenced from table \"%s\".",
3682 const int16 *attnums;
3687 attnums =
riinfo->pk_attnums;
3689 attnums =
riinfo->fk_attnums;
3843 const int16 *attnums;
3846 attnums =
riinfo->pk_attnums;
3848 attnums =
riinfo->fk_attnums;
3896 eq_opr =
riinfo->period_contained_by_oper;
3898 eq_opr =
riinfo->ff_eq_oprs[
i];
3991 key.eq_opr = eq_opr;
3992 key.typeid =
typeid;
3997 entry->
valid =
false;
4035 if (
typeid == righttype)
4052 elog(
ERROR,
"no conversion function from %s to %s",
4062 entry->
valid =
true;
4227 ctl.keysize =
sizeof(
Oid);
4276 "RI fast path flush temporary context",
Datum idx(PG_FUNCTION_ARGS)
bool has_bypassrls_privilege(Oid roleid)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Bitmapset * bms_add_member(Bitmapset *a, int x)
static Datum values[MAXATTR]
#define Assert(condition)
#define OidIsValid(objectId)
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void hash_destroy(HTAB *hashp)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errcode(int sqlerrcode)
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
bool ExecCheckPermissions(List *rangeTable, List *rteperminfos, bool ereport_on_violation)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsVirtual
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsHeapTuple
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
#define palloc_object(type)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
char * OidOutputFunctionCall(Oid functionId, Datum val)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
#define FunctionCall3(flinfo, arg1, arg2, arg3)
int NewGUCNestLevel(void)
void AtEOXact_GUC(bool isCommit, int nestLevel)
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
#define dclist_container(type, membername, ptr)
static void dclist_push_tail(dclist_head *head, dlist_node *node)
static uint32 dclist_count(const dclist_head *head)
static void dclist_delete_from(dclist_head *head, dlist_node *node)
#define dclist_foreach_modify(iter, lhead)
IndexInfo * BuildIndexInfo(Relation index)
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
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, uint32 flags)
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)
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
List * lappend(List *list, void *datum)
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
char get_rel_relkind(Oid relid)
RegProcedure get_opcode(Oid opno)
Oid get_index_column_opclass(Oid index_oid, int attno)
char * get_namespace_name(Oid nspid)
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
void MemoryContextReset(MemoryContext context)
MemoryContext TopTransactionContext
void pfree(void *pointer)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
#define SECURITY_NOFORCE_RLS
#define SECURITY_LOCAL_USERID_CHANGE
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
void SetUserIdAndSecContext(Oid userid, int sec_context)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
@ COERCION_PATH_RELABELTYPE
#define FKCONSTR_MATCH_SIMPLE
#define FKCONSTR_MATCH_PARTIAL
#define FKCONSTR_MATCH_FULL
FormData_pg_attribute * Form_pg_attribute
END_CATALOG_STRUCT typedef FormData_pg_collation * Form_pg_collation
void FindFKPeriodOpers(Oid opclass, Oid *containedbyoperoid, Oid *aggedcontainedbyoperoid, Oid *intersectoperoid)
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
static int list_length(const List *l)
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define ERRCODE_T_R_SERIALIZATION_FAILURE
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum Int32GetDatum(int32 X)
#define RelationGetForm(relation)
#define RelationGetRelid(relation)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define RelationGetNamespace(relation)
int errtableconstraint(Relation rel, const char *conname)
static void ri_FastPathEndBatch(void *arg)
static bool recheck_matched_pk_tuple(Relation idxrel, ScanKeyData *skeys, int nkeys, TupleTableSlot *new_slot)
static Datum ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
static bool ri_PerformCheck(const RI_ConstraintInfo *riinfo, RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, bool is_restrict, bool detectNewRows, int expect_OK)
#define RI_TRIGTYPE_INSERT
static const RI_ConstraintInfo * ri_LoadConstraintInfo(Oid constraintOid)
static Datum RI_FKey_check(TriggerData *trigdata)
static bool ri_fastpath_xact_callback_registered
#define RI_PLAN_SETNULL_ONUPDATE
#define RI_PLAN_CASCADE_ONUPDATE
#define RI_TRIGTYPE_DELETE
static void ri_FastPathSubXactCallback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Datum RI_FKey_setnull_del(PG_FUNCTION_ARGS)
static void ri_FastPathBatchFlush(RI_FastPathEntry *fpentry, Relation fk_rel, const RI_ConstraintInfo *riinfo)
static bool ri_fastpath_callback_registered
static pg_noreturn void ri_ReportViolation(const RI_ConstraintInfo *riinfo, Relation pk_rel, Relation fk_rel, TupleTableSlot *violatorslot, TupleDesc tupdesc, int queryno, bool is_restrict, bool partgone)
static void ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan)
static void quoteOneName(char *buffer, const char *name)
bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
#define RI_PLAN_LAST_ON_PK
#define RIAttType(rel, attnum)
static void ri_GenerateQualCollation(StringInfo buf, Oid collation)
Datum RI_FKey_cascade_del(PG_FUNCTION_ARGS)
#define RI_KEYS_SOME_NULL
Datum RI_FKey_check_upd(PG_FUNCTION_ARGS)
static HTAB * ri_query_cache
#define MAX_QUOTED_REL_NAME_LEN
Datum RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
static int ri_FastPathFlushLoop(RI_FastPathEntry *fpentry, TupleTableSlot *fk_slot, const RI_ConstraintInfo *riinfo, Relation fk_rel, Snapshot snapshot, IndexScanDesc scandesc)
static void ri_FastPathXactCallback(XactEvent event, void *arg)
static Datum ri_restrict(TriggerData *trigdata, bool is_no_action)
Datum RI_FKey_restrict_del(PG_FUNCTION_ARGS)
Datum RI_FKey_noaction_del(PG_FUNCTION_ARGS)
static void quoteRelationName(char *buffer, Relation rel)
static int ri_NullCheck(TupleDesc tupDesc, TupleTableSlot *slot, const RI_ConstraintInfo *riinfo, bool rel_is_pk)
static void ri_GenerateQual(StringInfo buf, const char *sep, const char *leftop, Oid leftoptype, Oid opoid, const char *rightop, Oid rightoptype)
static void build_index_scankeys(const RI_ConstraintInfo *riinfo, Relation idx_rel, Datum *pk_vals, char *pk_nulls, ScanKey skeys)
static bool ri_LockPKTuple(Relation pk_rel, TupleTableSlot *slot, Snapshot snap, bool *concurrently_updated)
static bool ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, const RI_ConstraintInfo *riinfo, bool rel_is_pk)
static HTAB * ri_fastpath_cache
static RI_CompareHashEntry * ri_HashCompareOp(Oid eq_opr, Oid typeid)
#define RI_PLAN_CHECK_LOOKUPPK_FROM_PK
#define RIAttCollation(rel, attnum)
static dclist_head ri_constraint_cache_valid_list
static Oid get_ri_constraint_root(Oid constrOid)
Datum RI_FKey_check_ins(PG_FUNCTION_ARGS)
static HTAB * ri_compare_cache
static void ri_populate_fastpath_metadata(RI_ConstraintInfo *riinfo, Relation fk_rel, Relation idx_rel)
#define RI_KEYS_NONE_NULL
#define RI_FASTPATH_BATCH_SIZE
#define RI_INIT_QUERYHASHSIZE
static const RI_ConstraintInfo * ri_FetchConstraintInfo(Trigger *trigger, Relation trig_rel, bool rel_is_pk)
static bool ri_FastPathProbeOne(Relation pk_rel, Relation idx_rel, IndexScanDesc scandesc, TupleTableSlot *slot, Snapshot snapshot, const RI_ConstraintInfo *riinfo, ScanKeyData *skey, int nkeys)
static void ri_FastPathBatchAdd(const RI_ConstraintInfo *riinfo, Relation fk_rel, TupleTableSlot *newslot)
static void ri_BuildQueryKey(RI_QueryKey *key, const RI_ConstraintInfo *riinfo, int32 constr_queryno)
static void ri_FastPathCheck(const RI_ConstraintInfo *riinfo, Relation fk_rel, TupleTableSlot *newslot)
#define RI_PLAN_CASCADE_ONDELETE
Datum RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
#define RI_PLAN_SETDEFAULT_ONDELETE
Datum RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
#define RI_PLAN_SETDEFAULT_ONUPDATE
#define RI_PLAN_CHECK_LOOKUPPK
static bool ri_CompareWithCast(Oid eq_opr, Oid typeid, Oid collid, Datum lhs, Datum rhs)
static int ri_FastPathFlushArray(RI_FastPathEntry *fpentry, TupleTableSlot *fk_slot, const RI_ConstraintInfo *riinfo, Relation fk_rel, Snapshot snapshot, IndexScanDesc scandesc)
#define RI_PLAN_SETNULL_ONDELETE
#define RI_INIT_CONSTRAINTHASHSIZE
static void ri_CheckPermissions(Relation query_rel)
bool RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
static RI_FastPathEntry * ri_FastPathGetEntry(const RI_ConstraintInfo *riinfo, Relation fk_rel)
static bool ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, TupleTableSlot *oldslot, const RI_ConstraintInfo *riinfo)
void RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
static void ri_FastPathTeardown(void)
static SPIPlanPtr ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes, RI_QueryKey *qkey, Relation fk_rel, Relation pk_rel)
#define MAX_QUOTED_NAME_LEN
static void ri_CheckTrigger(FunctionCallInfo fcinfo, const char *funcname, int tgkind)
static bool ri_fastpath_is_applicable(const RI_ConstraintInfo *riinfo)
#define RI_TRIGTYPE_UPDATE
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
int RI_FKey_trigger_type(Oid tgfoid)
Datum RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
Datum RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
static void ri_InitHashTables(void)
static void InvalidateConstraintCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
static void ri_ExtractValues(Relation rel, TupleTableSlot *slot, const RI_ConstraintInfo *riinfo, bool rel_is_pk, Datum *vals, char *nulls)
#define RIAttName(rel, attnum)
static HTAB * ri_constraint_cache
static SPIPlanPtr ri_FetchPreparedPlan(RI_QueryKey *key)
Datum RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
#define RI_PLAN_NO_ACTION
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
char * pg_get_partconstrdef_string(Oid partitionId, char *aliasname)
void generate_operator_clause(StringInfo buf, const char *leftop, Oid leftoptype, Oid opoid, const char *rightop, Oid rightoptype)
void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)
Snapshot GetTransactionSnapshot(void)
Snapshot GetLatestSnapshot(void)
void UnregisterSnapshot(Snapshot snapshot)
Snapshot RegisterSnapshot(Snapshot snapshot)
bool SPI_plan_is_valid(SPIPlanPtr plan)
int SPI_freeplan(SPIPlanPtr plan)
const char * SPI_result_code_string(int code)
SPITupleTable * SPI_tuptable
int SPI_execute_snapshot(SPIPlanPtr plan, const Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount)
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
int SPI_keepplan(SPIPlanPtr plan)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
int16 pk_attnums[RI_MAX_NUMKEYS]
Oid agged_period_contained_by_oper
int16 fk_attnums[RI_MAX_NUMKEYS]
Oid pp_eq_oprs[RI_MAX_NUMKEYS]
Oid pf_eq_oprs[RI_MAX_NUMKEYS]
Oid period_contained_by_oper
int16 confdelsetcols[RI_MAX_NUMKEYS]
Oid period_intersect_oper
Oid ff_eq_oprs[RI_MAX_NUMKEYS]
HeapTuple batch[RI_FASTPATH_BATCH_SIZE]
const struct IndexAmRoutine * rd_indam
TupleTableSlot * tg_trigslot
TupleTableSlot * tg_newslot
#define FirstLowInvalidHeapAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
#define GetSysCacheHashValue1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
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)
#define TUPLE_LOCK_FLAG_FIND_LAST_VERSION
static bool table_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot, Snapshot snapshot)
#define TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS
void RegisterAfterTriggerBatchCallback(AfterTriggerBatchCallback callback, void *arg)
bool AfterTriggerIsActive(void)
#define TRIGGER_FIRED_BY_DELETE(event)
#define CALLED_AS_TRIGGER(fcinfo)
#define TRIGGER_FIRED_FOR_ROW(event)
#define TRIGGER_FIRED_AFTER(event)
#define TRIGGER_FIRED_BY_INSERT(event)
#define TRIGGER_FIRED_BY_UPDATE(event)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
static bool slot_is_current_xact_tuple(TupleTableSlot *slot)
static bool slot_attisnull(TupleTableSlot *slot, int attnum)
void CommandCounterIncrement(void)
void RegisterXactCallback(XactCallback callback, void *arg)
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
CommandId GetCurrentCommandId(bool used)
@ SUBXACT_EVENT_ABORT_SUB
#define IsolationUsesXactSnapshot()