Skip to content

Commit 188c7c8

Browse files
committed
Add ALTER TABLE ENABLE/DISABLE TRIGGER commands. Change pg_dump to
use these instead of its previous hack of changing pg_class.reltriggers. Documentation is lacking, will add that later. Patch by Satoshi Nagayasu, review and some extra work by Tom Lane.
1 parent d086da4 commit 188c7c8

File tree

9 files changed

+255
-56
lines changed

9 files changed

+255
-56
lines changed

src/backend/commands/tablecmds.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.168 2005/08/22 19:40:09 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.169 2005/08/23 22:40:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -246,6 +246,8 @@ static void ATExecDropCluster(Relation rel);
246246
static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
247247
char *tablespacename);
248248
static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace);
249+
static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
250+
bool enable, bool skip_system);
249251
static void copy_relation_data(Relation rel, SMgrRelation dst);
250252
static void update_ri_trigger_args(Oid relid,
251253
const char *oldname,
@@ -2005,6 +2007,17 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
20052007
ATPrepSetTableSpace(tab, rel, cmd->name);
20062008
pass = AT_PASS_MISC; /* doesn't actually matter */
20072009
break;
2010+
case AT_EnableTrig: /* ENABLE TRIGGER variants */
2011+
case AT_EnableTrigAll:
2012+
case AT_EnableTrigUser:
2013+
case AT_DisableTrig: /* DISABLE TRIGGER variants */
2014+
case AT_DisableTrigAll:
2015+
case AT_DisableTrigUser:
2016+
ATSimplePermissions(rel, false);
2017+
/* These commands never recurse */
2018+
/* No command-specific prep needed */
2019+
pass = AT_PASS_MISC;
2020+
break;
20082021
default: /* oops */
20092022
elog(ERROR, "unrecognized alter table type: %d",
20102023
(int) cmd->subtype);
@@ -2163,6 +2176,24 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
21632176
* Nothing to do here; Phase 3 does the work
21642177
*/
21652178
break;
2179+
case AT_EnableTrig: /* ENABLE TRIGGER name */
2180+
ATExecEnableDisableTrigger(rel, cmd->name, true, false);
2181+
break;
2182+
case AT_DisableTrig: /* DISABLE TRIGGER name */
2183+
ATExecEnableDisableTrigger(rel, cmd->name, false, false);
2184+
break;
2185+
case AT_EnableTrigAll: /* ENABLE TRIGGER ALL */
2186+
ATExecEnableDisableTrigger(rel, NULL, true, false);
2187+
break;
2188+
case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
2189+
ATExecEnableDisableTrigger(rel, NULL, false, false);
2190+
break;
2191+
case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
2192+
ATExecEnableDisableTrigger(rel, NULL, true, true);
2193+
break;
2194+
case AT_DisableTrigUser: /* DISABLE TRIGGER USER */
2195+
ATExecEnableDisableTrigger(rel, NULL, false, true);
2196+
break;
21662197
default: /* oops */
21672198
elog(ERROR, "unrecognized alter table type: %d",
21682199
(int) cmd->subtype);
@@ -5778,6 +5809,18 @@ copy_relation_data(Relation rel, SMgrRelation dst)
57785809
smgrimmedsync(dst);
57795810
}
57805811

5812+
/*
5813+
* ALTER TABLE ENABLE/DISABLE TRIGGER
5814+
*
5815+
* We just pass this off to trigger.c.
5816+
*/
5817+
static void
5818+
ATExecEnableDisableTrigger(Relation rel, char *trigname,
5819+
bool enable, bool skip_system)
5820+
{
5821+
EnableDisableTrigger(rel, trigname, enable, skip_system);
5822+
}
5823+
57815824
/*
57825825
* ALTER TABLE CREATE TOAST TABLE
57835826
*

src/backend/commands/trigger.c

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.192 2005/08/20 00:39:54 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.193 2005/08/23 22:40:08 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -712,6 +712,114 @@ renametrig(Oid relid,
712712
heap_close(targetrel, NoLock);
713713
}
714714

715+
716+
/*
717+
* EnableDisableTrigger()
718+
*
719+
* Called by ALTER TABLE ENABLE/DISABLE TRIGGER
720+
* to change 'tgenabled' flag for the specified trigger(s)
721+
*
722+
* rel: relation to process (caller must hold suitable lock on it)
723+
* tgname: trigger to process, or NULL to scan all triggers
724+
* enable: new value for tgenabled flag
725+
* skip_system: if true, skip "system" triggers (constraint triggers)
726+
*
727+
* Caller should have checked permissions for the table; here we also
728+
* enforce that superuser privilege is required to alter the state of
729+
* system triggers
730+
*/
731+
void
732+
EnableDisableTrigger(Relation rel, const char *tgname,
733+
bool enable, bool skip_system)
734+
{
735+
Relation tgrel;
736+
int nkeys;
737+
ScanKeyData keys[2];
738+
SysScanDesc tgscan;
739+
HeapTuple tuple;
740+
bool found;
741+
bool changed;
742+
743+
/* Scan the relevant entries in pg_triggers */
744+
tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
745+
746+
ScanKeyInit(&keys[0],
747+
Anum_pg_trigger_tgrelid,
748+
BTEqualStrategyNumber, F_OIDEQ,
749+
ObjectIdGetDatum(RelationGetRelid(rel)));
750+
if (tgname)
751+
{
752+
ScanKeyInit(&keys[1],
753+
Anum_pg_trigger_tgname,
754+
BTEqualStrategyNumber, F_NAMEEQ,
755+
CStringGetDatum(tgname));
756+
nkeys = 2;
757+
}
758+
else
759+
nkeys = 1;
760+
761+
tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
762+
SnapshotNow, nkeys, keys);
763+
764+
found = changed = false;
765+
766+
while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
767+
{
768+
Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
769+
770+
if (oldtrig->tgisconstraint)
771+
{
772+
/* system trigger ... ok to process? */
773+
if (skip_system)
774+
continue;
775+
if (!superuser())
776+
ereport(ERROR,
777+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
778+
errmsg("permission denied: \"%s\" is a system trigger",
779+
NameStr(oldtrig->tgname))));
780+
}
781+
782+
found = true;
783+
784+
if (oldtrig->tgenabled != enable)
785+
{
786+
/* need to change this one ... make a copy to scribble on */
787+
HeapTuple newtup = heap_copytuple(tuple);
788+
Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
789+
790+
newtrig->tgenabled = enable;
791+
792+
simple_heap_update(tgrel, &newtup->t_self, newtup);
793+
794+
/* Keep catalog indexes current */
795+
CatalogUpdateIndexes(tgrel, newtup);
796+
797+
heap_freetuple(newtup);
798+
799+
changed = true;
800+
}
801+
}
802+
803+
systable_endscan(tgscan);
804+
805+
heap_close(tgrel, RowExclusiveLock);
806+
807+
if (tgname && !found)
808+
ereport(ERROR,
809+
(errcode(ERRCODE_UNDEFINED_OBJECT),
810+
errmsg("trigger \"%s\" for table \"%s\" does not exist",
811+
tgname, RelationGetRelationName(rel))));
812+
813+
/*
814+
* If we changed anything, broadcast a SI inval message to force each
815+
* backend (including our own!) to rebuild relation's relcache entry.
816+
* Otherwise they will fail to apply the change promptly.
817+
*/
818+
if (changed)
819+
CacheInvalidateRelcache(rel);
820+
}
821+
822+
715823
/*
716824
* Build trigger data to attach to the given relcache entry.
717825
*

src/backend/parser/gram.y

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.507 2005/08/01 20:31:09 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.508 2005/08/23 22:40:20 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -350,9 +350,9 @@ static void doNegateFloat(Value *v);
350350

351351
DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
352352
DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS
353-
DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP
353+
DESC DISABLE_P DISTINCT DO DOMAIN_P DOUBLE_P DROP
354354

355-
EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING
355+
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING
356356
EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
357357

358358
FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
@@ -1415,6 +1415,50 @@ alter_table_cmd:
14151415
n->name = NULL;
14161416
$$ = (Node *)n;
14171417
}
1418+
/* ALTER TABLE <name> ENABLE TRIGGER <trig> */
1419+
| ENABLE_P TRIGGER name
1420+
{
1421+
AlterTableCmd *n = makeNode(AlterTableCmd);
1422+
n->subtype = AT_EnableTrig;
1423+
n->name = $3;
1424+
$$ = (Node *)n;
1425+
}
1426+
/* ALTER TABLE <name> ENABLE TRIGGER ALL */
1427+
| ENABLE_P TRIGGER ALL
1428+
{
1429+
AlterTableCmd *n = makeNode(AlterTableCmd);
1430+
n->subtype = AT_EnableTrigAll;
1431+
$$ = (Node *)n;
1432+
}
1433+
/* ALTER TABLE <name> ENABLE TRIGGER USER */
1434+
| ENABLE_P TRIGGER USER
1435+
{
1436+
AlterTableCmd *n = makeNode(AlterTableCmd);
1437+
n->subtype = AT_EnableTrigUser;
1438+
$$ = (Node *)n;
1439+
}
1440+
/* ALTER TABLE <name> DISABLE TRIGGER <trig> */
1441+
| DISABLE_P TRIGGER name
1442+
{
1443+
AlterTableCmd *n = makeNode(AlterTableCmd);
1444+
n->subtype = AT_DisableTrig;
1445+
n->name = $3;
1446+
$$ = (Node *)n;
1447+
}
1448+
/* ALTER TABLE <name> DISABLE TRIGGER ALL */
1449+
| DISABLE_P TRIGGER ALL
1450+
{
1451+
AlterTableCmd *n = makeNode(AlterTableCmd);
1452+
n->subtype = AT_DisableTrigAll;
1453+
$$ = (Node *)n;
1454+
}
1455+
/* ALTER TABLE <name> DISABLE TRIGGER USER */
1456+
| DISABLE_P TRIGGER USER
1457+
{
1458+
AlterTableCmd *n = makeNode(AlterTableCmd);
1459+
n->subtype = AT_DisableTrigUser;
1460+
$$ = (Node *)n;
1461+
}
14181462
| alter_rel_cmd
14191463
{
14201464
$$ = $1;
@@ -8067,10 +8111,12 @@ unreserved_keyword:
80678111
| DELETE_P
80688112
| DELIMITER
80698113
| DELIMITERS
8114+
| DISABLE_P
80708115
| DOMAIN_P
80718116
| DOUBLE_P
80728117
| DROP
80738118
| EACH
8119+
| ENABLE_P
80748120
| ENCODING
80758121
| ENCRYPTED
80768122
| ESCAPE

src/backend/parser/keywords.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.164 2005/07/31 17:19:18 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.165 2005/08/23 22:40:27 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -117,13 +117,15 @@ static const ScanKeyword ScanKeywords[] = {
117117
{"delimiter", DELIMITER},
118118
{"delimiters", DELIMITERS},
119119
{"desc", DESC},
120+
{"disable", DISABLE_P},
120121
{"distinct", DISTINCT},
121122
{"do", DO},
122123
{"domain", DOMAIN_P},
123124
{"double", DOUBLE_P},
124125
{"drop", DROP},
125126
{"each", EACH},
126127
{"else", ELSE},
128+
{"enable", ENABLE_P},
127129
{"encoding", ENCODING},
128130
{"encrypted", ENCRYPTED},
129131
{"end", END_P},

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy