trigger.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:23k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * trigger.c
  4.  *   PostgreSQL TRIGGERs support code.
  5.  *
  6.  *-------------------------------------------------------------------------
  7.  */
  8. #include "postgres.h"
  9. #include "access/genam.h"
  10. #include "access/heapam.h"
  11. #include "catalog/catalog.h"
  12. #include "catalog/catname.h"
  13. #include "catalog/indexing.h"
  14. #include "catalog/pg_language.h"
  15. #include "catalog/pg_proc.h"
  16. #include "catalog/pg_trigger.h"
  17. #include "commands/trigger.h"
  18. #include "executor/executor.h"
  19. #include "miscadmin.h"
  20. #include "utils/acl.h"
  21. #include "utils/builtins.h"
  22. #include "utils/inval.h"
  23. #include "utils/syscache.h"
  24. DLLIMPORT TriggerData *CurrentTriggerData = NULL;
  25. void RelationBuildTriggers(Relation relation);
  26. void FreeTriggerDesc(Relation relation);
  27. static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
  28. static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
  29.    TupleTableSlot **newSlot);
  30. extern GlobalMemory CacheCxt;
  31. void
  32. CreateTrigger(CreateTrigStmt *stmt)
  33. {
  34. int16 tgtype;
  35. int16 tgattr[8] = {0};
  36. Datum values[Natts_pg_trigger];
  37. char nulls[Natts_pg_trigger];
  38. Relation rel;
  39. Relation tgrel;
  40. HeapScanDesc tgscan;
  41. ScanKeyData key;
  42. Relation pgrel;
  43. HeapTuple tuple;
  44. Relation idescs[Num_pg_trigger_indices];
  45. Relation ridescs[Num_pg_class_indices];
  46. MemoryContext oldcxt;
  47. Oid fargtypes[8];
  48. int found = 0;
  49. int i;
  50. if (!allowSystemTableMods && IsSystemRelationName(stmt->relname))
  51. elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname);
  52. #ifndef NO_SECURITY
  53. if (!pg_ownercheck(GetPgUserName(), stmt->relname, RELNAME))
  54. elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
  55. #endif
  56. rel = heap_openr(stmt->relname);
  57. if (!RelationIsValid(rel))
  58. elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
  59. LockRelation(rel, AccessExclusiveLock);
  60. TRIGGER_CLEAR_TYPE(tgtype);
  61. if (stmt->before)
  62. TRIGGER_SETT_BEFORE(tgtype);
  63. if (stmt->row)
  64. TRIGGER_SETT_ROW(tgtype);
  65. else
  66. elog(ERROR, "CreateTrigger: STATEMENT triggers are unimplemented, yet");
  67. for (i = 0; i < 3 && stmt->actions[i]; i++)
  68. {
  69. switch (stmt->actions[i])
  70. {
  71. case 'i':
  72. if (TRIGGER_FOR_INSERT(tgtype))
  73. elog(ERROR, "CreateTrigger: double INSERT event specified");
  74. TRIGGER_SETT_INSERT(tgtype);
  75. break;
  76. case 'd':
  77. if (TRIGGER_FOR_DELETE(tgtype))
  78. elog(ERROR, "CreateTrigger: double DELETE event specified");
  79. TRIGGER_SETT_DELETE(tgtype);
  80. break;
  81. case 'u':
  82. if (TRIGGER_FOR_UPDATE(tgtype))
  83. elog(ERROR, "CreateTrigger: double UPDATE event specified");
  84. TRIGGER_SETT_UPDATE(tgtype);
  85. break;
  86. default:
  87. elog(ERROR, "CreateTrigger: unknown event specified");
  88. break;
  89. }
  90. }
  91. /* Scan pg_trigger */
  92. tgrel = heap_openr(TriggerRelationName);
  93. LockRelation(tgrel, AccessExclusiveLock);
  94. ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
  95.    F_OIDEQ, RelationGetRelid(rel));
  96. tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
  97. while (HeapTupleIsValid(tuple = heap_getnext(tgscan, 0)))
  98. {
  99. Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
  100. if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
  101. elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s",
  102.  stmt->trigname, stmt->relname);
  103. else
  104. found++;
  105. }
  106. heap_endscan(tgscan);
  107. MemSet(fargtypes, 0, 8 * sizeof(Oid));
  108. tuple = SearchSysCacheTuple(PRONAME,
  109. PointerGetDatum(stmt->funcname),
  110. Int32GetDatum(0),
  111. PointerGetDatum(fargtypes),
  112. 0);
  113. if (!HeapTupleIsValid(tuple) ||
  114. ((Form_pg_proc) GETSTRUCT(tuple))->pronargs != 0)
  115. elog(ERROR, "CreateTrigger: function %s() does not exist",
  116.  stmt->funcname);
  117. if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype != 0)
  118. elog(ERROR, "CreateTrigger: function %s() must return OPAQUE",
  119.  stmt->funcname);
  120. if (((Form_pg_proc) GETSTRUCT(tuple))->prolang != ClanguageId)
  121. {
  122. HeapTuple langTup;
  123. langTup = SearchSysCacheTuple(LANOID,
  124. ObjectIdGetDatum(((Form_pg_proc) GETSTRUCT(tuple))->prolang),
  125.   0, 0, 0);
  126. if (!HeapTupleIsValid(langTup))
  127. elog(ERROR, "CreateTrigger: cache lookup for PL failed");
  128. if (((Form_pg_language) GETSTRUCT(langTup))->lanispl == false)
  129. elog(ERROR, "CreateTrigger: only C and PL functions are supported");
  130. }
  131. MemSet(nulls, ' ', Natts_pg_trigger * sizeof(char));
  132. values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
  133. values[Anum_pg_trigger_tgname - 1] = NameGetDatum(namein(stmt->trigname));
  134. values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(tuple->t_data->t_oid);
  135. values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
  136. if (stmt->args)
  137. {
  138. List    *le;
  139. char    *args;
  140. int16 nargs = length(stmt->args);
  141. int len = 0;
  142. foreach(le, stmt->args)
  143. {
  144. char    *ar = (char *) lfirst(le);
  145. len += strlen(ar) + VARHDRSZ;
  146. for (; *ar; ar++)
  147. {
  148. if (*ar == '\')
  149. len++;
  150. }
  151. }
  152. args = (char *) palloc(len + 1);
  153. args[0] = 0;
  154. foreach(le, stmt->args)
  155. {
  156. char    *s = (char *) lfirst(le);
  157. char    *d = args + strlen(args);
  158. while (*s)
  159. {
  160. if (*s == '\')
  161. *d++ = '\';
  162. *d++ = *s++;
  163. }
  164. *d = 0;
  165. strcat(args, "\000");
  166. }
  167. values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
  168. values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(byteain(args));
  169. }
  170. else
  171. {
  172. values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
  173. values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(byteain(""));
  174. }
  175. values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
  176. tuple = heap_formtuple(tgrel->rd_att, values, nulls);
  177. heap_insert(tgrel, tuple);
  178. CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
  179. CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
  180. CatalogCloseIndices(Num_pg_trigger_indices, idescs);
  181. pfree(tuple);
  182. UnlockRelation(tgrel, AccessExclusiveLock);
  183. heap_close(tgrel);
  184. pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
  185. pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
  186. /* update pg_class */
  187. tuple = SearchSysCacheTupleCopy(RELNAME,
  188. PointerGetDatum(stmt->relname),
  189. 0, 0, 0);
  190. if (!HeapTupleIsValid(tuple))
  191. elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname);
  192. pgrel = heap_openr(RelationRelationName);
  193. ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
  194. RelationInvalidateHeapTuple(pgrel, tuple);
  195. heap_replace(pgrel, &tuple->t_self, tuple, NULL);
  196. CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
  197. CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
  198. CatalogCloseIndices(Num_pg_class_indices, ridescs);
  199. pfree(tuple);
  200. heap_close(pgrel);
  201. CommandCounterIncrement();
  202. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  203. FreeTriggerDesc(rel);
  204. rel->rd_rel->reltriggers = found + 1;
  205. RelationBuildTriggers(rel);
  206. MemoryContextSwitchTo(oldcxt);
  207. heap_close(rel);
  208. return;
  209. }
  210. void
  211. DropTrigger(DropTrigStmt *stmt)
  212. {
  213. Relation rel;
  214. Relation tgrel;
  215. HeapScanDesc tgscan;
  216. ScanKeyData key;
  217. Relation pgrel;
  218. HeapTuple tuple;
  219. Relation ridescs[Num_pg_class_indices];
  220. MemoryContext oldcxt;
  221. int found = 0;
  222. int tgfound = 0;
  223. #ifndef NO_SECURITY
  224. if (!pg_ownercheck(GetPgUserName(), stmt->relname, RELNAME))
  225. elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
  226. #endif
  227. rel = heap_openr(stmt->relname);
  228. if (!RelationIsValid(rel))
  229. elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
  230. LockRelation(rel, AccessExclusiveLock);
  231. tgrel = heap_openr(TriggerRelationName);
  232. LockRelation(tgrel, AccessExclusiveLock);
  233. ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
  234.    F_OIDEQ, RelationGetRelid(rel));
  235. tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
  236. while (HeapTupleIsValid(tuple = heap_getnext(tgscan, 0)))
  237. {
  238. Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
  239. if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
  240. {
  241. heap_delete(tgrel, &tuple->t_self, NULL);
  242. tgfound++;
  243. }
  244. else
  245. found++;
  246. }
  247. if (tgfound == 0)
  248. elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
  249.  stmt->trigname, stmt->relname);
  250. if (tgfound > 1)
  251. elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
  252.  tgfound, stmt->trigname, stmt->relname);
  253. heap_endscan(tgscan);
  254. UnlockRelation(tgrel, AccessExclusiveLock);
  255. heap_close(tgrel);
  256. tuple = SearchSysCacheTupleCopy(RELNAME,
  257. PointerGetDatum(stmt->relname),
  258. 0, 0, 0);
  259. if (!HeapTupleIsValid(tuple))
  260. elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname);
  261. /* update pg_class */
  262. pgrel = heap_openr(RelationRelationName);
  263. ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
  264. RelationInvalidateHeapTuple(pgrel, tuple);
  265. heap_replace(pgrel, &tuple->t_self, tuple, NULL);
  266. CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
  267. CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
  268. CatalogCloseIndices(Num_pg_class_indices, ridescs);
  269. pfree(tuple);
  270. heap_close(pgrel);
  271. CommandCounterIncrement();
  272. oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
  273. FreeTriggerDesc(rel);
  274. rel->rd_rel->reltriggers = found;
  275. if (found > 0)
  276. RelationBuildTriggers(rel);
  277. MemoryContextSwitchTo(oldcxt);
  278. heap_close(rel);
  279. return;
  280. }
  281. void
  282. RelationRemoveTriggers(Relation rel)
  283. {
  284. Relation tgrel;
  285. HeapScanDesc tgscan;
  286. ScanKeyData key;
  287. HeapTuple tup;
  288. tgrel = heap_openr(TriggerRelationName);
  289. LockRelation(tgrel, AccessExclusiveLock);
  290. ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
  291.    F_OIDEQ, RelationGetRelid(rel));
  292. tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
  293. while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
  294. heap_delete(tgrel, &tup->t_self, NULL);
  295. heap_endscan(tgscan);
  296. UnlockRelation(tgrel, AccessExclusiveLock);
  297. heap_close(tgrel);
  298. }
  299. void
  300. RelationBuildTriggers(Relation relation)
  301. {
  302. TriggerDesc *trigdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
  303. int ntrigs = relation->rd_rel->reltriggers;
  304. Trigger    *triggers = NULL;
  305. Trigger    *build;
  306. Relation tgrel;
  307. Form_pg_trigger pg_trigger;
  308. Relation irel;
  309. ScanKeyData skey;
  310. HeapTupleData tuple;
  311. IndexScanDesc sd;
  312. RetrieveIndexResult indexRes;
  313. Buffer buffer;
  314. struct varlena *val;
  315. bool isnull;
  316. int found;
  317. MemSet(trigdesc, 0, sizeof(TriggerDesc));
  318. ScanKeyEntryInitialize(&skey,
  319.    (bits16) 0x0,
  320.    (AttrNumber) 1,
  321.    (RegProcedure) F_OIDEQ,
  322.    ObjectIdGetDatum(RelationGetRelid(relation)));
  323. tgrel = heap_openr(TriggerRelationName);
  324. irel = index_openr(TriggerRelidIndex);
  325. sd = index_beginscan(irel, false, 1, &skey);
  326. for (found = 0;;)
  327. {
  328. indexRes = index_getnext(sd, ForwardScanDirection);
  329. if (!indexRes)
  330. break;
  331. tuple.t_self = indexRes->heap_iptr;
  332. heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
  333. pfree(indexRes);
  334. if (!tuple.t_data)
  335. continue;
  336. if (found == ntrigs)
  337. elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %.*s",
  338.  NAMEDATALEN, relation->rd_rel->relname.data);
  339. pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);
  340. if (triggers == NULL)
  341. triggers = (Trigger *) palloc(sizeof(Trigger));
  342. else
  343. triggers = (Trigger *) repalloc(triggers, (found + 1) * sizeof(Trigger));
  344. build = &(triggers[found]);
  345. build->tgname = nameout(&(pg_trigger->tgname));
  346. build->tgfoid = pg_trigger->tgfoid;
  347. build->tgfunc.fn_addr = NULL;
  348. build->tgtype = pg_trigger->tgtype;
  349. build->tgnargs = pg_trigger->tgnargs;
  350. memcpy(build->tgattr, &(pg_trigger->tgattr), 8 * sizeof(int16));
  351. val = (struct varlena *) fastgetattr(&tuple,
  352.  Anum_pg_trigger_tgargs,
  353.  tgrel->rd_att, &isnull);
  354. if (isnull)
  355. elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",
  356.  NAMEDATALEN, relation->rd_rel->relname.data);
  357. if (build->tgnargs > 0)
  358. {
  359. char    *p;
  360. int i;
  361. val = (struct varlena *) fastgetattr(&tuple,
  362.  Anum_pg_trigger_tgargs,
  363.  tgrel->rd_att, &isnull);
  364. if (isnull)
  365. elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",
  366.  NAMEDATALEN, relation->rd_rel->relname.data);
  367. p = (char *) VARDATA(val);
  368. build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
  369. for (i = 0; i < build->tgnargs; i++)
  370. {
  371. build->tgargs[i] = (char *) palloc(strlen(p) + 1);
  372. strcpy(build->tgargs[i], p);
  373. p += strlen(p) + 1;
  374. }
  375. }
  376. else
  377. build->tgargs = NULL;
  378. found++;
  379. ReleaseBuffer(buffer);
  380. }
  381. if (found < ntrigs)
  382. elog(ERROR, "RelationBuildTriggers: %d record not found for rel %.*s",
  383.  ntrigs - found,
  384.  NAMEDATALEN, relation->rd_rel->relname.data);
  385. index_endscan(sd);
  386. pfree(sd);
  387. index_close(irel);
  388. heap_close(tgrel);
  389. /* Build trigdesc */
  390. trigdesc->triggers = triggers;
  391. for (found = 0; found < ntrigs; found++)
  392. {
  393. build = &(triggers[found]);
  394. DescribeTrigger(trigdesc, build);
  395. }
  396. relation->trigdesc = trigdesc;
  397. }
  398. void
  399. FreeTriggerDesc(Relation relation)
  400. {
  401. TriggerDesc *trigdesc = relation->trigdesc;
  402. Trigger  ***t;
  403. Trigger    *trigger;
  404. int i;
  405. if (trigdesc == NULL)
  406. return;
  407. t = trigdesc->tg_before_statement;
  408. for (i = 0; i < 3; i++)
  409. if (t[i] != NULL)
  410. pfree(t[i]);
  411. t = trigdesc->tg_before_row;
  412. for (i = 0; i < 3; i++)
  413. if (t[i] != NULL)
  414. pfree(t[i]);
  415. t = trigdesc->tg_after_row;
  416. for (i = 0; i < 3; i++)
  417. if (t[i] != NULL)
  418. pfree(t[i]);
  419. t = trigdesc->tg_after_statement;
  420. for (i = 0; i < 3; i++)
  421. if (t[i] != NULL)
  422. pfree(t[i]);
  423. trigger = trigdesc->triggers;
  424. for (i = 0; i < relation->rd_rel->reltriggers; i++)
  425. {
  426. pfree(trigger->tgname);
  427. if (trigger->tgnargs > 0)
  428. {
  429. while (--(trigger->tgnargs) >= 0)
  430. pfree(trigger->tgargs[trigger->tgnargs]);
  431. pfree(trigger->tgargs);
  432. }
  433. trigger++;
  434. }
  435. pfree(trigdesc->triggers);
  436. pfree(trigdesc);
  437. relation->trigdesc = NULL;
  438. return;
  439. }
  440. static void
  441. DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
  442. {
  443. uint16    *n;
  444. Trigger  ***t,
  445.  ***tp;
  446. if (TRIGGER_FOR_ROW(trigger->tgtype)) /* Is ROW/STATEMENT
  447.  * trigger */
  448. {
  449. if (TRIGGER_FOR_BEFORE(trigger->tgtype))
  450. {
  451. n = trigdesc->n_before_row;
  452. t = trigdesc->tg_before_row;
  453. }
  454. else
  455. {
  456. n = trigdesc->n_after_row;
  457. t = trigdesc->tg_after_row;
  458. }
  459. }
  460. else
  461. /* STATEMENT (NI) */
  462. {
  463. if (TRIGGER_FOR_BEFORE(trigger->tgtype))
  464. {
  465. n = trigdesc->n_before_statement;
  466. t = trigdesc->tg_before_statement;
  467. }
  468. else
  469. {
  470. n = trigdesc->n_after_statement;
  471. t = trigdesc->tg_after_statement;
  472. }
  473. }
  474. if (TRIGGER_FOR_INSERT(trigger->tgtype))
  475. {
  476. tp = &(t[TRIGGER_EVENT_INSERT]);
  477. if (*tp == NULL)
  478. *tp = (Trigger **) palloc(sizeof(Trigger *));
  479. else
  480. *tp = (Trigger **) repalloc(*tp, (n[TRIGGER_EVENT_INSERT] + 1) *
  481. sizeof(Trigger *));
  482. (*tp)[n[TRIGGER_EVENT_INSERT]] = trigger;
  483. (n[TRIGGER_EVENT_INSERT])++;
  484. }
  485. if (TRIGGER_FOR_DELETE(trigger->tgtype))
  486. {
  487. tp = &(t[TRIGGER_EVENT_DELETE]);
  488. if (*tp == NULL)
  489. *tp = (Trigger **) palloc(sizeof(Trigger *));
  490. else
  491. *tp = (Trigger **) repalloc(*tp, (n[TRIGGER_EVENT_DELETE] + 1) *
  492. sizeof(Trigger *));
  493. (*tp)[n[TRIGGER_EVENT_DELETE]] = trigger;
  494. (n[TRIGGER_EVENT_DELETE])++;
  495. }
  496. if (TRIGGER_FOR_UPDATE(trigger->tgtype))
  497. {
  498. tp = &(t[TRIGGER_EVENT_UPDATE]);
  499. if (*tp == NULL)
  500. *tp = (Trigger **) palloc(sizeof(Trigger *));
  501. else
  502. *tp = (Trigger **) repalloc(*tp, (n[TRIGGER_EVENT_UPDATE] + 1) *
  503. sizeof(Trigger *));
  504. (*tp)[n[TRIGGER_EVENT_UPDATE]] = trigger;
  505. (n[TRIGGER_EVENT_UPDATE])++;
  506. }
  507. }
  508. static HeapTuple
  509. ExecCallTriggerFunc(Trigger *trigger)
  510. {
  511. if (trigger->tgfunc.fn_addr == NULL)
  512. fmgr_info(trigger->tgfoid, &trigger->tgfunc);
  513. if (trigger->tgfunc.fn_plhandler != NULL)
  514. {
  515. return (HeapTuple) (*(trigger->tgfunc.fn_plhandler))
  516. (&trigger->tgfunc);
  517. }
  518. return (HeapTuple) ((*fmgr_faddr(&trigger->tgfunc)) ());
  519. }
  520. HeapTuple
  521. ExecBRInsertTriggers(Relation rel, HeapTuple trigtuple)
  522. {
  523. TriggerData *SaveTriggerData;
  524. int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
  525. Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_INSERT];
  526. HeapTuple newtuple = trigtuple;
  527. HeapTuple oldtuple;
  528. int i;
  529. SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
  530. SaveTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
  531. SaveTriggerData->tg_relation = rel;
  532. SaveTriggerData->tg_newtuple = NULL;
  533. for (i = 0; i < ntrigs; i++)
  534. {
  535. CurrentTriggerData = SaveTriggerData;
  536. CurrentTriggerData->tg_trigtuple = oldtuple = newtuple;
  537. CurrentTriggerData->tg_trigger = trigger[i];
  538. newtuple = ExecCallTriggerFunc(trigger[i]);
  539. if (newtuple == NULL)
  540. break;
  541. else if (oldtuple != newtuple && oldtuple != trigtuple)
  542. pfree(oldtuple);
  543. }
  544. CurrentTriggerData = NULL;
  545. pfree(SaveTriggerData);
  546. return newtuple;
  547. }
  548. void
  549. ExecARInsertTriggers(Relation rel, HeapTuple trigtuple)
  550. {
  551. TriggerData *SaveTriggerData;
  552. int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT];
  553. Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_INSERT];
  554. int i;
  555. SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
  556. SaveTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
  557. SaveTriggerData->tg_relation = rel;
  558. SaveTriggerData->tg_newtuple = NULL;
  559. for (i = 0; i < ntrigs; i++)
  560. {
  561. CurrentTriggerData = SaveTriggerData;
  562. CurrentTriggerData->tg_trigtuple = trigtuple;
  563. CurrentTriggerData->tg_trigger = trigger[i];
  564. ExecCallTriggerFunc(trigger[i]);
  565. }
  566. CurrentTriggerData = NULL;
  567. pfree(SaveTriggerData);
  568. return;
  569. }
  570. bool
  571. ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
  572. {
  573. Relation rel = estate->es_result_relation_info->ri_RelationDesc;
  574. TriggerData *SaveTriggerData;
  575. int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
  576. Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
  577. HeapTuple trigtuple;
  578. HeapTuple newtuple = NULL;
  579. TupleTableSlot *newSlot;
  580. int i;
  581. trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot);
  582. if (trigtuple == NULL)
  583. return false;
  584. SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
  585. SaveTriggerData->tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
  586. SaveTriggerData->tg_relation = rel;
  587. SaveTriggerData->tg_newtuple = NULL;
  588. for (i = 0; i < ntrigs; i++)
  589. {
  590. CurrentTriggerData = SaveTriggerData;
  591. CurrentTriggerData->tg_trigtuple = trigtuple;
  592. CurrentTriggerData->tg_trigger = trigger[i];
  593. newtuple = ExecCallTriggerFunc(trigger[i]);
  594. if (newtuple == NULL)
  595. break;
  596. if (newtuple != trigtuple)
  597. pfree(newtuple);
  598. }
  599. CurrentTriggerData = NULL;
  600. pfree(SaveTriggerData);
  601. pfree(trigtuple);
  602. return (newtuple == NULL) ? false : true;
  603. }
  604. void
  605. ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
  606. {
  607. Relation rel = estate->es_result_relation_info->ri_RelationDesc;
  608. TriggerData *SaveTriggerData;
  609. int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
  610. Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
  611. HeapTuple trigtuple;
  612. int i;
  613. trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
  614. Assert(trigtuple != NULL);
  615. SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
  616. SaveTriggerData->tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW;
  617. SaveTriggerData->tg_relation = rel;
  618. SaveTriggerData->tg_newtuple = NULL;
  619. for (i = 0; i < ntrigs; i++)
  620. {
  621. CurrentTriggerData = SaveTriggerData;
  622. CurrentTriggerData->tg_trigtuple = trigtuple;
  623. CurrentTriggerData->tg_trigger = trigger[i];
  624. ExecCallTriggerFunc(trigger[i]);
  625. }
  626. CurrentTriggerData = NULL;
  627. pfree(SaveTriggerData);
  628. pfree(trigtuple);
  629. return;
  630. }
  631. HeapTuple
  632. ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
  633. {
  634. Relation rel = estate->es_result_relation_info->ri_RelationDesc;
  635. TriggerData *SaveTriggerData;
  636. int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
  637. Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
  638. HeapTuple trigtuple;
  639. HeapTuple oldtuple;
  640. HeapTuple intuple = newtuple;
  641. TupleTableSlot *newSlot;
  642. int i;
  643. trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot);
  644. if (trigtuple == NULL)
  645. return NULL;
  646. /*
  647.  * In READ COMMITTED isolevel it's possible that newtuple was changed
  648.  * due to concurrent update.
  649.  */
  650. if (newSlot != NULL)
  651. intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot);
  652. SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
  653. SaveTriggerData->tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
  654. SaveTriggerData->tg_relation = rel;
  655. for (i = 0; i < ntrigs; i++)
  656. {
  657. CurrentTriggerData = SaveTriggerData;
  658. CurrentTriggerData->tg_trigtuple = trigtuple;
  659. CurrentTriggerData->tg_newtuple = oldtuple = newtuple;
  660. CurrentTriggerData->tg_trigger = trigger[i];
  661. newtuple = ExecCallTriggerFunc(trigger[i]);
  662. if (newtuple == NULL)
  663. break;
  664. else if (oldtuple != newtuple && oldtuple != intuple)
  665. pfree(oldtuple);
  666. }
  667. CurrentTriggerData = NULL;
  668. pfree(SaveTriggerData);
  669. pfree(trigtuple);
  670. return newtuple;
  671. }
  672. void
  673. ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
  674. {
  675. Relation rel = estate->es_result_relation_info->ri_RelationDesc;
  676. TriggerData *SaveTriggerData;
  677. int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
  678. Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
  679. HeapTuple trigtuple;
  680. int i;
  681. trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
  682. Assert(trigtuple != NULL);
  683. SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
  684. SaveTriggerData->tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW;
  685. SaveTriggerData->tg_relation = rel;
  686. for (i = 0; i < ntrigs; i++)
  687. {
  688. CurrentTriggerData = SaveTriggerData;
  689. CurrentTriggerData->tg_trigtuple = trigtuple;
  690. CurrentTriggerData->tg_newtuple = newtuple;
  691. CurrentTriggerData->tg_trigger = trigger[i];
  692. ExecCallTriggerFunc(trigger[i]);
  693. }
  694. CurrentTriggerData = NULL;
  695. pfree(SaveTriggerData);
  696. pfree(trigtuple);
  697. return;
  698. }
  699. extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
  700. static HeapTuple
  701. GetTupleForTrigger(EState *estate, ItemPointer tid, TupleTableSlot **newSlot)
  702. {
  703. Relation relation = estate->es_result_relation_info->ri_RelationDesc;
  704. HeapTupleData tuple;
  705. HeapTuple result;
  706. Buffer buffer;
  707. if (newSlot != NULL)
  708. {
  709. int test;
  710. /*
  711.  * mark tuple for update
  712.  */
  713. *newSlot = NULL;
  714. tuple.t_self = *tid;
  715. ltrmark:;
  716. test = heap_mark4update(relation, &tuple, &buffer);
  717. switch (test)
  718. {
  719. case HeapTupleSelfUpdated:
  720. ReleaseBuffer(buffer);
  721. return (NULL);
  722. case HeapTupleMayBeUpdated:
  723. break;
  724. case HeapTupleUpdated:
  725. ReleaseBuffer(buffer);
  726. if (XactIsoLevel == XACT_SERIALIZABLE)
  727. elog(ERROR, "Can't serialize access due to concurrent update");
  728. else if (!(ItemPointerEquals(&(tuple.t_self), tid)))
  729. {
  730. TupleTableSlot *epqslot = EvalPlanQual(estate,
  731.  estate->es_result_relation_info->ri_RangeTableIndex,
  732. &(tuple.t_self));
  733. if (!(TupIsNull(epqslot)))
  734. {
  735. *tid = tuple.t_self;
  736. *newSlot = epqslot;
  737. goto ltrmark;
  738. }
  739. }
  740. /*
  741.  * if tuple was deleted or PlanQual failed for updated
  742.  * tuple - we have not process this tuple!
  743.  */
  744. return (NULL);
  745. default:
  746. ReleaseBuffer(buffer);
  747. elog(ERROR, "Unknown status %u from heap_mark4update", test);
  748. return (NULL);
  749. }
  750. }
  751. else
  752. {
  753. PageHeader dp;
  754. ItemId lp;
  755. buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
  756. if (!BufferIsValid(buffer))
  757. elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
  758. dp = (PageHeader) BufferGetPage(buffer);
  759. lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
  760. Assert(ItemIdIsUsed(lp));
  761. tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
  762. tuple.t_len = ItemIdGetLength(lp);
  763. tuple.t_self = *tid;
  764. }
  765. result = heap_copytuple(&tuple);
  766. ReleaseBuffer(buffer);
  767. return result;
  768. }