44#include "utils/fmgroids.h"
60#define RI_MAX_NUMKEYS INDEX_MAX_KEYS
62#define RI_INIT_CONSTRAINTHASHSIZE 64
63#define RI_INIT_QUERYHASHSIZE (RI_INIT_CONSTRAINTHASHSIZE * 4)
65#define RI_KEYS_ALL_NULL 0
66#define RI_KEYS_SOME_NULL 1
67#define RI_KEYS_NONE_NULL 2
71#define RI_PLAN_CHECK_LOOKUPPK 1
72#define RI_PLAN_CHECK_LOOKUPPK_FROM_PK 2
73#define RI_PLAN_LAST_ON_PK RI_PLAN_CHECK_LOOKUPPK_FROM_PK
75#define RI_PLAN_CASCADE_ONDELETE 3
76#define RI_PLAN_CASCADE_ONUPDATE 4
77#define RI_PLAN_NO_ACTION 5
79#define RI_PLAN_RESTRICT 6
80#define RI_PLAN_SETNULL_ONDELETE 7
81#define RI_PLAN_SETNULL_ONUPDATE 8
82#define RI_PLAN_SETDEFAULT_ONDELETE 9
83#define RI_PLAN_SETDEFAULT_ONUPDATE 10
85#define MAX_QUOTED_NAME_LEN (NAMEDATALEN*2+3)
86#define MAX_QUOTED_REL_NAME_LEN (MAX_QUOTED_NAME_LEN*2)
88#define RIAttName(rel, attnum) NameStr(*attnumAttName(rel, attnum))
89#define RIAttType(rel, attnum) attnumTypeId(rel, attnum)
90#define RIAttCollation(rel, attnum) attnumCollationId(rel, attnum)
92#define RI_TRIGTYPE_INSERT 1
93#define RI_TRIGTYPE_UPDATE 2
94#define RI_TRIGTYPE_DELETE 3
201 const char *leftop,
Oid leftoptype,
203 const char *rightop,
Oid rightoptype);
209 int32 constr_queryno);
234 bool detectNewRows,
int expect_OK);
237 Datum *vals,
char *nulls);
313 (
errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
314 errmsg(
"insert or update on table \"%s\" violates foreign key constraint \"%s\"",
317 errdetail(
"MATCH FULL does not allow mixing of null and nonnull key values."),
365 const char *querysep;
393 pk_only = pk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
402 "SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
411 for (
int i = 0;
i < riinfo->
nkeys;
i++)
424 queryoids[
i] = fk_type;
436 "pg_catalog.range_agg", ANYMULTIRANGEOID);
442 &qkey, fk_rel, pk_rel);
456 pk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE,
536 const char *querysep;
564 pk_only = pk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
572 "SELECT 1 FROM (SELECT %s AS r FROM %s%s x",
581 for (
int i = 0;
i < riinfo->
nkeys;
i++)
593 queryoids[
i] = pk_type;
605 "pg_catalog.range_agg", ANYMULTIRANGEOID);
611 &qkey, fk_rel, pk_rel);
743 if (is_no_action && !riinfo->
hasperiod &&
766 const char *querysep;
779 fk_only = fk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
785 for (
int i = 0;
i < riinfo->
nkeys;
i++)
798 queryoids[
i] = pk_type;
831 char *pk_only = pk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
845 paramname, pk_period_type);
855 periodattname, pk_only, pkrelname);
859 for (
int i = 0;
i < riinfo->
nkeys;
i++)
871 queryoids[
i] = pk_type;
876 intersectbuf.
data, fk_period_type,
878 replacementsbuf.
data, ANYMULTIRANGEOID);
887 &qkey, fk_rel, pk_rel);
952 const char *querysep;
964 fk_only = fk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
970 for (
int i = 0;
i < riinfo->nkeys;
i++)
980 riinfo->pf_eq_oprs[
i],
983 queryoids[
i] = pk_type;
988 &qkey, fk_rel, pk_rel);
1058 const char *querysep;
1059 const char *qualsep;
1061 const char *fk_only;
1075 fk_only = fk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
1079 fk_only, fkrelname);
1082 for (
int i = 0,
j = riinfo->nkeys; i < riinfo->nkeys;
i++,
j++)
1095 riinfo->pf_eq_oprs[
i],
1099 queryoids[
i] = pk_type;
1100 queryoids[
j] = pk_type;
1106 &qkey, fk_rel, pk_rel);
1226 queryno = is_set_null
1231 queryno = is_set_null
1236 elog(
ERROR,
"invalid tgkind passed to ri_set");
1247 const char *querysep;
1248 const char *qualsep;
1250 const char *fk_only;
1251 int num_cols_to_set;
1252 const int16 *set_cols;
1257 num_cols_to_set = riinfo->
nkeys;
1274 num_cols_to_set = riinfo->
nkeys;
1279 elog(
ERROR,
"invalid tgkind passed to ri_set");
1291 fk_only = fk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
1295 fk_only, fkrelname);
1301 for (
int i = 0;
i < num_cols_to_set;
i++)
1307 is_set_null ?
"NULL" :
"DEFAULT");
1315 for (
int i = 0;
i < riinfo->
nkeys;
i++)
1329 queryoids[
i] = pk_type;
1334 &qkey, fk_rel, pk_rel);
1401 if (newslot &&
ri_KeysEqual(pk_rel, oldslot, newslot, riinfo,
true))
1428 Assert(fk_rel->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE);
1494 if (
ri_KeysEqual(fk_rel, oldslot, newslot, riinfo,
false))
1533 const char *fk_only;
1534 const char *pk_only;
1536 char workmembuf[32];
1552 perminfos =
lappend(perminfos, pk_perminfo);
1556 rte->relkind = pk_rel->
rd_rel->relkind;
1564 perminfos =
lappend(perminfos, fk_perminfo);
1568 rte->relkind = fk_rel->
rd_rel->relkind;
1573 for (
int i = 0;
i < riinfo->
nkeys;
i++)
1593 ((pk_rel->
rd_rel->relrowsecurity &&
1596 (fk_rel->
rd_rel->relrowsecurity &&
1619 for (
int i = 0;
i < riinfo->
nkeys;
i++)
1629 fk_only = fk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
1631 pk_only = pk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
1634 " FROM %s%s fk LEFT OUTER JOIN %s%s pk ON",
1635 fk_only, fkrelname, pk_only, pkrelname);
1637 strcpy(pkattname,
"pk.");
1638 strcpy(fkattname,
"fk.");
1640 for (
int i = 0;
i < riinfo->
nkeys;
i++)
1654 fkattname, fk_type);
1655 if (pk_coll != fk_coll)
1668 for (
int i = 0;
i < riinfo->
nkeys;
i++)
1672 "%sfk.%s IS NOT NULL",
1719 elog(
ERROR,
"SPI_prepare returned %s for %s",
1763 for (
int i = 0;
i < fake_riinfo.
nkeys;
i++)
1774 (
errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
1775 errmsg(
"insert or update on table \"%s\" violates foreign key constraint \"%s\"",
1778 errdetail(
"MATCH FULL does not allow mixing of null and nonnull key values."),
1817 char *constraintDef;
1823 const char *fk_only;
1825 char workmembuf[32];
1856 for (
i = 0;
i < riinfo->
nkeys;
i++)
1866 fk_only = fk_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE ?
1869 " FROM %s%s fk JOIN %s pk ON",
1870 fk_only, fkrelname, pkrelname);
1871 strcpy(pkattname,
"pk.");
1872 strcpy(fkattname,
"fk.");
1874 for (
i = 0;
i < riinfo->
nkeys;
i++)
1888 fkattname, fk_type);
1889 if (pk_coll != fk_coll)
1900 if (constraintDef && constraintDef[0] !=
'\0')
1907 for (
i = 0;
i < riinfo->
nkeys;
i++)
1911 "%sfk.%s IS NOT NULL",
1958 elog(
ERROR,
"SPI_prepare returned %s for %s",
2002 for (
i = 0;
i < fake_riinfo.
nkeys;
i++)
2006 slot, tupdesc, 0,
false,
true);
2039 *buffer++ = *
name++;
2054 buffer += strlen(buffer);
2070 const char *leftop,
Oid leftoptype,
2072 const char *rightop,
Oid rightoptype)
2076 rightop, rightoptype);
2108 elog(
ERROR,
"cache lookup failed for collation %u", collation);
2110 collname =
NameStr(colltup->collname);
2137 int32 constr_queryno)
2161 key->constr_queryno = constr_queryno;
2174 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2175 errmsg(
"function \"%s\" was not called by trigger manager",
funcname)));
2183 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2191 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2197 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2203 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2226 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2227 errmsg(
"no pg_constraint entry for trigger \"%s\" on table \"%s\"",
2229 errhint(
"Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT.")));
2239 elog(
ERROR,
"wrong pg_constraint entry for trigger \"%s\" on table \"%s\"",
2246 elog(
ERROR,
"wrong pg_constraint entry for trigger \"%s\" on table \"%s\"",
2253 elog(
ERROR,
"unrecognized confmatchtype: %d",
2258 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2259 errmsg(
"MATCH PARTIAL not yet implemented")));
2288 riinfo->
valid =
false;
2289 else if (riinfo->
valid)
2297 elog(
ERROR,
"cache lookup failed for constraint %u", constraintOid);
2300 if (conForm->contype != CONSTRAINT_FOREIGN)
2301 elog(
ERROR,
"constraint %u is not a foreign key constraint",
2316 riinfo->
pk_relid = conForm->confrelid;
2317 riinfo->
fk_relid = conForm->conrelid;
2356 riinfo->
valid =
true;
2371 Oid constrParentOid;
2375 elog(
ERROR,
"cache lookup failed for constraint %u", constrOid);
2380 constrOid = constrParentOid;
2418 valid_link, iter.
cur);
2425 if (hashvalue == 0 ||
2429 riinfo->
valid =
false;
2447 int save_sec_context;
2489 bool detectNewRows,
int expect_OK)
2499 int save_sec_context;
2521 source_rel = fk_rel;
2522 source_is_pk =
false;
2526 source_rel = pk_rel;
2527 source_is_pk =
true;
2537 vals + riinfo->
nkeys, nulls + riinfo->
nkeys);
2586 test_snapshot, crosscheck_snapshot,
2587 false,
false, limit);
2596 if (expect_OK >= 0 && spi_result != expect_OK)
2598 (
errcode(ERRCODE_INTERNAL_ERROR),
2599 errmsg(
"referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result",
2603 errhint(
"This is most likely due to a rule having rewritten the query.")));
2611 newslot ? newslot : oldslot,
2624 Datum *vals,
char *nulls)
2626 const int16 *attnums;
2634 for (
int i = 0;
i < riinfo->
nkeys;
i++)
2637 nulls[
i] = isnull ?
'n' :
' ';
2654 int queryno,
bool is_restrict,
bool partgone)
2659 const int16 *attnums;
2662 bool has_perm =
true;
2672 rel_oid = fk_rel->
rd_id;
2673 if (tupdesc == NULL)
2674 tupdesc = fk_rel->
rd_att;
2679 rel_oid = pk_rel->
rd_id;
2680 if (tupdesc == NULL)
2681 tupdesc = pk_rel->
rd_att;
2730 int fnum = attnums[
idx];
2763 (
errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
2764 errmsg(
"removing partition \"%s\" violates foreign key constraint \"%s\"",
2767 errdetail(
"Key (%s)=(%s) is still referenced from table \"%s\".",
2773 (
errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
2774 errmsg(
"insert or update on table \"%s\" violates foreign key constraint \"%s\"",
2778 errdetail(
"Key (%s)=(%s) is not present in table \"%s\".",
2781 errdetail(
"Key is not present in table \"%s\".",
2784 else if (is_restrict)
2786 (
errcode(ERRCODE_RESTRICT_VIOLATION),
2787 errmsg(
"update or delete on table \"%s\" violates RESTRICT setting of foreign key constraint \"%s\" on table \"%s\"",
2792 errdetail(
"Key (%s)=(%s) is referenced from table \"%s\".",
2795 errdetail(
"Key is referenced from table \"%s\".",
2800 (
errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
2801 errmsg(
"update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"",
2806 errdetail(
"Key (%s)=(%s) is still referenced from table \"%s\".",
2809 errdetail(
"Key is still referenced from table \"%s\".",
2827 const int16 *attnums;
2828 bool allnull =
true;
2829 bool nonenull =
true;
2836 for (
int i = 0;
i < riinfo->
nkeys;
i++)
2864 ctl.keysize =
sizeof(
Oid);
2988 const int16 *attnums;
2996 for (
int i = 0;
i < riinfo->
nkeys;
i++)
3051 newvalue, oldvalue))
3133 key.eq_opr = eq_opr;
3134 key.typeid =
typeid;
3139 entry->
valid =
false;
3170 Assert(lefttype == righttype);
3171 if (
typeid == lefttype)
3188 elog(
ERROR,
"no conversion function from %s to %s",
3198 entry->
valid =
true;
3214 case F_RI_FKEY_CASCADE_DEL:
3215 case F_RI_FKEY_CASCADE_UPD:
3216 case F_RI_FKEY_RESTRICT_DEL:
3217 case F_RI_FKEY_RESTRICT_UPD:
3218 case F_RI_FKEY_SETNULL_DEL:
3219 case F_RI_FKEY_SETNULL_UPD:
3220 case F_RI_FKEY_SETDEFAULT_DEL:
3221 case F_RI_FKEY_SETDEFAULT_UPD:
3222 case F_RI_FKEY_NOACTION_DEL:
3223 case F_RI_FKEY_NOACTION_UPD:
3226 case F_RI_FKEY_CHECK_INS:
3227 case F_RI_FKEY_CHECK_UPD:
Datum idx(PG_FUNCTION_ARGS)
bool has_bypassrls_privilege(Oid roleid)
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Bitmapset * bms_add_member(Bitmapset *a, int x)
#define Assert(condition)
#define pg_attribute_noreturn()
#define OidIsValid(objectId)
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, long nelem, const HASHCTL *info, int flags)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#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)
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)
#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)
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
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)
MemoryContext TopMemoryContext
#define SECURITY_NOFORCE_RLS
#define SECURITY_LOCAL_USERID_CHANGE
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
void SetUserIdAndSecContext(Oid userid, int sec_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
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)
FormData_pg_constraint * Form_pg_constraint
static int list_length(const List *l)
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 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
struct RI_ConstraintInfo RI_ConstraintInfo
static const RI_ConstraintInfo * ri_LoadConstraintInfo(Oid constraintOid)
static Datum RI_FKey_check(TriggerData *trigdata)
#define RI_PLAN_SETNULL_ONUPDATE
#define RI_PLAN_CASCADE_ONUPDATE
#define RI_TRIGTYPE_DELETE
Datum RI_FKey_setnull_del(PG_FUNCTION_ARGS)
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 void InvalidateConstraintCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
static Datum ri_restrict(TriggerData *trigdata, bool is_no_action)
Datum RI_FKey_restrict_del(PG_FUNCTION_ARGS)
static void ri_ReportViolation(const RI_ConstraintInfo *riinfo, Relation pk_rel, Relation fk_rel, TupleTableSlot *violatorslot, TupleDesc tupdesc, int queryno, bool is_restrict, bool partgone) pg_attribute_noreturn()
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)
struct RI_QueryKey RI_QueryKey
static bool ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, const RI_ConstraintInfo *riinfo, bool rel_is_pk)
struct RI_CompareHashEntry RI_CompareHashEntry
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)
struct RI_QueryHashEntry RI_QueryHashEntry
static HTAB * ri_compare_cache
#define RI_KEYS_NONE_NULL
#define RI_INIT_QUERYHASHSIZE
static const RI_ConstraintInfo * ri_FetchConstraintInfo(Trigger *trigger, Relation trig_rel, bool rel_is_pk)
static void ri_BuildQueryKey(RI_QueryKey *key, const RI_ConstraintInfo *riinfo, int32 constr_queryno)
#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)
#define RI_PLAN_SETNULL_ONDELETE
#define RI_INIT_CONSTRAINTHASHSIZE
bool RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_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 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)
#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 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)
struct RI_CompareKey RI_CompareKey
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)
Snapshot GetTransactionSnapshot(void)
Snapshot GetLatestSnapshot(void)
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, 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]
TupleTableSlot * tg_trigslot
TupleTableSlot * tg_newslot
TupleDesc tts_tupleDescriptor
#define FirstLowInvalidHeapAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define GetSysCacheHashValue1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
static bool table_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot, Snapshot snapshot)
#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 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)
#define IsolationUsesXactSnapshot()