Hi,

It was much easier than I previously thought. This patch adds a Triggers
node in the each view object node if you're connected to a 9.1
PostgreSQL server. You can add and see triggers on views.

It's not ready to be commited. I still have a bug to fix. I tried since
two days, and I can't make it work. My issue is with the Triggers node.
I should have the "Create a new object..." button enabled in the toolbar
and a "New trigger" (or whatever it's labelled) item in the contextual
menu. But I don't have them. I really don't understand why. View objects
seem to be treated differently than others but, despite many tests, I
can't make it work.

You can still test the patch because you have the capacity to create a
trigger on a view with a contextual menu available on the view object node.

If someone has a pointer to help me fix this patch, I would really
appreciate it.


-- 
Guillaume
 http://www.postgresql.fr
 http://dalibo.com
>From 6faa81d364f44f15bc0f63936c767e0f5ac42d52 Mon Sep 17 00:00:00 2001
From: Guillaume Lelarge <[email protected]>
Date: Fri, 22 Oct 2010 17:15:44 -0700
Subject: [PATCH] New kind of trigger: INSTEAD OF

This patch adds support to INSTEAD OF triggers. This is part of the 9.1
PostgreSQL release. It's only available for views.

Implements #256.
---
 pgadmin/dlg/dlgTrigger.cpp         |   26 +++++++++++++++++---------
 pgadmin/include/schema/pgTrigger.h |    1 +
 pgadmin/include/schema/pgView.h    |    1 +
 pgadmin/include/utils/pgDefs.h     |    1 +
 pgadmin/schema/pgTrigger.cpp       |   13 +++++++++++--
 pgadmin/schema/pgView.cpp          |    8 +++++++-
 pgadmin/ui/dlgTrigger.xrc          |    1 +
 7 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/pgadmin/dlg/dlgTrigger.cpp b/pgadmin/dlg/dlgTrigger.cpp
index 3661d5b..65e89f4 100644
--- a/pgadmin/dlg/dlgTrigger.cpp
+++ b/pgadmin/dlg/dlgTrigger.cpp
@@ -66,14 +66,13 @@ dlgProperty *pgTriggerFactory::CreateDialog(frmMain *frame, pgObject *node, pgOb
 }
 
 
-
-
 dlgTrigger::dlgTrigger(pgaFactory *f, frmMain *frame, pgTrigger *node, pgTable *parentNode)
 : dlgCollistProperty(f, frame, wxT("dlgTrigger"), parentNode)
 {
     trigger=node;
     table=parentNode;
-    wxASSERT(!table || table->GetMetaType() == PGM_TABLE || table->GetMetaType() == GP_PARTITION);
+    wxASSERT(!table || table->GetMetaType() == PGM_TABLE || table->GetMetaType() == PGM_VIEW
+        || table->GetMetaType() == GP_PARTITION);
 
     bool bVal;
     settings->Read(wxT("frmQuery/ShowLineNumber"), &bVal, false);
@@ -120,7 +119,12 @@ int dlgTrigger::Go(bool modal)
         chkUpdate->SetValue((trigger->GetTriggerType() & TRIGGER_TYPE_UPDATE) != 0);
         chkDelete->SetValue((trigger->GetTriggerType() & TRIGGER_TYPE_DELETE) != 0);
 		chkTruncate->SetValue((trigger->GetTriggerType() & TRIGGER_TYPE_TRUNCATE) != 0);
-        rdbFires->SetSelection(trigger->GetTriggerType() & TRIGGER_TYPE_BEFORE ? 0 : 1);
+        if (trigger->GetTriggerType() & TRIGGER_TYPE_BEFORE)
+            rdbFires->SetSelection(0);
+        else if (trigger->GetTriggerType() & TRIGGER_TYPE_INSTEAD)
+            rdbFires->SetSelection(2);
+        else
+            rdbFires->SetSelection(1);
         txtArguments->SetValue(trigger->GetArguments());
         txtWhen->SetValue(trigger->GetWhen());
         if (!connection->BackendMinimumVersion(7, 4))
@@ -196,6 +200,8 @@ int dlgTrigger::Go(bool modal)
 		if (!connection->BackendMinimumVersion(8, 4))
 			chkTruncate->Disable();
 
+		if (!connection->BackendMinimumVersion(9, 1) || table->GetMetaType() != PGM_VIEW)
+			rdbFires->Enable(2, false);
     }
 
     cbColumns->Disable();
@@ -259,15 +265,17 @@ wxString dlgTrigger::GetSql()
         chkUpdate->GetValue() != (trigger->GetTriggerType() & TRIGGER_TYPE_UPDATE ? true : false) ||
         chkDelete->GetValue() != (trigger->GetTriggerType() & TRIGGER_TYPE_DELETE ? true : false) ||
 		chkTruncate->GetValue() != (trigger->GetTriggerType() & TRIGGER_TYPE_TRUNCATE ? true : false) ||
-        rdbFires->GetSelection() != (trigger->GetTriggerType() & TRIGGER_TYPE_BEFORE ? 0 : 1))
+        rdbFires->GetSelection() != (trigger->GetTriggerType() & TRIGGER_TYPE_BEFORE ? 0 : TRIGGER_TYPE_INSTEAD ? 2 : 1))
     {
         if (cbFunction->GetValue() == wxString::Format(wxT("<%s>"), _("Inline EDB-SPL")))
             sql += wxT("CREATE OR REPLACE TRIGGER ") + qtIdent(name);
         else
             sql += wxT("CREATE TRIGGER ") + qtIdent(name);
 
-        if (rdbFires->GetSelection())
+        if (rdbFires->GetSelection() == 1)
             sql += wxT(" AFTER");
+        else if (rdbFires->GetSelection() == 2)
+            sql += wxT(" INSTEAD OF");
         else
             sql += wxT(" BEFORE");
         int actionCount=0;
@@ -400,14 +408,14 @@ void dlgTrigger::CheckChange()
     wxString name=GetName();
 
 	// We can only have per-statement TRUNCATE triggers
-	if (connection->BackendMinimumVersion(8, 4))
+	if (trigger || connection->BackendMinimumVersion(8, 4))
 	{
 		if (chkRow->GetValue())
 		{
 			chkTruncate->Disable();
 			chkTruncate->SetValue(false);
 		}
-		else
+		else if (connection->EdbMinimumVersion(8,0))
 			chkTruncate->Enable();
 	}
 
@@ -432,7 +440,7 @@ void dlgTrigger::CheckChange()
                  chkUpdate->GetValue() != (trigger->GetTriggerType() & TRIGGER_TYPE_UPDATE ? true : false) ||
                  chkDelete->GetValue() != (trigger->GetTriggerType() & TRIGGER_TYPE_DELETE ? true : false) ||
 				 chkTruncate->GetValue() != (trigger->GetTriggerType() & TRIGGER_TYPE_TRUNCATE ? true : false) ||
-                 rdbFires->GetSelection() != (trigger->GetTriggerType() & TRIGGER_TYPE_BEFORE ? 0 : 1)));
+                 rdbFires->GetSelection() != (trigger->GetTriggerType() & TRIGGER_TYPE_BEFORE ? 0 : (trigger->GetTriggerType() & TRIGGER_TYPE_INSTEAD ? 2 : 1))));
     }
     else
     {
diff --git a/pgadmin/include/schema/pgTrigger.h b/pgadmin/include/schema/pgTrigger.h
index 8e6c9b5..0637056 100644
--- a/pgadmin/include/schema/pgTrigger.h
+++ b/pgadmin/include/schema/pgTrigger.h
@@ -64,6 +64,7 @@ public:
 	wxArrayString GetColumnList() const { return columnList; }
     long GetColumnCount() const { return columnCount; }
     void iSetColumnCount(const long l) { columnCount=l; }
+    bool GetParentIsTable() { return table && table->GetMetaType() == PGM_TABLE; }
 
     void SetDirty();
 
diff --git a/pgadmin/include/schema/pgView.h b/pgadmin/include/schema/pgView.h
index 0863374..9704a7d 100644
--- a/pgadmin/include/schema/pgView.h
+++ b/pgadmin/include/schema/pgView.h
@@ -37,6 +37,7 @@ public:
     bool CanDropCascaded() { return !GetSystemObject() && pgSchemaObject::CanDrop(); }
 
     bool DropObject(wxFrame *frame, ctlTree *browser, bool cascaded);
+    bool CanCreate() { return GetSchema()->CanCreate(); }
     bool CanView() { return true; }
     bool WantDummyChild() { return true; }
 
diff --git a/pgadmin/include/utils/pgDefs.h b/pgadmin/include/utils/pgDefs.h
index bd55d06..f26d4c5 100644
--- a/pgadmin/include/utils/pgDefs.h
+++ b/pgadmin/include/utils/pgDefs.h
@@ -71,5 +71,6 @@
 #define TRIGGER_TYPE_DELETE				(1 << 3)
 #define TRIGGER_TYPE_UPDATE				(1 << 4)
 #define TRIGGER_TYPE_TRUNCATE			(1 << 5)
+#define TRIGGER_TYPE_INSTEAD			(1 << 6)
 
 #endif
diff --git a/pgadmin/schema/pgTrigger.cpp b/pgadmin/schema/pgTrigger.cpp
index 222e248..5a24af8 100644
--- a/pgadmin/schema/pgTrigger.cpp
+++ b/pgadmin/schema/pgTrigger.cpp
@@ -195,7 +195,15 @@ wxString pgTrigger::GetSql(ctlTree *browser)
 
 wxString pgTrigger::GetFireWhen() const 
 {
-    return (triggerType & TRIGGER_TYPE_BEFORE) ? wxT("BEFORE") : wxT("AFTER");
+    wxString when = wxEmptyString;
+
+    if (triggerType & TRIGGER_TYPE_BEFORE)
+        when = wxT("BEFORE");
+    else if (triggerType & TRIGGER_TYPE_INSTEAD)
+        when = wxT("INSTEAD OF");
+    else
+        when = wxT("AFTER");
+    return when;
 }
 
 
@@ -503,7 +511,8 @@ wxWindow *enabledisableTriggerFactory::StartDialog(frmMain *form, pgObject *obj)
 bool enabledisableTriggerFactory::CheckEnable(pgObject *obj)
 {
     return obj && obj->IsCreatedBy(triggerFactory) && obj->CanEdit()
-               && ((pgTrigger*)obj)->GetConnection()->BackendMinimumVersion(8, 1);
+               && ((pgTrigger*)obj)->GetConnection()->BackendMinimumVersion(8, 1)
+               && ((pgTrigger*)obj)->GetParentIsTable();
 }
 
 bool enabledisableTriggerFactory::CheckChecked(pgObject *obj)
diff --git a/pgadmin/schema/pgView.cpp b/pgadmin/schema/pgView.cpp
index f97466f..33272f2 100644
--- a/pgadmin/schema/pgView.cpp
+++ b/pgadmin/schema/pgView.cpp
@@ -18,6 +18,7 @@
 #include "schema/pgColumn.h"
 #include "schema/pgView.h"
 #include "frm/frmHint.h"
+#include "schema/pgTrigger.h"
 
 
 pgView::pgView(pgSchema *newSchema, const wxString& newName)
@@ -107,8 +108,10 @@ wxMenu *pgView::GetNewMenu()
 {
     wxMenu *menu=pgObject::GetNewMenu();
     if (schema->GetCreatePrivilege())
+    {
         ruleFactory.AppendMenu(menu);
-
+        triggerFactory.AppendMenu(menu);
+    }
     return menu;
 }
 
@@ -172,6 +175,7 @@ wxString pgView::GetSql(ctlTree *browser)
         }
 
         AppendStuff(sql, browser, ruleFactory);
+        AppendStuff(sql, browser, triggerFactory);
     }
     return sql;
 }
@@ -280,6 +284,8 @@ void pgView::ShowTreeDetail(ctlTree *browser, frmMain *form, ctlListView *proper
 				hasDeleteRule = true;
 		}
 
+        if (GetConnection()->BackendMinimumVersion(9, 1))
+		    browser->AppendCollection(this, triggerFactory);
     }
     if (properties)
     {
diff --git a/pgadmin/ui/dlgTrigger.xrc b/pgadmin/ui/dlgTrigger.xrc
index 7af64e9..091803c 100644
--- a/pgadmin/ui/dlgTrigger.xrc
+++ b/pgadmin/ui/dlgTrigger.xrc
@@ -104,6 +104,7 @@
                     <content>
                       <item>BEFORE</item>
                       <item>AFTER</item>
+                      <item>INSTEAD OF</item>
                     </content>
                     <selection>0</selection>
                     <dimension>1</dimension>
-- 
1.7.1

-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to