Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)