Обсуждение: Enable/disable trigger path

Поиск
Список
Период
Сортировка

Enable/disable trigger path

От
Guillaume Lelarge
Дата:
Hi all,

Here is my first patch to support enable/disable trigger. This
functionnality is available since release 8.1 of PostgreSQL. Im' not
really happy with my code. I have some code to enable a trigger and some
code to disable it. I think it would be better to merge them since they
are pretty close. For example, I use two menus (Enable trigger and
Disable trigger). It would be better to use just one but I don't know
what to do :
 * rename the menu's title
 * use a checked menu.

Or perhaps two menus are just fine. Any advice on this ?

Also, I would like to add enable/disable all triggers but I don't know
where I should put the menu item : on the table name's contextual menu ?
on the "Triggers" contextual menu ?

Thanks for any tips on this matter.

Regards.


--
Guillaume.
<!-- http://abs.traduc.org/
     http://lfs.traduc.org/
     http://docs.postgresqlfr.org/ -->
Index: pgadmin/include/schema/pgTrigger.h
===================================================================
--- pgadmin/include/schema/pgTrigger.h    (révision 5866)
+++ pgadmin/include/schema/pgTrigger.h    (copie de travail)
@@ -57,6 +57,8 @@
     bool DropObject(wxFrame *frame, ctlTree *browser, bool cascaded);
     wxString GetSql(ctlTree *browser);
     pgObject *Refresh(ctlTree *browser, const wxTreeItemId item);
+    bool EnableTrigger();
+    bool DisableTrigger();

     bool HasStats() { return false; }
     bool HasDepends() { return true; }
Index: pgadmin/include/dlg/dlgTrigger.h
===================================================================
--- pgadmin/include/dlg/dlgTrigger.h    (révision 5866)
+++ pgadmin/include/dlg/dlgTrigger.h    (copie de travail)
@@ -39,4 +39,21 @@
 };


+class enableTriggerFactory : public contextActionFactory
+{
+public:
+    enableTriggerFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+};
+
+
+class disableTriggerFactory : public contextActionFactory
+{
+public:
+    disableTriggerFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+};
+
 #endif
Index: pgadmin/frm/frmMain.cpp
===================================================================
--- pgadmin/frm/frmMain.cpp    (révision 5866)
+++ pgadmin/frm/frmMain.cpp    (copie de travail)
@@ -63,6 +63,7 @@
 #include "dlg/dlgServer.h"
 #include "dlg/dlgDatabase.h"
 #include "dlg/dlgTable.h"
+#include "dlg/dlgTrigger.h"
 #include "dlg/dlgServer.h"
 #include "slony/dlgRepCluster.h"
 #include "slony/dlgRepSet.h"
@@ -258,6 +259,8 @@
     actionFactory *refFact=new refreshFactory(menuFactories, viewMenu, toolBar);
     new countRowsFactory(menuFactories, viewMenu, 0);
     new executePgstattupleFactory(menuFactories, viewMenu, 0);
+    new enableTriggerFactory(menuFactories, viewMenu, 0);
+    new disableTriggerFactory(menuFactories, viewMenu, 0);


     //--------------------------
Index: pgadmin/schema/pgTrigger.cpp
===================================================================
--- pgadmin/schema/pgTrigger.cpp    (révision 5866)
+++ pgadmin/schema/pgTrigger.cpp    (copie de travail)
@@ -48,6 +48,20 @@
 }


+bool pgTrigger::EnableTrigger()
+{
+    wxString sql = wxT("ALTER TABLE ") + GetQuotedFullTable() + wxT(" ENABLE TRIGGER ") + GetQuotedIdentifier();
+    return GetDatabase()->ExecuteVoid(sql);
+}
+
+
+bool pgTrigger::DisableTrigger()
+{
+    wxString sql = wxT("ALTER TABLE ") + GetQuotedFullTable() + wxT(" DISABLE TRIGGER ") + GetQuotedIdentifier();
+    return GetDatabase()->ExecuteVoid(sql);
+}
+
+
 void pgTrigger::SetDirty()
 {
     if (expandedKids)
Index: pgadmin/dlg/dlgTrigger.cpp
===================================================================
--- pgadmin/dlg/dlgTrigger.cpp    (révision 5866)
+++ pgadmin/dlg/dlgTrigger.cpp    (copie de travail)
@@ -15,6 +15,7 @@
 // App headers
 #include "pgAdmin3.h"
 #include "utils/misc.h"
+#include "frm/frmMain.h"
 #include "utils/pgDefs.h"

 #include "dlg/dlgTrigger.h"
@@ -208,3 +209,58 @@
         EnableOK(enable);
     }
 }
+
+enableTriggerFactory::enableTriggerFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("&Enable trigger"), _("Enable trigger."));
+}
+
+
+wxWindow *enableTriggerFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    if (((pgTrigger*)obj)->EnableTrigger())
+        ((pgTrigger*)obj)->iSetEnabled(true);
+
+    wxTreeItemId item=form->GetBrowser()->GetSelection();
+    {
+        obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
+        form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), form->GetToolBar());
+    }
+
+    return 0;
+}
+
+
+bool enableTriggerFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(triggerFactory) && ! ((pgTrigger*)obj)->GetEnabled()
+               && ((pgTrigger*)obj)->GetConnection()->BackendMinimumVersion(8, 1);
+}
+
+disableTriggerFactory::disableTriggerFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("&Disable trigger"), _("Disable trigger."));
+}
+
+
+wxWindow *disableTriggerFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    if (((pgTrigger*)obj)->DisableTrigger())
+        ((pgTrigger*)obj)->iSetEnabled(false);
+
+    wxTreeItemId item=form->GetBrowser()->GetSelection();
+    if (obj == form->GetBrowser()->GetObject(item))
+    {
+        obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
+        form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), form->GetToolBar());
+    }
+
+    return 0;
+}
+
+
+bool disableTriggerFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(triggerFactory) && ((pgTrigger*)obj)->GetEnabled()
+               && ((pgTrigger*)obj)->GetConnection()->BackendMinimumVersion(8, 1);
+}

Re: Enable/disable trigger path

От
Dave Page
Дата:
Guillaume Lelarge wrote:
> Hi all,
>
> Here is my first patch to support enable/disable trigger. This
> functionnality is available since release 8.1 of PostgreSQL. Im' not
> really happy with my code. I have some code to enable a trigger and some
> code to disable it. I think it would be better to merge them since they
> are pretty close. For example, I use two menus (Enable trigger and
> Disable trigger). It would be better to use just one but I don't know
> what to do :
>  * rename the menu's title
>  * use a checked menu.
>
> Or perhaps two menus are just fine. Any advice on this ?
>
> Also, I would like to add enable/disable all triggers but I don't know
> where I should put the menu item : on the table name's contextual menu ?
> on the "Triggers" contextual menu ?
>
> Thanks for any tips on this matter.

Bullet pointed tips, purely because that's how they escaped from my
brain :-)

- This should be on the Tools menu, not the View menu.

- Use a single factory, and a check/uncheck menu option. See the changes
I made to the pg_stattuple stuff as an example of a check option.

- The menu option should probably become something like 'Trigger enabled?'

- pgTrigger::Enable/DisableTrigger should manage the state of the
enabled flag themselves - you should not have to change that from the
factory.

- If Enable/Disable trigger don't work for some reason, StartDialog
should exit without doing anything else as a general rule.

Otherwise it looks OK though - certainly looks like you've got the hang
of the factories :-)

Regards, Dave.

Re: Enable/disable trigger path

От
Guillaume Lelarge
Дата:
Dave Page a écrit :
> [...]
> Bullet pointed tips, purely because that's how they escaped from my
> brain :-)
>
> - This should be on the Tools menu, not the View menu.
>

I don't understand what you mean by this. I put them on the Tools
contextual menu but I don't see a View contextual menu. Can you give me
more details ?

> - Use a single factory, and a check/uncheck menu option. See the changes
> I made to the pg_stattuple stuff as an example of a check option.
>

Done.

> - The menu option should probably become something like 'Trigger enabled?'
>

Done too.

> - pgTrigger::Enable/DisableTrigger should manage the state of the
> enabled flag themselves - you should not have to change that from the
> factory.
>

OK. I discarded pgTrigger::Enable/DisableTrigger to use
pgTrigger::iSetEnabled. Everything takes place in this method.

> - If Enable/Disable trigger don't work for some reason, StartDialog
> should exit without doing anything else as a general rule.
>

OK.

> Otherwise it looks OK though - certainly looks like you've got the hang
> of the factories :-)
>

Hehe... :)

I added some code to make use of the "ENABLE/DISABLE TRIGGER ALL" on a
table.

You'll find my new patch attached.

Regards.


--
Guillaume.
<!-- http://abs.traduc.org/
     http://lfs.traduc.org/
     http://docs.postgresqlfr.org/ -->
Index: pgadmin/include/schema/pgTable.h
===================================================================
--- pgadmin/include/schema/pgTable.h    (révision 5875)
+++ pgadmin/include/schema/pgTable.h    (copie de travail)
@@ -78,6 +78,8 @@
     void iSetHasSubclass(bool b) { hasSubclass = b; }
     void iSetIsReplicated(bool b) { isReplicated = b; }
     bool GetIsReplicated() const { return isReplicated; }
+    bool GetAllTriggersEnabled();
+    void iSetAllTriggersEnabled(const bool b);
     void UpdateRows();
     bool DropObject(wxFrame *frame, ctlTree *browser, bool cascaded);
     bool CanView() { return true; }
@@ -110,7 +112,7 @@
     void AppendStuff(wxString &sql, ctlTree *browser, pgaFactory &factory);
     wxULongLong rows;
     double estimatedRows;
-    bool hasOids, hasSubclass, rowsCounted, isReplicated, showExtendedStatistics;
+    bool hasOids, hasSubclass, rowsCounted, isReplicated, showExtendedStatistics, allTriggersEnabled;
     long inheritedTableCount;
     wxString quotedInheritedTables, inheritedTables, primaryKey, quotedPrimaryKey,
         primaryKeyName, primaryKeyColNumbers, tablespace;
Index: pgadmin/include/schema/pgTrigger.h
===================================================================
--- pgadmin/include/schema/pgTrigger.h    (révision 5875)
+++ pgadmin/include/schema/pgTrigger.h    (copie de travail)
@@ -45,7 +45,7 @@
     long GetTriggerType() const {return triggerType; }
     void iSetTriggerType(const long l) { triggerType=l; }
     bool GetEnabled() const { return enabled; }
-    void iSetEnabled(const bool b) {enabled=b; }
+    void iSetEnabled(const bool b);
     void iSetTriggerFunction(pgFunction *fkt) { triggerFunction=fkt; }
     wxString GetQuotedFullTable() const { return quotedFullTable; }
     void iSetQuotedFullTable(const wxString &s) { quotedFullTable=s; }
Index: pgadmin/include/dlg/dlgTrigger.h
===================================================================
--- pgadmin/include/dlg/dlgTrigger.h    (révision 5875)
+++ pgadmin/include/dlg/dlgTrigger.h    (copie de travail)
@@ -39,4 +39,14 @@
 };


+class enabledisableTriggerFactory : public contextActionFactory
+{
+public:
+    enabledisableTriggerFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+    bool CheckChecked(pgObject *obj);
+};
+
+
 #endif
Index: pgadmin/include/dlg/dlgTable.h
===================================================================
--- pgadmin/include/dlg/dlgTable.h    (révision 5875)
+++ pgadmin/include/dlg/dlgTable.h    (copie de travail)
@@ -92,4 +92,15 @@
     bool CheckChecked(pgObject *obj);
 };

+
+class enabledisableAllTriggersFactory : public contextActionFactory
+{
+public:
+    enabledisableAllTriggersFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar);
+    wxWindow *StartDialog(frmMain *form, pgObject *obj);
+    bool CheckEnable(pgObject *obj);
+    bool CheckChecked(pgObject *obj);
+};
+
+
 #endif
Index: pgadmin/frm/frmMain.cpp
===================================================================
--- pgadmin/frm/frmMain.cpp    (révision 5875)
+++ pgadmin/frm/frmMain.cpp    (copie de travail)
@@ -63,6 +63,7 @@
 #include "dlg/dlgServer.h"
 #include "dlg/dlgDatabase.h"
 #include "dlg/dlgTable.h"
+#include "dlg/dlgTrigger.h"
 #include "dlg/dlgServer.h"
 #include "slony/dlgRepCluster.h"
 #include "slony/dlgRepSet.h"
@@ -258,8 +259,10 @@
     actionFactory *refFact=new refreshFactory(menuFactories, viewMenu, toolBar);
     new countRowsFactory(menuFactories, viewMenu, 0);
     new executePgstattupleFactory(menuFactories, viewMenu, 0);
+    new enabledisableTriggerFactory(menuFactories, viewMenu, 0);
+    new enabledisableAllTriggersFactory(menuFactories, viewMenu, 0);

-
+
     //--------------------------
     new separatorFactory(menuFactories);

Index: pgadmin/schema/pgTable.cpp
===================================================================
--- pgadmin/schema/pgTable.cpp    (révision 5875)
+++ pgadmin/schema/pgTable.cpp    (copie de travail)
@@ -408,6 +408,30 @@
 }


+void pgTable::iSetAllTriggersEnabled(const bool b)
+{
+    if (((allTriggersEnabled && !b) || (!allTriggersEnabled && b)))
+    {
+        wxString sql = wxT("ALTER TABLE ") + GetQuotedFullIdentifier() + wxT(" ");
+        if (allTriggersEnabled && !b)
+            sql += wxT("DISABLE");
+        else if (!allTriggersEnabled && b)
+            sql += wxT("ENABLE");
+        sql += wxT(" TRIGGER ALL");
+printf((sql + wxT("\n")).ToAscii());
+        GetDatabase()->ExecuteVoid(sql);
+    }
+
+    allTriggersEnabled=b;
+}
+
+
+bool pgTable::GetAllTriggersEnabled()
+{
+    return allTriggersEnabled;
+}
+
+
 void pgTable::UpdateRows()
 {
     pgSet *props = ExecuteSet(wxT("SELECT count(*) AS rows FROM ONLY ") + GetQuotedFullIdentifier());
Index: pgadmin/schema/pgTrigger.cpp
===================================================================
--- pgadmin/schema/pgTrigger.cpp    (révision 5875)
+++ pgadmin/schema/pgTrigger.cpp    (copie de travail)
@@ -48,6 +48,23 @@
 }


+void pgTrigger::iSetEnabled(const bool b)
+{
+    if (GetQuotedFullTable().Len() > 0 && ((enabled && !b) || (!enabled && b)))
+    {
+        wxString sql = wxT("ALTER TABLE ") + GetQuotedFullTable() + wxT(" ");
+        if (enabled && !b)
+            sql += wxT("DISABLE");
+        else if (!enabled && b)
+            sql += wxT("ENABLE");
+        sql += wxT(" TRIGGER ") + GetQuotedIdentifier();
+        GetDatabase()->ExecuteVoid(sql);
+    }
+
+    enabled=b;
+}
+
+
 void pgTrigger::SetDirty()
 {
     if (expandedKids)
Index: pgadmin/dlg/dlgTable.cpp
===================================================================
--- pgadmin/dlg/dlgTable.cpp    (révision 5875)
+++ pgadmin/dlg/dlgTable.cpp    (copie de travail)
@@ -1205,4 +1205,34 @@
 bool executePgstattupleFactory::CheckChecked(pgObject *obj)
 {
     return obj && ((pgTable*)obj)->GetShowExtendedStatistics();
-}
\ Pas de fin de ligne à la fin du fichier
+}
+
+enabledisableAllTriggersFactory::enabledisableAllTriggersFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar
*toolbar): contextActionFactory(list) 
+{
+    mnu->Append(id, _("All table's triggers enabled?"), _("Enable or disable all triggers on selected table."),
wxITEM_CHECK);
+}
+
+
+wxWindow *enabledisableAllTriggersFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    ((pgTable*)obj)->iSetAllTriggersEnabled(!((pgTable*)obj)->GetAllTriggersEnabled());
+
+    wxTreeItemId item=form->GetBrowser()->GetSelection();
+    if (obj == form->GetBrowser()->GetObject(item))
+        obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
+    form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), form->GetToolBar());
+
+    return 0;
+}
+
+
+bool enabledisableAllTriggersFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(tableFactory)
+               && ((pgTable*)obj)->GetConnection()->BackendMinimumVersion(8, 1);
+}
+
+bool enabledisableAllTriggersFactory::CheckChecked(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(tableFactory) && ((pgTable*)obj)->GetAllTriggersEnabled();
+}
Index: pgadmin/dlg/dlgTrigger.cpp
===================================================================
--- pgadmin/dlg/dlgTrigger.cpp    (révision 5875)
+++ pgadmin/dlg/dlgTrigger.cpp    (copie de travail)
@@ -15,6 +15,7 @@
 // App headers
 #include "pgAdmin3.h"
 #include "utils/misc.h"
+#include "frm/frmMain.h"
 #include "utils/pgDefs.h"

 #include "dlg/dlgTrigger.h"
@@ -208,3 +209,34 @@
         EnableOK(enable);
     }
 }
+
+
+enabledisableTriggerFactory::enabledisableTriggerFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) :
contextActionFactory(list)
+{
+    mnu->Append(id, _("Trigger enabled?"), _("Enable or disable selected trigger."), wxITEM_CHECK);
+}
+
+
+wxWindow *enabledisableTriggerFactory::StartDialog(frmMain *form, pgObject *obj)
+{
+    ((pgTrigger*)obj)->iSetEnabled(!((pgTrigger*)obj)->GetEnabled());
+
+    wxTreeItemId item=form->GetBrowser()->GetSelection();
+    if (obj == form->GetBrowser()->GetObject(item))
+        obj->ShowTreeDetail(form->GetBrowser(), 0, form->GetProperties());
+    form->GetMenuFactories()->CheckMenu(obj, form->GetMenuBar(), form->GetToolBar());
+
+    return 0;
+}
+
+
+bool enabledisableTriggerFactory::CheckEnable(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(triggerFactory)
+               && ((pgTrigger*)obj)->GetConnection()->BackendMinimumVersion(8, 1);
+}
+
+bool enabledisableTriggerFactory::CheckChecked(pgObject *obj)
+{
+    return obj && obj->IsCreatedBy(triggerFactory) && ((pgTrigger*)obj)->GetEnabled();
+}

Re: Enable/disable trigger path

От
Dave Page
Дата:
OK, nearly there... :-)

Guillaume Lelarge wrote:
> Dave Page a écrit :
>> [...]
>> Bullet pointed tips, purely because that's how they escaped from my
>> brain :-)
>>
>> - This should be on the Tools menu, not the View menu.
>>
>
> I don't understand what you mean by this. I put them on the Tools
> contextual menu but I don't see a View contextual menu. Can you give me
> more details ?

You had:

+    new enabledisableTriggerFactory(menuFactories, viewMenu, 0);
+    new enabledisableAllTriggersFactory(menuFactories, viewMenu, 0);

but that should be

+    new enabledisableTriggerFactory(menuFactories, toolsMenu, 0);
+    new enabledisableAllTriggersFactory(menuFactories, toolsMenu, 0);

Enabling/disabling triggers is something you do, not something you look at.

Anyhoo, I've applied a modifed version of the patch:

- Added a heap of refatoring to move actionFactories to live with the
objects they ac on, rather than the object's properties dialog.

- Changed enable/disable all to two factories. This is because we cannot
easily track the state of all triggers, and we definitely cannot
represent all enabled/some enabled/none enabled with a check menu item.
We now have enable all and disable all options, with no attempt to track
status.

- Recursively reset the enabled flag of the trigger objects under a
table after enabling/disabling them all.

Thanks, Dave