| Line | Hits | Source | Commit |
|---|---|---|---|
| 14066 | - | CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint, | - |
| 14067 | - | Oid constraintOid, Oid indexOid, Oid parentTrigOid, | - |
| 14068 | - | bool on_insert) | - |
| 14069 | - | { | - |
| 14070 | - | ObjectAddress trigAddress; | - |
| 14071 | - | CreateTrigStmt *fk_trigger; | - |
| 14072 | - | - | |
| 14073 | - | /* | - |
| 14074 | - | * Note: for a self-referential FK (referencing and referenced tables are | - |
| 14075 | - | * the same), it is important that the ON UPDATE action fires before the | - |
| 14076 | - | * CHECK action, since both triggers will fire on the same row during an | - |
| 14077 | - | * UPDATE event; otherwise the CHECK trigger will be checking a non-final | - |
| 14078 | - | * state of the row. Triggers fire in name order, so we ensure this by | - |
| 14079 | - | * using names like "RI_ConstraintTrigger_a_NNNN" for the action triggers | - |
| 14080 | - | * and "RI_ConstraintTrigger_c_NNNN" for the check triggers. | - |
| 14081 | - | */ | - |
| 14082 | - | fk_trigger = makeNode(CreateTrigStmt); | - |
| 14083 | - | fk_trigger->replace = false; | - |
| 14084 | 4898 | fk_trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; | 39ae762CREATE TABLE LIKE INCLUDING TRIGGERS copies tgenabled |
| 14085 | - | fk_trigger->isconstraint = true; | - |
| 14086 | - | fk_trigger->trigname = "RI_ConstraintTrigger_c"; | - |
| 14087 | - | fk_trigger->relation = NULL; | - |
| 14088 | - | - | |
| 14089 | - | /* Either ON INSERT or ON UPDATE */ | - |
| 14090 | - | if (on_insert) | - |
| 14091 | - | { | - |
| 14092 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins"); | - |
| 14093 | - | fk_trigger->events = TRIGGER_TYPE_INSERT; | - |
| 14094 | - | } | - |
| 14095 | - | else | - |
| 14096 | - | { | - |
| 14097 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd"); | - |
| 14098 | - | fk_trigger->events = TRIGGER_TYPE_UPDATE; | - |
| 14099 | - | } | - |
| 14100 | - | - | |
| 14101 | - | fk_trigger->args = NIL; | - |
| 14102 | - | fk_trigger->row = true; | - |
| 14103 | - | fk_trigger->timing = TRIGGER_TYPE_AFTER; | - |
| 14104 | - | fk_trigger->columns = NIL; | - |
| 14105 | - | fk_trigger->whenClause = NULL; | - |
| 14106 | - | fk_trigger->transitionRels = NIL; | - |
| 14107 | - | fk_trigger->deferrable = fkconstraint->deferrable; | - |
| 14108 | - | fk_trigger->initdeferred = fkconstraint->initdeferred; | - |
| 14109 | - | fk_trigger->constrrel = NULL; | - |
| 14110 | 4898 | fk_trigger->trigcomment = NULL; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 14111 | 4898 | fk_trigger->transformed = true; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 14112 | - | - | |
| 14113 | - | trigAddress = CreateTrigger(fk_trigger, NULL, myRelOid, refRelOid, | - |
| 14114 | - | constraintOid, indexOid, InvalidOid, | - |
| 14115 | - | parentTrigOid, NULL, true, false); | - |
| 14116 | - | - | |
| 14117 | - | /* Make changes-so-far visible */ | - |
| 14118 | - | CommandCounterIncrement(); | - |
| 14119 | - | - | |
| 14120 | - | return trigAddress.objectId; | - |
| 14121 | - | } | - |
| Line | Hits | Source | Commit |
|---|---|---|---|
| 14132 | - | createForeignKeyActionTriggers(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint, | - |
| 14133 | - | Oid constraintOid, Oid indexOid, | - |
| 14134 | - | Oid parentDelTrigger, Oid parentUpdTrigger, | - |
| 14135 | - | Oid *deleteTrigOid, Oid *updateTrigOid) | - |
| 14136 | - | { | - |
| 14137 | - | CreateTrigStmt *fk_trigger; | - |
| 14138 | - | ObjectAddress trigAddress; | - |
| 14139 | - | - | |
| 14140 | - | /* | - |
| 14141 | - | * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON | - |
| 14142 | - | * DELETE action on the referenced table. | - |
| 14143 | - | */ | - |
| 14144 | - | fk_trigger = makeNode(CreateTrigStmt); | - |
| 14145 | - | fk_trigger->replace = false; | - |
| 14146 | 2796 | fk_trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; | 39ae762CREATE TABLE LIKE INCLUDING TRIGGERS copies tgenabled |
| 14147 | - | fk_trigger->isconstraint = true; | - |
| 14148 | - | fk_trigger->trigname = "RI_ConstraintTrigger_a"; | - |
| 14149 | - | fk_trigger->relation = NULL; | - |
| 14150 | - | fk_trigger->args = NIL; | - |
| 14151 | - | fk_trigger->row = true; | - |
| 14152 | - | fk_trigger->timing = TRIGGER_TYPE_AFTER; | - |
| 14153 | - | fk_trigger->events = TRIGGER_TYPE_DELETE; | - |
| 14154 | - | fk_trigger->columns = NIL; | - |
| 14155 | - | fk_trigger->whenClause = NULL; | - |
| 14156 | - | fk_trigger->transitionRels = NIL; | - |
| 14157 | - | fk_trigger->constrrel = NULL; | - |
| 14158 | 2796 | fk_trigger->trigcomment = NULL; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 14159 | 2796 | fk_trigger->transformed = true; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 14160 | - | - | |
| 14161 | - | switch (fkconstraint->fk_del_action) | - |
| 14162 | - | { | - |
| 14163 | - | case FKCONSTR_ACTION_NOACTION: | - |
| 14164 | - | fk_trigger->deferrable = fkconstraint->deferrable; | - |
| 14165 | - | fk_trigger->initdeferred = fkconstraint->initdeferred; | - |
| 14166 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del"); | - |
| 14167 | - | break; | - |
| 14168 | - | case FKCONSTR_ACTION_RESTRICT: | - |
| 14169 | - | fk_trigger->deferrable = false; | - |
| 14170 | - | fk_trigger->initdeferred = false; | - |
| 14171 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del"); | - |
| 14172 | - | break; | - |
| 14173 | - | case FKCONSTR_ACTION_CASCADE: | - |
| 14174 | - | fk_trigger->deferrable = false; | - |
| 14175 | - | fk_trigger->initdeferred = false; | - |
| 14176 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del"); | - |
| 14177 | - | break; | - |
| 14178 | - | case FKCONSTR_ACTION_SETNULL: | - |
| 14179 | - | fk_trigger->deferrable = false; | - |
| 14180 | - | fk_trigger->initdeferred = false; | - |
| 14181 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del"); | - |
| 14182 | - | break; | - |
| 14183 | - | case FKCONSTR_ACTION_SETDEFAULT: | - |
| 14184 | - | fk_trigger->deferrable = false; | - |
| 14185 | - | fk_trigger->initdeferred = false; | - |
| 14186 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del"); | - |
| 14187 | - | break; | - |
| 14188 | - | default: | - |
| 14189 | - | elog(ERROR, "unrecognized FK action type: %d", | - |
| 14190 | - | (int) fkconstraint->fk_del_action); | - |
| 14191 | - | break; | - |
| 14192 | - | } | - |
| 14193 | - | - | |
| 14194 | - | trigAddress = CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, | - |
| 14195 | - | constraintOid, indexOid, InvalidOid, | - |
| 14196 | - | parentDelTrigger, NULL, true, false); | - |
| 14197 | - | if (deleteTrigOid) | - |
| 14198 | - | *deleteTrigOid = trigAddress.objectId; | - |
| 14199 | - | - | |
| 14200 | - | /* Make changes-so-far visible */ | - |
| 14201 | - | CommandCounterIncrement(); | - |
| 14202 | - | - | |
| 14203 | - | /* | - |
| 14204 | - | * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON | - |
| 14205 | - | * UPDATE action on the referenced table. | - |
| 14206 | - | */ | - |
| 14207 | - | fk_trigger = makeNode(CreateTrigStmt); | - |
| 14208 | - | fk_trigger->replace = false; | - |
| 14209 | 2796 | fk_trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; | 39ae762CREATE TABLE LIKE INCLUDING TRIGGERS copies tgenabled |
| 14210 | - | fk_trigger->isconstraint = true; | - |
| 14211 | - | fk_trigger->trigname = "RI_ConstraintTrigger_a"; | - |
| 14212 | - | fk_trigger->relation = NULL; | - |
| 14213 | - | fk_trigger->args = NIL; | - |
| 14214 | - | fk_trigger->row = true; | - |
| 14215 | - | fk_trigger->timing = TRIGGER_TYPE_AFTER; | - |
| 14216 | - | fk_trigger->events = TRIGGER_TYPE_UPDATE; | - |
| 14217 | - | fk_trigger->columns = NIL; | - |
| 14218 | - | fk_trigger->whenClause = NULL; | - |
| 14219 | - | fk_trigger->transitionRels = NIL; | - |
| 14220 | - | fk_trigger->constrrel = NULL; | - |
| 14221 | 2796 | fk_trigger->trigcomment = NULL; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 14222 | 2796 | fk_trigger->transformed = true; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 14223 | - | - | |
| 14224 | - | switch (fkconstraint->fk_upd_action) | - |
| 14225 | - | { | - |
| 14226 | - | case FKCONSTR_ACTION_NOACTION: | - |
| 14227 | - | fk_trigger->deferrable = fkconstraint->deferrable; | - |
| 14228 | - | fk_trigger->initdeferred = fkconstraint->initdeferred; | - |
| 14229 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd"); | - |
| 14230 | - | break; | - |
| 14231 | - | case FKCONSTR_ACTION_RESTRICT: | - |
| 14232 | - | fk_trigger->deferrable = false; | - |
| 14233 | - | fk_trigger->initdeferred = false; | - |
| 14234 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd"); | - |
| 14235 | - | break; | - |
| 14236 | - | case FKCONSTR_ACTION_CASCADE: | - |
| 14237 | - | fk_trigger->deferrable = false; | - |
| 14238 | - | fk_trigger->initdeferred = false; | - |
| 14239 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd"); | - |
| 14240 | - | break; | - |
| 14241 | - | case FKCONSTR_ACTION_SETNULL: | - |
| 14242 | - | fk_trigger->deferrable = false; | - |
| 14243 | - | fk_trigger->initdeferred = false; | - |
| 14244 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd"); | - |
| 14245 | - | break; | - |
| 14246 | - | case FKCONSTR_ACTION_SETDEFAULT: | - |
| 14247 | - | fk_trigger->deferrable = false; | - |
| 14248 | - | fk_trigger->initdeferred = false; | - |
| 14249 | - | fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd"); | - |
| 14250 | - | break; | - |
| 14251 | - | default: | - |
| 14252 | - | elog(ERROR, "unrecognized FK action type: %d", | - |
| 14253 | - | (int) fkconstraint->fk_upd_action); | - |
| 14254 | - | break; | - |
| 14255 | - | } | - |
| 14256 | - | - | |
| 14257 | - | trigAddress = CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, | - |
| 14258 | - | constraintOid, indexOid, InvalidOid, | - |
| 14259 | - | parentUpdTrigger, NULL, true, false); | - |
| 14260 | - | if (updateTrigOid) | - |
| 14261 | - | *updateTrigOid = trigAddress.objectId; | - |
| 14262 | - | } | - |
| Line | Hits | Source | Commit |
|---|---|---|---|
| 21095 | - | CloneRowTriggersToPartition(Relation parent, Relation partition) | - |
| 21096 | - | { | - |
| 21097 | - | Relation pg_trigger; | - |
| 21098 | - | ScanKeyData key; | - |
| 21099 | - | SysScanDesc scan; | - |
| 21100 | - | HeapTuple tuple; | - |
| 21101 | - | MemoryContext perTupCxt; | - |
| 21102 | - | - | |
| 21103 | - | ScanKeyInit(&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, | - |
| 21104 | - | F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(parent))); | - |
| 21105 | - | pg_trigger = table_open(TriggerRelationId, RowExclusiveLock); | - |
| 21106 | - | scan = systable_beginscan(pg_trigger, TriggerRelidNameIndexId, | - |
| 21107 | - | true, NULL, 1, &key); | - |
| 21108 | - | - | |
| 21109 | - | perTupCxt = AllocSetContextCreate(CurrentMemoryContext, | - |
| 21110 | - | "clone trig", ALLOCSET_SMALL_SIZES); | - |
| 21111 | - | - | |
| 21112 | - | while (HeapTupleIsValid(tuple = systable_getnext(scan))) | - |
| 21113 | - | { | - |
| 21114 | - | Form_pg_trigger trigForm = (Form_pg_trigger) GETSTRUCT(tuple); | - |
| 21115 | - | CreateTrigStmt *trigStmt; | - |
| 21116 | - | Node *qual = NULL; | - |
| 21117 | - | Datum value; | - |
| 21118 | - | bool isnull; | - |
| 21119 | - | List *cols = NIL; | - |
| 21120 | - | List *trigargs = NIL; | - |
| 21121 | - | MemoryContext oldcxt; | - |
| 21122 | - | - | |
| 21123 | - | /* | - |
| 21124 | - | * Ignore statement-level triggers; those are not cloned. | - |
| 21125 | - | */ | - |
| 21126 | - | if (!TRIGGER_FOR_ROW(trigForm->tgtype)) | - |
| 21127 | - | continue; | - |
| 21128 | - | - | |
| 21129 | - | /* | - |
| 21130 | - | * Don't clone internal triggers, because the constraint cloning code | - |
| 21131 | - | * will. | - |
| 21132 | - | */ | - |
| 21133 | - | if (trigForm->tgisinternal) | - |
| 21134 | - | continue; | - |
| 21135 | - | - | |
| 21136 | - | /* | - |
| 21137 | - | * Complain if we find an unexpected trigger type. | - |
| 21138 | - | */ | - |
| 21139 | - | if (!TRIGGER_FOR_BEFORE(trigForm->tgtype) && | - |
| 21140 | - | !TRIGGER_FOR_AFTER(trigForm->tgtype)) | - |
| 21141 | - | elog(ERROR, "unexpected trigger \"%s\" found", | - |
| 21142 | - | NameStr(trigForm->tgname)); | - |
| 21143 | - | - | |
| 21144 | - | /* Use short-lived context for CREATE TRIGGER */ | - |
| 21145 | - | oldcxt = MemoryContextSwitchTo(perTupCxt); | - |
| 21146 | - | - | |
| 21147 | - | /* | - |
| 21148 | - | * If there is a WHEN clause, generate a 'cooked' version of it that's | - |
| 21149 | - | * appropriate for the partition. | - |
| 21150 | - | */ | - |
| 21151 | - | value = heap_getattr(tuple, Anum_pg_trigger_tgqual, | - |
| 21152 | - | RelationGetDescr(pg_trigger), &isnull); | - |
| 21153 | - | if (!isnull) | - |
| 21154 | - | { | - |
| 21155 | - | qual = stringToNode(TextDatumGetCString(value)); | - |
| 21156 | - | qual = (Node *) map_partition_varattnos((List *) qual, PRS2_OLD_VARNO, | - |
| 21157 | - | partition, parent); | - |
| 21158 | - | qual = (Node *) map_partition_varattnos((List *) qual, PRS2_NEW_VARNO, | - |
| 21159 | - | partition, parent); | - |
| 21160 | - | } | - |
| 21161 | - | - | |
| 21162 | - | /* | - |
| 21163 | - | * If there is a column list, transform it to a list of column names. | - |
| 21164 | - | * Note we don't need to map this list in any way ... | - |
| 21165 | - | */ | - |
| 21166 | - | if (trigForm->tgattr.dim1 > 0) | - |
| 21167 | - | { | - |
| 21168 | - | int i; | - |
| 21169 | - | - | |
| 21170 | - | for (i = 0; i < trigForm->tgattr.dim1; i++) | - |
| 21171 | - | { | - |
| 21172 | - | Form_pg_attribute col; | - |
| 21173 | - | - | |
| 21174 | - | col = TupleDescAttr(parent->rd_att, | - |
| 21175 | - | trigForm->tgattr.values[i] - 1); | - |
| 21176 | - | cols = lappend(cols, | - |
| 21177 | - | makeString(pstrdup(NameStr(col->attname)))); | - |
| 21178 | - | } | - |
| 21179 | - | } | - |
| 21180 | - | - | |
| 21181 | - | /* Reconstruct trigger arguments list. */ | - |
| 21182 | - | if (trigForm->tgnargs > 0) | - |
| 21183 | - | { | - |
| 21184 | - | char *p; | - |
| 21185 | - | - | |
| 21186 | - | value = heap_getattr(tuple, Anum_pg_trigger_tgargs, | - |
| 21187 | - | RelationGetDescr(pg_trigger), &isnull); | - |
| 21188 | - | if (isnull) | - |
| 21189 | - | elog(ERROR, "tgargs is null for trigger \"%s\" in partition \"%s\"", | - |
| 21190 | - | NameStr(trigForm->tgname), RelationGetRelationName(partition)); | - |
| 21191 | - | - | |
| 21192 | - | p = (char *) VARDATA_ANY(DatumGetByteaPP(value)); | - |
| 21193 | - | - | |
| 21194 | - | for (int i = 0; i < trigForm->tgnargs; i++) | - |
| 21195 | - | { | - |
| 21196 | - | trigargs = lappend(trigargs, makeString(pstrdup(p))); | - |
| 21197 | - | p += strlen(p) + 1; | - |
| 21198 | - | } | - |
| 21199 | - | } | - |
| 21200 | - | - | |
| 21201 | - | trigStmt = makeNode(CreateTrigStmt); | - |
| 21202 | - | trigStmt->replace = false; | - |
| 21203 | 163 | trigStmt->tgenabled = trigForm->tgenabled; | 39ae762CREATE TABLE LIKE INCLUDING TRIGGERS copies tgenabled |
| 21204 | - | trigStmt->isconstraint = OidIsValid(trigForm->tgconstraint); | - |
| 21205 | - | trigStmt->trigname = NameStr(trigForm->tgname); | - |
| 21206 | - | trigStmt->relation = NULL; | - |
| 21207 | - | trigStmt->funcname = NULL; /* passed separately */ | - |
| 21208 | - | trigStmt->args = trigargs; | - |
| 21209 | - | trigStmt->row = true; | - |
| 21210 | - | trigStmt->timing = trigForm->tgtype & TRIGGER_TYPE_TIMING_MASK; | - |
| 21211 | - | trigStmt->events = trigForm->tgtype & TRIGGER_TYPE_EVENT_MASK; | - |
| 21212 | - | trigStmt->columns = cols; | - |
| 21213 | - | trigStmt->whenClause = NULL; /* passed separately */ | - |
| 21214 | - | trigStmt->transitionRels = NIL; /* not supported at present */ | - |
| 21215 | - | trigStmt->deferrable = trigForm->tgdeferrable; | - |
| 21216 | - | trigStmt->initdeferred = trigForm->tginitdeferred; | - |
| 21217 | - | trigStmt->constrrel = NULL; /* passed separately */ | - |
| 21218 | 163 | trigStmt->trigcomment = NULL; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 21219 | 163 | trigStmt->transformed = true; | e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 21220 | - | - | |
| 21221 | - | CreateTriggerFiringOn(trigStmt, NULL, RelationGetRelid(partition), | - |
| 21222 | - | trigForm->tgconstrrelid, InvalidOid, InvalidOid, | - |
| 21223 | - | trigForm->tgfoid, trigForm->oid, qual, | - |
| 21224 | - | false, true, trigForm->tgenabled); | - |
| 21225 | - | - | |
| 21226 | - | MemoryContextSwitchTo(oldcxt); | - |
| 21227 | - | MemoryContextReset(perTupCxt); | - |
| 21228 | - | } | - |
| 21229 | - | - | |
| 21230 | - | MemoryContextDelete(perTupCxt); | - |
| 21231 | - | - | |
| 21232 | - | systable_endscan(scan); | - |
| 21233 | - | table_close(pg_trigger, RowExclusiveLock); | - |
| 21234 | - | } | - |