Re: enable/disable trigger (Re: Fwd: [HACKERS] Open items)

Поиск
Список
Период
Сортировка
От Satoshi Nagayasu
Тема Re: enable/disable trigger (Re: Fwd: [HACKERS] Open items)
Дата
Msg-id 43015202.50903@nttdata.co.jp
обсуждение исходный текст
Ответ на Re: enable/disable trigger (Re: Fwd: [HACKERS] Open items)  (Satoshi Nagayasu <nagayasus@nttdata.co.jp>)
Ответы Re: enable/disable trigger (Re: Fwd: [HACKERS] Open items)  (Bruce Momjian <pgman@candle.pha.pa.us>)
Список pgsql-patches
The message format for elog() report is cleaned up.

--
NAGAYASU Satoshi <nagayasus@nttdata.co.jp>
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 <name> ENABLE TRIGGER <trig> */
+             | ENABLE TRIGGER name
+                 {
+                     AlterTableCmd *n = makeNode(AlterTableCmd);
+                     n->subtype = AT_EnableTrig;
+                     n->name = $3;
+                     $$ = (Node *)n;
+                 }
+             /* ALTER TABLE <name> ENABLE TRIGGER ALL */
+             | ENABLE TRIGGER ALL
+                 {
+                     AlterTableCmd *n = makeNode(AlterTableCmd);
+                     n->subtype = AT_EnableTrig;
+                     n->name = pstrdup("*");
+                     $$ = (Node *)n;
+                 }
+             /* ALTER TABLE <name> DISABLE TRIGGER <trig> */
+             | DISABLE TRIGGER name
+                 {
+                     AlterTableCmd *n = makeNode(AlterTableCmd);
+                     n->subtype = AT_DisableTrig;
+                     n->name = $3;
+                     $$ = (Node *)n;
+                 }
+             /* ALTER TABLE <name> 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;


В списке pgsql-patches по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: [HACKERS] pg_stat_file() and length/size
Следующее
От: "Solange"
Дата:
Сообщение: PostgreSQL 8.0.3 and Ipv6