diff -cr pgsql.orig/src/backend/commands/tablecmds.c pgsql/src/backend/commands/tablecmds.c *** pgsql.orig/src/backend/commands/tablecmds.c 2005-06-28 14:08:54.000000000 +0900 --- pgsql/src/backend/commands/tablecmds.c 2005-08-08 13:46:44.000000000 +0900 *************** *** 236,241 **** --- 236,243 ---- Oid newOwnerId); static void ATExecClusterOn(Relation rel, const char *indexName); static void ATExecDropCluster(Relation rel); + static void ATExecEnableDisableTrigger(Relation rel, char *trigname, + bool enable); static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename); static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace); *************** *** 1993,1998 **** --- 1995,2005 ---- } pass = AT_PASS_DROP; break; + case AT_EnableTrig: /* ENABLE TRIGGER */ + case AT_DisableTrig: /* DISABLE TRIGGER */ + ATSimplePermissions(rel, false); + pass = AT_PASS_MISC; + break; case AT_SetTableSpace: /* SET TABLESPACE */ /* This command never recurses */ ATPrepSetTableSpace(tab, rel, cmd->name); *************** *** 2155,2160 **** --- 2162,2173 ---- * Nothing to do here; Phase 3 does the work */ break; + case AT_EnableTrig: /* ENABLE TRIGGER */ + ATExecEnableDisableTrigger(rel, cmd->name, true); + break; + case AT_DisableTrig: /* DISABLE TRIGGER */ + ATExecEnableDisableTrigger(rel, cmd->name, false); + break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); *************** *** 5465,5470 **** --- 5478,5492 ---- } /* + * ALTER TABLE ENABLE/DISABLE TRIGGER + */ + static void + ATExecEnableDisableTrigger(Relation rel, char *trigname, bool enable) + { + EnableDisableTrigger(rel, trigname, enable); + } + + /* * ALTER TABLE SET TABLESPACE */ static void diff -cr pgsql.orig/src/backend/commands/trigger.c pgsql/src/backend/commands/trigger.c *** pgsql.orig/src/backend/commands/trigger.c 2005-05-30 16:20:58.000000000 +0900 --- pgsql/src/backend/commands/trigger.c 2005-08-16 11:23:47.000000000 +0900 *************** *** 3063,3065 **** --- 3063,3174 ---- afterTriggerAddEvent(new_event); } } + + /* ---------- + * EnableDisableTrigger() + * + * Called by ALTER TABLE ENABLE/DISABLE TRIGGER + * to change 'tgenabled' flag in the pg_trigger. + * ---------- + */ + void + EnableDisableTrigger(Relation rel, const char *tgname, bool enable) + { + Relation tgrel; + SysScanDesc tgscan; + ScanKeyData keys[2]; + HeapTuple tuple; + int nkeys; + int changed; + + /* Permissions checks */ + if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, + RelationGetRelationName(rel)); + + if (!allowSystemTableMods && IsSystemRelation(rel)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied: \"%s\" is a system catalog", + RelationGetRelationName(rel)))); + + tgrel = heap_open(TriggerRelationId, RowExclusiveLock); + + nkeys = 2; + changed = 0; + if ( strcmp(tgname, "*")==0 ) + { + if ( !superuser() ) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("ENABLE/DISABLE TRIGGER ALL is allowed superuser only."))); + + nkeys = 1; + } + + ScanKeyInit(&keys[0], + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(rel))); + ScanKeyInit(&keys[1], + Anum_pg_trigger_tgname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(tgname)); + + tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, + SnapshotNow, nkeys, keys); + + while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) + { + HeapTuple newtup = heap_copytuple(tuple); + Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(newtup); + + if ( pg_trigger->tgenabled != enable ) + { + if ( !superuser() && pg_trigger->tgisconstraint ) + { + elog(NOTICE, "Constraint trigger can be enabled/disabled " + "only by superuser."); + continue; + } + + pg_trigger->tgenabled = enable; + + simple_heap_update(tgrel, &newtup->t_self, newtup); + + /* Keep catalog indexes current */ + CatalogUpdateIndexes(tgrel, newtup); + + changed++; + } + + heap_freetuple(newtup); + } + systable_endscan(tgscan); + + heap_close(tgrel, RowExclusiveLock); + + CommandCounterIncrement(); + + FreeTriggerDesc(rel->trigdesc); + RelationBuildTriggers(rel); + + if ( enable ) + { + if ( changed==1 ) + elog(NOTICE, "One trigger on %s is enabled.", + NameStr(rel->rd_rel->relname)); + else if ( changed>1 ) + elog(NOTICE, "%d triggers on %s are enabled.", + changed, NameStr(rel->rd_rel->relname)); + } + else + { + if ( changed==1 ) + elog(NOTICE, "One trigger on %s is disabled.", + NameStr(rel->rd_rel->relname)); + else if ( changed>1 ) + elog(NOTICE, "%d triggers on %s are disabled.", + changed, NameStr(rel->rd_rel->relname)); + } + } diff -cr pgsql.orig/src/backend/parser/gram.y pgsql/src/backend/parser/gram.y *** pgsql.orig/src/backend/parser/gram.y 2005-06-30 05:34:13.000000000 +0900 --- pgsql/src/backend/parser/gram.y 2005-08-08 13:46:44.000000000 +0900 *************** *** 348,356 **** DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS ! DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP ! EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD --- 348,356 ---- DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS ! DESC DISABLE DISTINCT DO DOMAIN_P DOUBLE_P DROP ! EACH ELSE ENABLE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD *************** *** 1389,1394 **** --- 1389,1426 ---- n->name = NULL; $$ = (Node *)n; } + /* ALTER TABLE ENABLE TRIGGER */ + | ENABLE TRIGGER name + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_EnableTrig; + n->name = $3; + $$ = (Node *)n; + } + /* ALTER TABLE ENABLE TRIGGER ALL */ + | ENABLE TRIGGER ALL + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_EnableTrig; + n->name = pstrdup("*"); + $$ = (Node *)n; + } + /* ALTER TABLE DISABLE TRIGGER */ + | DISABLE TRIGGER name + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DisableTrig; + n->name = $3; + $$ = (Node *)n; + } + /* ALTER TABLE DISABLE TRIGGER ALL */ + | DISABLE TRIGGER ALL + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DisableTrig; + n->name = pstrdup("*"); + $$ = (Node *)n; + } | alter_rel_cmd { $$ = $1; *************** *** 7960,7969 **** --- 7992,8003 ---- | DELETE_P | DELIMITER | DELIMITERS + | DISABLE | DOMAIN_P | DOUBLE_P | DROP | EACH + | ENABLE | ENCODING | ENCRYPTED | ESCAPE diff -cr pgsql.orig/src/backend/parser/keywords.c pgsql/src/backend/parser/keywords.c *** pgsql.orig/src/backend/parser/keywords.c 2005-06-30 05:34:14.000000000 +0900 --- pgsql/src/backend/parser/keywords.c 2005-08-08 13:46:44.000000000 +0900 *************** *** 116,121 **** --- 116,122 ---- {"delimiter", DELIMITER}, {"delimiters", DELIMITERS}, {"desc", DESC}, + {"disable", DISABLE}, {"distinct", DISTINCT}, {"do", DO}, {"domain", DOMAIN_P}, *************** *** 123,128 **** --- 124,130 ---- {"drop", DROP}, {"each", EACH}, {"else", ELSE}, + {"enable", ENABLE}, {"encoding", ENCODING}, {"encrypted", ENCRYPTED}, {"end", END_P}, diff -cr pgsql.orig/src/bin/pg_dump/pg_dump.c pgsql/src/bin/pg_dump/pg_dump.c *** pgsql.orig/src/bin/pg_dump/pg_dump.c 2005-06-30 12:02:56.000000000 +0900 --- pgsql/src/bin/pg_dump/pg_dump.c 2005-08-08 13:46:44.000000000 +0900 *************** *** 3273,3278 **** --- 3273,3279 ---- i_tgtype, i_tgnargs, i_tgargs, + i_tgenabled, i_tgisconstraint, i_tgconstrname, i_tgconstrrelid, *************** *** 3308,3314 **** appendPQExpBuffer(query, "SELECT tgname, " "tgfoid::pg_catalog.regproc as tgfname, " ! "tgtype, tgnargs, tgargs, " "tgisconstraint, tgconstrname, tgdeferrable, " "tgconstrrelid, tginitdeferred, tableoid, oid, " "tgconstrrelid::pg_catalog.regclass as tgconstrrelname " --- 3309,3315 ---- appendPQExpBuffer(query, "SELECT tgname, " "tgfoid::pg_catalog.regproc as tgfname, " ! "tgtype, tgnargs, tgargs, tgenabled, " "tgisconstraint, tgconstrname, tgdeferrable, " "tgconstrrelid, tginitdeferred, tableoid, oid, " "tgconstrrelid::pg_catalog.regclass as tgconstrrelname " *************** *** 3372,3377 **** --- 3373,3379 ---- i_tgtype = PQfnumber(res, "tgtype"); i_tgnargs = PQfnumber(res, "tgnargs"); i_tgargs = PQfnumber(res, "tgargs"); + i_tgenabled = PQfnumber(res, "tgenabled"); i_tgisconstraint = PQfnumber(res, "tgisconstraint"); i_tgconstrname = PQfnumber(res, "tgconstrname"); i_tgconstrrelid = PQfnumber(res, "tgconstrrelid"); *************** *** 3394,3399 **** --- 3396,3402 ---- tginfo[j].tgtype = atoi(PQgetvalue(res, j, i_tgtype)); tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs)); tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs)); + tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled)) == 't'; tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't'; tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't'; tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't'; *************** *** 7804,7809 **** --- 7807,7820 ---- } appendPQExpBuffer(query, ");\n"); + if ( !tginfo->tgenabled ) + { + appendPQExpBuffer(query, "\n"); + appendPQExpBuffer(query, "ALTER TABLE %s DISABLE TRIGGER %s;\n", + tbinfo->dobj.name, + tginfo->dobj.name); + } + ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId, tginfo->dobj.name, tbinfo->dobj.namespace->dobj.name, diff -cr pgsql.orig/src/bin/pg_dump/pg_dump.h pgsql/src/bin/pg_dump/pg_dump.h *** pgsql.orig/src/bin/pg_dump/pg_dump.h 2005-06-30 12:03:02.000000000 +0900 --- pgsql/src/bin/pg_dump/pg_dump.h 2005-08-08 13:46:44.000000000 +0900 *************** *** 263,268 **** --- 263,269 ---- TableInfo *tgtable; /* link to table the trigger is for */ char *tgfname; int tgtype; + bool tgenabled; int tgnargs; char *tgargs; bool tgisconstraint; diff -cr pgsql.orig/src/include/commands/trigger.h pgsql/src/include/commands/trigger.h *** pgsql.orig/src/include/commands/trigger.h 2005-05-30 16:20:58.000000000 +0900 --- pgsql/src/include/commands/trigger.h 2005-08-16 11:24:07.000000000 +0900 *************** *** 164,169 **** --- 164,172 ---- extern void AfterTriggerSetState(ConstraintsSetStmt *stmt); + extern void EnableDisableTrigger(Relation rel, + const char *tgname, + bool enable); /* * in utils/adt/ri_triggers.c diff -cr pgsql.orig/src/include/nodes/parsenodes.h pgsql/src/include/nodes/parsenodes.h *** pgsql.orig/src/include/nodes/parsenodes.h 2005-06-29 04:51:24.000000000 +0900 --- pgsql/src/include/nodes/parsenodes.h 2005-08-08 13:46:44.000000000 +0900 *************** *** 822,827 **** --- 822,829 ---- AT_ClusterOn, /* CLUSTER ON */ AT_DropCluster, /* SET WITHOUT CLUSTER */ AT_DropOids, /* SET WITHOUT OIDS */ + AT_EnableTrig, /* ENABLE TRIGGER */ + AT_DisableTrig, /* DISABLE TRIGGER */ AT_SetTableSpace /* SET TABLESPACE */ } AlterTableType;