Le 24/10/2010 00:18, Dave Page a écrit :
> [Ashesh, if you haven't aready, I suggest reviewing this thread. It
> may shed some light on that Rule weirdness on Solaris]
>
> On Sat, Oct 23, 2010 at 11:03 PM, Guillaume Lelarge
> <[email protected]> wrote:
>>> pgView derives from pgSchemaObject
>>
>> Actually, pgView derives from pgRuleObject, which is already weird by
>> itself but makes the whole thing even more weird.
>
> Oh, I misread that. pgView*Factory* derives from pgSchemaObj*Factory*.
> Which seems bizarre.
>
>>> pgColumn derives from pgTableObject
>>
>> Seems logical.
>>
>>> and:
>>>
>>> pgRule derives from pgRuleObject
>>> pgRuleObject derives from pgSchemaObject
>>
>> Which just doesn't make sense. I would really like to know the reason of
>> all this.
>
> I think the point is, that pgRule can't be a descendent of a table or
> a view (in the inheritance hierarchy), because it is a descendent of
> both (logically).
>
>>> My guess is to do this properly you'll probably have to create a
>>> similar pgTriggerObject class (or make pgRuleObject into a more
>>> generic pgRelationObject), and then add properties to represent the
>>> table/view directly to pgTrigger and re-parent it appropriately.
>>
>> Will look into this.
>>
>> Thanks for your remarks. I hope to come up with something. We'll
>> probably need someone more knowledgable than me with C++.
>
> I don't think it needs "more C++ knowledge", just some patience to
> untangle things. Do you know of any tools that can automatically
> visually display the object model and members? I'm sure there used to
> be something in Visual Studio, but I can't find it atm.
>
Some patience, yeah, I did use that :)
New patch attached. Works good for me.
--
Guillaume
http://www.postgresql.fr
http://dalibo.com
diff --git a/pgadmin/dlg/dlgProperty.cpp b/pgadmin/dlg/dlgProperty.cpp
index ece5ea3..c25699c 100644
--- a/pgadmin/dlg/dlgProperty.cpp
+++ b/pgadmin/dlg/dlgProperty.cpp
@@ -1012,11 +1012,11 @@ void dlgProperty::InitDialog(frmMain *frame, pgObject *node)
case PGM_FOREIGNKEY:
case PGM_INDEX:
case PGM_PRIMARYKEY:
- case PGM_TRIGGER:
case PGM_UNIQUE:
owneritem=node->GetTable()->GetId();
break;
+ case PGM_TRIGGER:
case PGM_RULE: // Rules are technically table objects! Yeuch
case EDB_PACKAGEFUNCTION:
case EDB_PACKAGEVARIABLE:
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..5412473 100644
--- a/pgadmin/include/schema/pgTrigger.h
+++ b/pgadmin/include/schema/pgTrigger.h
@@ -16,7 +16,22 @@
class pgFunction;
-class pgTriggerFactory : public pgTableObjFactory
+class pgTriggerObject : public pgSchemaObject
+{
+public:
+ pgTriggerObject(pgSchema *newSchema, pgaFactory &factory, const wxString& newName=wxEmptyString) : pgSchemaObject(newSchema, factory, newName) {}
+
+ wxString GetFormattedDefinition();
+ wxString GetDefinition() const { return definition; }
+ void iSetDefinition(const wxString& s) { definition=s; }
+
+protected:
+ wxString definition;
+};
+
+
+
+class pgTriggerFactory : public pgSchemaObjFactory
{
public:
pgTriggerFactory();
@@ -26,10 +41,10 @@ public:
extern pgTriggerFactory triggerFactory;
-class pgTrigger : public pgTableObject
+class pgTrigger : public pgTriggerObject
{
public:
- pgTrigger(pgTable *newTable, const wxString& newName = wxT(""));
+ pgTrigger(pgSchema *newSchema, const wxString& newName = wxT(""));
~pgTrigger();
wxString GetTranslatedMessage(int kindOfMessage) const;
@@ -64,6 +79,8 @@ public:
wxArrayString GetColumnList() const { return columnList; }
long GetColumnCount() const { return columnCount; }
void iSetColumnCount(const long l) { columnCount=l; }
+ void iSetParentIsTable(const bool b) { parentistable=b; }
+ bool GetParentIsTable() { return parentistable; }
void SetDirty();
@@ -87,12 +104,12 @@ private:
long columnCount;
OID functionOid;
long triggerType;
- bool enabled;
+ bool enabled, parentistable;
pgFunction *triggerFunction;
};
-class pgTriggerCollection : public pgTableObjCollection
+class pgTriggerCollection : public pgSchemaObjCollection
{
public:
pgTriggerCollection(pgaFactory *factory, pgSchema *sch);
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/pgObject.cpp b/pgadmin/schema/pgObject.cpp
index 314a2e8..f61aa6b 100644
--- a/pgadmin/schema/pgObject.cpp
+++ b/pgadmin/schema/pgObject.cpp
@@ -1311,7 +1311,6 @@ void pgSchemaObject::SetSchema(pgSchema *newSchema)
void pgSchemaObject::UpdateSchema(ctlTree *browser, OID schemaOid)
{
// used e.g. for triggers that use trigger functions from other namespaces
-
if (!browser)
return;
diff --git a/pgadmin/schema/pgRule.cpp b/pgadmin/schema/pgRule.cpp
index 747f869..60d7af8 100644
--- a/pgadmin/schema/pgRule.cpp
+++ b/pgadmin/schema/pgRule.cpp
@@ -200,7 +200,8 @@ pgObject *pgRuleFactory::CreateObjects(pgCollection *collection, ctlTree *browse
{
while (!rules->Eof())
{
- rule = new pgRule(collection->GetSchema(), rules->GetVal(wxT("rulename")));
+ // Be careful that the schema of a rule (and a trigger) is the schema of the schema
+ rule = new pgRule(collection->GetSchema()->GetSchema(), rules->GetVal(wxT("rulename")));
rule->iSetOid(rules->GetOid(wxT("oid")));
rule->iSetComment(rules->GetVal(wxT("description")));
diff --git a/pgadmin/schema/pgTrigger.cpp b/pgadmin/schema/pgTrigger.cpp
index 222e248..e162be0 100644
--- a/pgadmin/schema/pgTrigger.cpp
+++ b/pgadmin/schema/pgTrigger.cpp
@@ -22,8 +22,8 @@
#include "schema/pgFunction.h"
-pgTrigger::pgTrigger(pgTable *newTable, const wxString& newName)
-: pgTableObject(newTable, triggerFactory, newName)
+pgTrigger::pgTrigger(pgSchema *newSchema, const wxString& newName)
+: pgTriggerObject(newSchema, triggerFactory, newName)
{
triggerFunction=0;
}
@@ -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;
}
@@ -348,11 +356,12 @@ pgObject *pgTrigger::Refresh(ctlTree *browser, const wxTreeItemId item)
pgObject *pgTriggerFactory::CreateObjects(pgCollection *coll, ctlTree *browser, const wxString &restriction)
{
- pgTableObjCollection *collection=(pgTableObjCollection*)coll;
+ pgSchemaObjCollection *collection=(pgSchemaObjCollection*)coll;
pgTrigger *trigger=0;
wxString trig_sql;
- trig_sql = wxT("SELECT t.oid, t.xmin, t.*, relname, nspname, des.description, l.lanname, p.prosrc, \n")
+ trig_sql = wxT("SELECT t.oid, t.xmin, t.*, relname, CASE WHEN relkind = 'r' THEN TRUE ELSE FALSE END AS parentistable, ")
+ wxT(" nspname, des.description, l.lanname, p.prosrc, \n")
wxT(" trim(substring(pg_get_triggerdef(t.oid), 'WHEN (.*) EXECUTE PROCEDURE'), '()') AS whenclause\n")
wxT(" FROM pg_trigger t\n")
wxT(" JOIN pg_class cl ON cl.oid=tgrelid\n")
@@ -376,7 +385,8 @@ pgObject *pgTriggerFactory::CreateObjects(pgCollection *coll, ctlTree *browser,
{
while (!triggers->Eof())
{
- trigger = new pgTrigger(collection->GetTable(), triggers->GetVal(wxT("tgname")));
+ // Be careful that the schema of a trigger (and a rule) is the schema of the schema
+ trigger = new pgTrigger(collection->GetSchema()->GetSchema(), triggers->GetVal(wxT("tgname")));
trigger->iSetOid(triggers->GetOid(wxT("oid")));
trigger->iSetXid(triggers->GetOid(wxT("xmin")));
@@ -394,6 +404,8 @@ pgObject *pgTriggerFactory::CreateObjects(pgCollection *coll, ctlTree *browser,
trigger->iSetEnabled(triggers->GetBool(wxT("tgenabled")));
trigger->iSetTriggerType(triggers->GetLong(wxT("tgtype")));
+ trigger->iSetParentIsTable(triggers->GetBool(wxT("parentistable")));
+
trigger->iSetLanguage(triggers->GetVal(wxT("lanname")));
trigger->iSetSource(triggers->GetVal(wxT("prosrc")));
trigger->iSetQuotedFullTable(collection->GetDatabase()->GetQuotedSchemaPrefix(triggers->GetVal(wxT("nspname"))) + qtIdent(triggers->GetVal(wxT("relname"))));
@@ -472,7 +484,7 @@ wxString pgTriggerCollection::GetTranslatedMessage(int kindOfMessage) const
#include "images/triggers.xpm"
pgTriggerFactory::pgTriggerFactory()
-: pgTableObjFactory(__("Trigger"), __("New Trigger..."), __("Create a new Trigger."), trigger_xpm)
+: pgSchemaObjFactory(__("Trigger"), __("New Trigger..."), __("Create a new Trigger."), trigger_xpm)
{
metaType = PGM_TRIGGER;
}
@@ -503,7 +515,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>
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers